+1 Release Date : Sun May 14 22:49:52 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.03.01
+3 Older Version : 00.00.02.04
+
+i. Added support for ZCR controller.
+
+ New device id 0x413 added.
+
+ii. Bug fix : Disable controller interrupt before firing INIT cmd to FW.
+
+ Interrupt is enabled after required initialization is over.
+ This is done to ensure that driver is ready to handle interrupts when
+ it is generated by the controller.
+
+ -Sumant Patro <Sumant.Patro@lsil.com>
+
1 Release Date : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
2 Current Version : 00.00.02.04
3 Older Version : 00.00.02.04
}
static int
-iscsi_iser_conn_set_param(struct iscsi_cls_conn *cls_conn,
- enum iscsi_param param, uint32_t value)
+iscsi_iser_set_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, char *buf, int buflen)
{
- struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_session *session = conn->session;
-
- spin_lock_bh(&session->lock);
- if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
- conn->stop_stage != STOP_CONN_RECOVER) {
- printk(KERN_ERR "iscsi_iser: can not change parameter [%d]\n",
- param);
- spin_unlock_bh(&session->lock);
- return 0;
- }
- spin_unlock_bh(&session->lock);
+ int value;
switch (param) {
case ISCSI_PARAM_MAX_RECV_DLENGTH:
/* TBD */
break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- conn->max_xmit_dlength = value;
- break;
case ISCSI_PARAM_HDRDGST_EN:
+ sscanf(buf, "%d", &value);
if (value) {
printk(KERN_ERR "DataDigest wasn't negotiated to None");
return -EPROTO;
}
break;
case ISCSI_PARAM_DATADGST_EN:
+ sscanf(buf, "%d", &value);
if (value) {
printk(KERN_ERR "DataDigest wasn't negotiated to None");
return -EPROTO;
}
break;
- case ISCSI_PARAM_INITIAL_R2T_EN:
- session->initial_r2t_en = value;
- break;
- case ISCSI_PARAM_IMM_DATA_EN:
- session->imm_data_en = value;
- break;
- case ISCSI_PARAM_FIRST_BURST:
- session->first_burst = value;
- break;
- case ISCSI_PARAM_MAX_BURST:
- session->max_burst = value;
- break;
- case ISCSI_PARAM_PDU_INORDER_EN:
- session->pdu_inorder_en = value;
- break;
- case ISCSI_PARAM_DATASEQ_INORDER_EN:
- session->dataseq_inorder_en = value;
- break;
- case ISCSI_PARAM_ERL:
- session->erl = value;
- break;
case ISCSI_PARAM_IFMARKER_EN:
+ sscanf(buf, "%d", &value);
if (value) {
printk(KERN_ERR "IFMarker wasn't negotiated to No");
return -EPROTO;
}
break;
case ISCSI_PARAM_OFMARKER_EN:
+ sscanf(buf, "%d", &value);
if (value) {
printk(KERN_ERR "OFMarker wasn't negotiated to No");
return -EPROTO;
}
break;
default:
- break;
- }
-
- return 0;
-}
-
-static int
-iscsi_iser_session_get_param(struct iscsi_cls_session *cls_session,
- enum iscsi_param param, uint32_t *value)
-{
- struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
- struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
-
- switch (param) {
- case ISCSI_PARAM_INITIAL_R2T_EN:
- *value = session->initial_r2t_en;
- break;
- case ISCSI_PARAM_MAX_R2T:
- *value = session->max_r2t;
- break;
- case ISCSI_PARAM_IMM_DATA_EN:
- *value = session->imm_data_en;
- break;
- case ISCSI_PARAM_FIRST_BURST:
- *value = session->first_burst;
- break;
- case ISCSI_PARAM_MAX_BURST:
- *value = session->max_burst;
- break;
- case ISCSI_PARAM_PDU_INORDER_EN:
- *value = session->pdu_inorder_en;
- break;
- case ISCSI_PARAM_DATASEQ_INORDER_EN:
- *value = session->dataseq_inorder_en;
- break;
- case ISCSI_PARAM_ERL:
- *value = session->erl;
- break;
- case ISCSI_PARAM_IFMARKER_EN:
- *value = 0;
- break;
- case ISCSI_PARAM_OFMARKER_EN:
- *value = 0;
- break;
- default:
- return ISCSI_ERR_PARAM_NOT_FOUND;
- }
-
- return 0;
-}
-
-static int
-iscsi_iser_conn_get_param(struct iscsi_cls_conn *cls_conn,
- enum iscsi_param param, uint32_t *value)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
-
- switch(param) {
- case ISCSI_PARAM_MAX_RECV_DLENGTH:
- *value = conn->max_recv_dlength;
- break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- *value = conn->max_xmit_dlength;
- break;
- case ISCSI_PARAM_HDRDGST_EN:
- *value = 0;
- break;
- case ISCSI_PARAM_DATADGST_EN:
- *value = 0;
- break;
- /*case ISCSI_PARAM_TARGET_RECV_DLENGTH:
- *value = conn->target_recv_dlength;
- break;
- case ISCSI_PARAM_INITIATOR_RECV_DLENGTH:
- *value = conn->initiator_recv_dlength;
- break;*/
- default:
- return ISCSI_ERR_PARAM_NOT_FOUND;
+ return iscsi_set_param(cls_conn, param, buf, buflen);
}
return 0;
}
-
static void
iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
{
ISCSI_FIRST_BURST |
ISCSI_MAX_BURST |
ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN,
+ ISCSI_DATASEQ_INORDER_EN |
+ ISCSI_EXP_STATSN |
+ ISCSI_PERSISTENT_PORT |
+ ISCSI_PERSISTENT_ADDRESS |
+ ISCSI_TARGET_NAME |
+ ISCSI_TPGT,
.host_template = &iscsi_iser_sht,
.conndata_size = sizeof(struct iscsi_conn),
.max_lun = ISCSI_ISER_MAX_LUN,
.create_conn = iscsi_iser_conn_create,
.bind_conn = iscsi_iser_conn_bind,
.destroy_conn = iscsi_iser_conn_destroy,
- .set_param = iscsi_iser_conn_set_param,
- .get_conn_param = iscsi_iser_conn_get_param,
- .get_session_param = iscsi_iser_session_get_param,
+ .set_param = iscsi_iser_set_param,
+ .get_conn_param = iscsi_conn_get_param,
+ .get_session_param = iscsi_session_get_param,
.start_conn = iscsi_iser_conn_start,
.stop_conn = iscsi_conn_stop,
/* these are called as part of conn recovery */
# For mptfc:
#CFLAGS_mptfc.o += -DMPT_DEBUG_FC
+# For mptsas:
+#CFLAGS_mptsas.o += -DMPT_DEBUG_SAS
+#CFLAGS_mptsas.o += -DMPT_DEBUG_SAS_WIDE
+
+
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o
+++ /dev/null
-/*
- * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
- *
- * NAME: fc_log.h
- * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips
- * DESCRIPTION: Contains the enumerated list of values that may be returned
- * in the IOCLogInfo field of a MPI Default Reply Message.
- *
- * CREATION DATE: 6/02/2000
- * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
- */
-
-
-/*
- * MpiIocLogInfo_t enum
- *
- * These 32 bit values are used in the IOCLogInfo field of the MPI reply
- * messages.
- * The value is 0xabcccccc where
- * a = The type of log info as per the MPI spec. Since these codes are
- * all for Fibre Channel this value will always be 2.
- * b = Specifies a subclass of the firmware where
- * 0 = FCP Initiator
- * 1 = FCP Target
- * 2 = LAN
- * 3 = MPI Message Layer
- * 4 = FC Link
- * 5 = Context Manager
- * 6 = Invalid Field Offset
- * 7 = State Change Info
- * all others are reserved for future use
- * c = A specific value within the subclass.
- *
- * NOTE: Any new values should be added to the end of each subclass so that the
- * codes remain consistent across firmware releases.
- */
-typedef enum _MpiIocLogInfoFc
-{
- MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000,
- MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
- MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
- MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
- MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */
- MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */
- MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */
- MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */
- MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */
- MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */
- MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */
- MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */
-
- MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000,
- MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
- MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */
- MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
- MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
- MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */
- MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
- MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */
- MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */
- MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */
- MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */
- MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */
- MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */
- MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */
- MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */
-
- MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000,
- MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */
- MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */
- MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */
- MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */
-
- MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000,
-
- MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000,
- MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */
- MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */
- MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
- MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */
-
- MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000,
-
- 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 */
- MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff,
-
- MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */
-
-} MpiIocLogInfoFc_t;
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.10
+ * mpi.h Version: 01.05.11
*
* Version History
* ---------------
* Added EEDP IOCStatus codes.
* 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
* 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
+ * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x0C)
+#define MPI_HEADER_VERSION_UNIT (0x0D)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.11
+ * mpi_cnfg.h Version: 01.05.12
*
* Version History
* ---------------
* Added postpone SATA Init bit to SAS IO Unit Page 1
* ControlFlags.
* Changed LogEntry format for Log Page 0.
+ * 03-27-06 01.05.12 Added two new Flags defines for Manufacturing Page 4.
+ * Added Manufacturing Page 7.
+ * Added MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING.
+ * Added IOC Page 6.
+ * Added PrevBootDeviceForm field to CONFIG_PAGE_BIOS_2.
+ * Added MaxLBAHigh field to RAID Volume Page 0.
+ * Added Nvdata version fields to SAS IO Unit Page 0.
+ * Added AdditionalControlFlags, MaxTargetPortConnectTime,
+ * ReportDeviceMissingDelay, and IODeviceMissingDelay
+ * fields to SAS IO Unit Page 1.
* --------------------------------------------------------------------------
*/
} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
-#define MPI_MANUFACTURING4_PAGEVERSION (0x03)
+#define MPI_MANUFACTURING4_PAGEVERSION (0x04)
/* defines for the Flags field */
+#define MPI_MANPAGE4_FORCE_BAD_BLOCK_TABLE (0x80)
+#define MPI_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x40)
#define MPI_MANPAGE4_IME_DISABLE (0x20)
#define MPI_MANPAGE4_IM_DISABLE (0x10)
#define MPI_MANPAGE4_IS_DISABLE (0x08)
#define MPI_MANUFACTURING6_PAGEVERSION (0x00)
+typedef struct _MPI_MANPAGE7_CONNECTOR_INFO
+{
+ U32 Pinout; /* 00h */
+ U8 Connector[16]; /* 04h */
+ U8 Location; /* 14h */
+ U8 Reserved1; /* 15h */
+ U16 Slot; /* 16h */
+ U32 Reserved2; /* 18h */
+} MPI_MANPAGE7_CONNECTOR_INFO, MPI_POINTER PTR_MPI_MANPAGE7_CONNECTOR_INFO,
+ MpiManPage7ConnectorInfo_t, MPI_POINTER pMpiManPage7ConnectorInfo_t;
+
+/* defines for the Pinout field */
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000)
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000)
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000)
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100)
+#define MPI_MANPAGE7_PINOUT_SFF_8482 (0x00000002)
+#define MPI_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001)
+
+/* defines for the Location field */
+#define MPI_MANPAGE7_LOCATION_UNKNOWN (0x01)
+#define MPI_MANPAGE7_LOCATION_INTERNAL (0x02)
+#define MPI_MANPAGE7_LOCATION_EXTERNAL (0x04)
+#define MPI_MANPAGE7_LOCATION_SWITCHABLE (0x08)
+#define MPI_MANPAGE7_LOCATION_AUTO (0x10)
+#define MPI_MANPAGE7_LOCATION_NOT_PRESENT (0x20)
+#define MPI_MANPAGE7_LOCATION_NOT_CONNECTED (0x80)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumPhys at runtime.
+ */
+#ifndef MPI_MANPAGE7_CONNECTOR_INFO_MAX
+#define MPI_MANPAGE7_CONNECTOR_INFO_MAX (1)
+#endif
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_7
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 Reserved1; /* 04h */
+ U32 Reserved2; /* 08h */
+ U32 Flags; /* 0Ch */
+ U8 EnclosureName[16]; /* 10h */
+ U8 NumPhys; /* 20h */
+ U8 Reserved3; /* 21h */
+ U16 Reserved4; /* 22h */
+ MPI_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI_MANPAGE7_CONNECTOR_INFO_MAX]; /* 24h */
+} CONFIG_PAGE_MANUFACTURING_7, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_7,
+ ManufacturingPage7_t, MPI_POINTER pManufacturingPage7_t;
+
+#define MPI_MANUFACTURING7_PAGEVERSION (0x00)
+
+/* defines for the Flags field */
+#define MPI_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
+
+
/****************************************************************************
* IO Unit Config Pages
****************************************************************************/
} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
IOCPage2_t, MPI_POINTER pIOCPage2_t;
-#define MPI_IOCPAGE2_PAGEVERSION (0x03)
+#define MPI_IOCPAGE2_PAGEVERSION (0x04)
/* IOC Page 2 Capabilities flags */
#define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT (0x00000010)
#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT (0x00000020)
#define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT (0x00000040)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING (0x10000000)
#define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT (0x20000000)
#define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT (0x40000000)
#define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT (0x80000000)
#define MPI_IOCPAGE5_PAGEVERSION (0x00)
+typedef struct _CONFIG_PAGE_IOC_6
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 CapabilitiesFlags; /* 04h */
+ U8 MaxDrivesIS; /* 08h */
+ U8 MaxDrivesIM; /* 09h */
+ U8 MaxDrivesIME; /* 0Ah */
+ U8 Reserved1; /* 0Bh */
+ U8 MinDrivesIS; /* 0Ch */
+ U8 MinDrivesIM; /* 0Dh */
+ U8 MinDrivesIME; /* 0Eh */
+ U8 Reserved2; /* 0Fh */
+ U8 MaxGlobalHotSpares; /* 10h */
+ U8 Reserved3; /* 11h */
+ U16 Reserved4; /* 12h */
+ U32 Reserved5; /* 14h */
+ U32 SupportedStripeSizeMapIS; /* 18h */
+ U32 SupportedStripeSizeMapIME; /* 1Ch */
+ U32 Reserved6; /* 20h */
+ U8 MetadataSize; /* 24h */
+ U8 Reserved7; /* 25h */
+ U16 Reserved8; /* 26h */
+ U16 MaxBadBlockTableEntries; /* 28h */
+ U16 Reserved9; /* 2Ah */
+ U16 IRNvsramUsage; /* 2Ch */
+ U16 Reserved10; /* 2Eh */
+ U32 IRNvsramVersion; /* 30h */
+ U32 Reserved11; /* 34h */
+ U32 Reserved12; /* 38h */
+} CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6,
+ IOCPage6_t, MPI_POINTER pIOCPage6_t;
+
+#define MPI_IOCPAGE6_PAGEVERSION (0x00)
+
+/* IOC Page 6 Capabilities Flags */
+
+#define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001)
+
/****************************************************************************
* BIOS Config Pages
U32 Reserved5; /* 14h */
U32 Reserved6; /* 18h */
U8 BootDeviceForm; /* 1Ch */
- U8 Reserved7; /* 1Dh */
+ U8 PrevBootDeviceForm; /* 1Ch */
U16 Reserved8; /* 1Eh */
MPI_BIOSPAGE2_BOOT_DEVICE BootDevice; /* 20h */
} CONFIG_PAGE_BIOS_2, MPI_POINTER PTR_CONFIG_PAGE_BIOS_2,
BIOSPage2_t, MPI_POINTER pBIOSPage2_t;
-#define MPI_BIOSPAGE2_PAGEVERSION (0x01)
+#define MPI_BIOSPAGE2_PAGEVERSION (0x02)
#define MPI_BIOSPAGE2_FORM_MASK (0x0F)
#define MPI_BIOSPAGE2_FORM_ADAPTER_ORDER (0x00)
RAID_VOL0_STATUS VolumeStatus; /* 08h */
RAID_VOL0_SETTINGS VolumeSettings; /* 0Ch */
U32 MaxLBA; /* 10h */
- U32 Reserved1; /* 14h */
+ U32 MaxLBAHigh; /* 14h */
U32 StripeSize; /* 18h */
U32 Reserved2; /* 1Ch */
U32 Reserved3; /* 20h */
} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
-#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x05)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x06)
/* values for RAID Volume Page 0 InactiveStatus field */
#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ U16 NvdataVersionDefault; /* 08h */
+ U16 NvdataVersionPersistent; /* 0Ah */
U8 NumPhys; /* 0Ch */
U8 Reserved2; /* 0Dh */
U16 Reserved3; /* 0Eh */
} CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
-#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x03)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x04)
/* values for SAS IO Unit Page 0 PortFlags */
#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08)
typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
{
- U8 Port; /* 00h */
- U8 PortFlags; /* 01h */
- U8 PhyFlags; /* 02h */
- U8 MaxMinLinkRate; /* 03h */
- U32 ControllerPhyDeviceInfo;/* 04h */
- U32 Reserved1; /* 08h */
+ U8 Port; /* 00h */
+ U8 PortFlags; /* 01h */
+ U8 PhyFlags; /* 02h */
+ U8 MaxMinLinkRate; /* 03h */
+ U32 ControllerPhyDeviceInfo; /* 04h */
+ U16 MaxTargetPortConnectTime; /* 08h */
+ U16 Reserved1; /* 0Ah */
} MPI_SAS_IO_UNIT1_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT1_PHY_DATA,
SasIOUnit1PhyData, MPI_POINTER pSasIOUnit1PhyData;
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U16 ControlFlags; /* 08h */
U16 MaxNumSATATargets; /* 0Ah */
- U32 Reserved1; /* 0Ch */
+ U16 AdditionalControlFlags; /* 0Ch */
+ U16 Reserved1; /* 0Eh */
U8 NumPhys; /* 10h */
U8 SATAMaxQDepth; /* 11h */
- U16 Reserved2; /* 12h */
+ U8 ReportDeviceMissingDelay; /* 12h */
+ U8 IODeviceMissingDelay; /* 13h */
MPI_SAS_IO_UNIT1_PHY_DATA PhyData[MPI_SAS_IOUNIT1_PHY_MAX]; /* 14h */
} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
-#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x06)
/* values for SAS IO Unit Page 1 ControlFlags */
#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
+/* values for SAS IO Unit Page 1 AdditionalControlFlags */
+#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
+
+/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
+#define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F)
+#define MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16 (0x80)
+
/* values for SAS IO Unit Page 1 PortFlags */
#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.12
- Header Set Release Date: 08-30-05
+ Header Set Release Version: 01.05.13
+ Header Set Release Date: 03-27-06
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.05.10 01.05.09
- mpi_ioc.h 01.05.10 01.05.09
- mpi_cnfg.h 01.05.11 01.05.10
- mpi_init.h 01.05.06 01.05.06
- mpi_targ.h 01.05.05 01.05.05
+ mpi.h 01.05.11 01.05.10
+ mpi_ioc.h 01.05.11 01.05.10
+ mpi_cnfg.h 01.05.12 01.05.11
+ mpi_init.h 01.05.07 01.05.06
+ mpi_targ.h 01.05.06 01.05.05
mpi_fc.h 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01
mpi_raid.h 01.05.02 01.05.02
mpi_tool.h 01.05.03 01.05.03
mpi_inb.h 01.05.01 01.05.01
- mpi_sas.h 01.05.02 01.05.01
- mpi_type.h 01.05.02 01.05.01
- mpi_history.txt 01.05.12 01.05.11
+ mpi_sas.h 01.05.03 01.05.02
+ mpi_type.h 01.05.02 01.05.02
+ mpi_history.txt 01.05.13 01.05.12
* Date Version Description
* Added EEDP IOCStatus codes.
* 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
* 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
+ * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
mpi_ioc.h
* Added new ReasonCode value for SAS Device Status Change
* event.
* Added new family code for FC949E.
+ * 03-27-06 01.05.11 Added MPI_IOCFACTS_CAPABILITY_TLR.
+ * Added additional Reason Codes and more event data fields
+ * to EVENT_DATA_SAS_DEVICE_STATUS_CHANGE.
+ * Added EVENT_DATA_SAS_BROADCAST_PRIMITIVE structure and
+ * new event.
+ * Added MPI_EVENT_SAS_SMP_ERROR and event data structure.
+ * Added MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE and event
+ * data structure.
+ * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
+ * data structure.
+ * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
* --------------------------------------------------------------------------
mpi_cnfg.h
* Added postpone SATA Init bit to SAS IO Unit Page 1
* ControlFlags.
* Changed LogEntry format for Log Page 0.
+ * 03-27-06 01.05.12 Added two new Flags defines for Manufacturing Page 4.
+ * Added Manufacturing Page 7.
+ * Added MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING.
+ * Added IOC Page 6.
+ * Added PrevBootDeviceForm field to CONFIG_PAGE_BIOS_2.
+ * Added MaxLBAHigh field to RAID Volume Page 0.
+ * Added Nvdata version fields to SAS IO Unit Page 0.
+ * Added AdditionalControlFlags, MaxTargetPortConnectTime,
+ * ReportDeviceMissingDelay, and IODeviceMissingDelay
+ * fields to SAS IO Unit Page 1.
* --------------------------------------------------------------------------
mpi_init.h
* Added four new defines for SEP SlotStatus.
* 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
* unique in the first 32 characters.
+ * 03-27-06 01.05.07 Added Task Management type of Clear ACA.
* --------------------------------------------------------------------------
mpi_targ.h
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
* 06-24-05 01.05.05 Added TargetAssistExtended structures and defines.
+ * 03-27-06 01.05.06 Added a comment.
* --------------------------------------------------------------------------
mpi_fc.h
* 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
* Added PrimFlags and Primitive field to SAS IO Unit
* Control request, and added a new operation code.
+ * 03-27-06 01.05.03 Added Force Full Discovery, Transmit Port Select Signal,
+ * and Remove Device operations to SAS IO Unit Control.
+ * Added DevHandle field to SAS IO Unit Control request and
+ * reply.
* --------------------------------------------------------------------------
mpi_type.h
mpi_history.txt Parts list history
-Filename 01.05.12 01.05.11 01.05.10 01.05.09
----------- -------- -------- -------- --------
-mpi.h 01.05.10 01.05.09 01.05.08 01.05.07
-mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08
-mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08
-mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04
-mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04
-mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01
-mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01
-mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02
-mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03
-mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01
-mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01
-mpi_type.h 01.05.02 01.05.01 01.05.01 01.05.01
+Filename 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09
+---------- -------- -------- -------- -------- --------
+mpi.h 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07
+mpi_ioc.h 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08
+mpi_cnfg.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08
+mpi_init.h 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04
+mpi_targ.h 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01
+mpi_type.h 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01
Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
---------- -------- -------- -------- -------- -------- --------
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
- * mpi_init.h Version: 01.05.06
+ * mpi_init.h Version: 01.05.07
*
* Version History
* ---------------
* Added four new defines for SEP SlotStatus.
* 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
* unique in the first 32 characters.
+ * 03-27-06 01.05.07 Added Task Management type of Clear ACA.
* --------------------------------------------------------------------------
*/
#define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
+#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08)
/* MsgFlags bits */
#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00)
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.10
+ * mpi_ioc.h Version: 01.05.11
*
* Version History
* ---------------
* Added new ReasonCode value for SAS Device Status Change
* event.
* Added new family code for FC949E.
+ * 03-27-06 01.05.11 Added MPI_IOCFACTS_CAPABILITY_TLR.
+ * Added additional Reason Codes and more event data fields
+ * to EVENT_DATA_SAS_DEVICE_STATUS_CHANGE.
+ * Added EVENT_DATA_SAS_BROADCAST_PRIMITIVE structure and
+ * new event.
+ * Added MPI_EVENT_SAS_SMP_ERROR and event data structure.
+ * Added MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE and event
+ * data structure.
+ * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
+ * data structure.
+ * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
* --------------------------------------------------------------------------
*/
#define MPI_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
#define MPI_IOCFACTS_CAPABILITY_SCSIIO32 (0x00000200)
#define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16 (0x00000400)
+#define MPI_IOCFACTS_CAPABILITY_TLR (0x00000800)
/*****************************************************************************
/* Event */
-#define MPI_EVENT_NONE (0x00000000)
-#define MPI_EVENT_LOG_DATA (0x00000001)
-#define MPI_EVENT_STATE_CHANGE (0x00000002)
-#define MPI_EVENT_UNIT_ATTENTION (0x00000003)
-#define MPI_EVENT_IOC_BUS_RESET (0x00000004)
-#define MPI_EVENT_EXT_BUS_RESET (0x00000005)
-#define MPI_EVENT_RESCAN (0x00000006)
-#define MPI_EVENT_LINK_STATUS_CHANGE (0x00000007)
-#define MPI_EVENT_LOOP_STATE_CHANGE (0x00000008)
-#define MPI_EVENT_LOGOUT (0x00000009)
-#define MPI_EVENT_EVENT_CHANGE (0x0000000A)
-#define MPI_EVENT_INTEGRATED_RAID (0x0000000B)
-#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C)
-#define MPI_EVENT_ON_BUS_TIMER_EXPIRED (0x0000000D)
-#define MPI_EVENT_QUEUE_FULL (0x0000000E)
-#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F)
-#define MPI_EVENT_SAS_SES (0x00000010)
-#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
-#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
-#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
-#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
-#define MPI_EVENT_IR2 (0x00000015)
-#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
-#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
+#define MPI_EVENT_NONE (0x00000000)
+#define MPI_EVENT_LOG_DATA (0x00000001)
+#define MPI_EVENT_STATE_CHANGE (0x00000002)
+#define MPI_EVENT_UNIT_ATTENTION (0x00000003)
+#define MPI_EVENT_IOC_BUS_RESET (0x00000004)
+#define MPI_EVENT_EXT_BUS_RESET (0x00000005)
+#define MPI_EVENT_RESCAN (0x00000006)
+#define MPI_EVENT_LINK_STATUS_CHANGE (0x00000007)
+#define MPI_EVENT_LOOP_STATE_CHANGE (0x00000008)
+#define MPI_EVENT_LOGOUT (0x00000009)
+#define MPI_EVENT_EVENT_CHANGE (0x0000000A)
+#define MPI_EVENT_INTEGRATED_RAID (0x0000000B)
+#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C)
+#define MPI_EVENT_ON_BUS_TIMER_EXPIRED (0x0000000D)
+#define MPI_EVENT_QUEUE_FULL (0x0000000E)
+#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F)
+#define MPI_EVENT_SAS_SES (0x00000010)
+#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
+#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
+#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
+#define MPI_EVENT_IR2 (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
+#define MPI_EVENT_SAS_BROADCAST_PRIMITIVE (0x00000017)
+#define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018)
+#define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW (0x00000019)
+#define MPI_EVENT_SAS_SMP_ERROR (0x0000001A)
+#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
/* AckRequired field values */
U8 PhyNum; /* 0Eh */
U8 Reserved1; /* 0Fh */
U64 SASAddress; /* 10h */
+ U8 LUN[8]; /* 18h */
+ U16 TaskTag; /* 20h */
+ U16 Reserved2; /* 22h */
} EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
MpiEventDataSasDeviceStatusChange_t,
MPI_POINTER pMpiEventDataSasDeviceStatusChange_t;
/* MPI SAS Device Status Change Event data ReasonCode values */
-#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED (0x03)
-#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING (0x04)
-#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
-#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
-#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
-#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
+#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED (0x03)
+#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING (0x04)
+#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
+#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
+#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
+#define MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
+#define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
+#define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
+#define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
/* SCSI Event data for Queue Full event */
} EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES,
MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t;
+/* SAS Broadcast Primitive Event data */
+
+typedef struct _EVENT_DATA_SAS_BROADCAST_PRIMITIVE
+{
+ U8 PhyNum; /* 00h */
+ U8 Port; /* 01h */
+ U8 PortWidth; /* 02h */
+ U8 Primitive; /* 04h */
+} EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+ MPI_POINTER PTR_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+ MpiEventDataSasBroadcastPrimitive_t,
+ MPI_POINTER pMpiEventDataSasBroadcastPrimitive_t;
+
+#define MPI_EVENT_PRIMITIVE_CHANGE (0x01)
+#define MPI_EVENT_PRIMITIVE_EXPANDER (0x03)
+#define MPI_EVENT_PRIMITIVE_RESERVED2 (0x04)
+#define MPI_EVENT_PRIMITIVE_RESERVED3 (0x05)
+#define MPI_EVENT_PRIMITIVE_RESERVED4 (0x06)
+#define MPI_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07)
+#define MPI_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08)
+
/* SAS Phy Link Status Event data */
typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800)
#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000)
+/* SAS SMP Error Event data */
+
+typedef struct _EVENT_DATA_SAS_SMP_ERROR
+{
+ U8 Status; /* 00h */
+ U8 Port; /* 01h */
+ U8 SMPFunctionResult; /* 02h */
+ U8 Reserved1; /* 03h */
+ U64 SASAddress; /* 04h */
+} EVENT_DATA_SAS_SMP_ERROR, MPI_POINTER PTR_EVENT_DATA_SAS_SMP_ERROR,
+ MpiEventDataSasSmpError_t, MPI_POINTER pMpiEventDataSasSmpError_t;
+
+/* defines for the Status field of the SAS SMP Error event */
+#define MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID (0x00)
+#define MPI_EVENT_SAS_SMP_CRC_ERROR (0x01)
+#define MPI_EVENT_SAS_SMP_TIMEOUT (0x02)
+#define MPI_EVENT_SAS_SMP_NO_DESTINATION (0x03)
+#define MPI_EVENT_SAS_SMP_BAD_DESTINATION (0x04)
+
+/* SAS Initiator Device Status Change Event data */
+
+typedef struct _EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
+{
+ U8 ReasonCode; /* 00h */
+ U8 Port; /* 01h */
+ U16 DevHandle; /* 02h */
+ U64 SASAddress; /* 04h */
+} EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+ MPI_POINTER PTR_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+ MpiEventDataSasInitDevStatusChange_t,
+ MPI_POINTER pMpiEventDataSasInitDevStatusChange_t;
+
+/* defines for the ReasonCode field of the SAS Initiator Device Status Change event */
+#define MPI_EVENT_SAS_INIT_RC_ADDED (0x01)
+
+/* SAS Initiator Device Table Overflow Event data */
+
+typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
+{
+ U8 MaxInit; /* 00h */
+ U8 CurrentInit; /* 01h */
+ U16 Reserved1; /* 02h */
+} EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+ MPI_POINTER PTR_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+ MpiEventDataSasInitTableOverflow_t,
+ MPI_POINTER pMpiEventDataSasInitTableOverflow_t;
+
/*****************************************************************************
*
#define MPI_EXT_IMAGE_TYPE_FW (0x01)
#define MPI_EXT_IMAGE_TYPE_NVDATA (0x03)
#define MPI_EXT_IMAGE_TYPE_BOOTLOADER (0x04)
+#define MPI_EXT_IMAGE_TYPE_INITIALIZATION (0x05)
#endif
#ifndef IOPI_IOCLOGINFO_H_INCLUDED
#define IOPI_IOCLOGINFO_H_INCLUDED
+#define SAS_LOGINFO_NEXUS_LOSS 0x31170000
+#define SAS_LOGINFO_MASK 0xFFFF0000
/****************************************************************************/
/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */
#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */
#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */
#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
+
+#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */
+
#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)
#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */
#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000)
#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000)
+#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000)
#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101)
#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */
/****************************************************************************/
/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */
/****************************************************************************/
-#define IR_LOGINFO_CODE_UNUSED1 (0x00010000)
-#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)
+#define IR_LOGINFO_RAID_ACTION_ERROR (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)
+
+/* Amount of information passed down for Create Volume is too large */
+#define IR_LOGINFO_VOLUME_CREATE_INVALID_LENGTH (0x00010001)
+/* Creation of duplicate volume attempted (Bus/Target ID checked) */
+#define IR_LOGINFO_VOLUME_CREATE_DUPLICATE (0x00010002)
+/* Creation failed due to maximum number of supported volumes exceeded */
+#define IR_LOGINFO_VOLUME_CREATE_NO_SLOTS (0x00010003)
+/* Creation failed due to DMA error in trying to read from host */
+#define IR_LOGINFO_VOLUME_CREATE_DMA_ERROR (0x00010004)
+/* Creation failed due to invalid volume type passed down */
+#define IR_LOGINFO_VOLUME_CREATE_INVALID_VOLUME_TYPE (0x00010005)
+/* Creation failed due to error reading MFG Page 4 */
+#define IR_LOGINFO_VOLUME_MFG_PAGE4_ERROR (0x00010006)
+/* Creation failed when trying to create internal structures */
+#define IR_LOGINFO_VOLUME_INTERNAL_CONFIG_STRUCTURE_ERROR (0x00010007)
+
+/* Activation failed due to trying to activate an already active volume */
+#define IR_LOGINFO_VOLUME_ACTIVATING_AN_ACTIVE_VOLUME (0x00010010)
+/* Activation failed due to trying to active unsupported volume type */
+#define IR_LOGINFO_VOLUME_ACTIVATING_INVALID_VOLUME_TYPE (0x00010011)
+/* Activation failed due to trying to active too many volumes */
+#define IR_LOGINFO_VOLUME_ACTIVATING_TOO_MANY_VOLUMES (0x00010012)
+/* Activation failed due to Volume ID in use already */
+#define IR_LOGINFO_VOLUME_ACTIVATING_VOLUME_ID_IN_USE (0x00010013)
+/* Activation failed call to activateVolume returned failure */
+#define IR_LOGINFO_VOLUME_ACTIVATE_VOLUME_FAILED (0x00010014)
+/* Activation failed trying to import the volume */
+#define IR_LOGINFO_VOLUME_ACTIVATING_IMPORT_VOLUME_FAILED (0x00010015)
+
+/* Phys Disk failed, too many phys disks */
+#define IR_LOGINFO_PHYSDISK_CREATE_TOO_MANY_DISKS (0x00010020)
+/* Amount of information passed down for Create Pnysdisk is too large */
+#define IR_LOGINFO_PHYSDISK_CREATE_INVALID_LENGTH (0x00010021)
+/* Creation failed due to DMA error in trying to read from host */
+#define IR_LOGINFO_PHYSDISK_CREATE_DMA_ERROR (0x00010022)
+/* Creation failed due to invalid Bus TargetID passed down */
+#define IR_LOGINFO_PHYSDISK_CREATE_BUS_TID_INVALID (0x00010023)
+/* Creation failed due to error in creating RAID Phys Disk Config Page */
+#define IR_LOGINFO_PHYSDISK_CREATE_CONFIG_PAGE_ERROR (0x00010024)
+
+
+/* Compatibility Error : IR Disabled */
+#define IR_LOGINFO_COMPAT_ERROR_RAID_DISABLED (0x00010030)
+/* Compatibility Error : Inquiry Comand failed */
+#define IR_LOGINFO_COMPAT_ERROR_INQUIRY_FAILED (0x00010031)
+/* Compatibility Error : Device not direct access device */
+#define IR_LOGINFO_COMPAT_ERROR_NOT_DIRECT_ACCESS (0x00010032)
+/* Compatibility Error : Removable device found */
+#define IR_LOGINFO_COMPAT_ERROR_REMOVABLE_FOUND (0x00010033)
+/* Compatibility Error : Device SCSI Version not 2 or higher */
+#define IR_LOGINFO_COMPAT_ERROR_NEED_SCSI_2_OR_HIGHER (0x00010034)
+/* Compatibility Error : SATA device, 48 BIT LBA not supported */
+#define IR_LOGINFO_COMPAT_ERROR_SATA_48BIT_LBA_NOT_SUPPORTED (0x00010035)
+/* Compatibility Error : Device does not have 512 byte block sizes */
+#define IR_LOGINFO_COMPAT_ERROR_DEVICE_NOT_512_BYTE_BLOCK (0x00010036)
+/* Compatibility Error : Volume Type check failed */
+#define IR_LOGINFO_COMPAT_ERROR_VOLUME_TYPE_CHECK_FAILED (0x00010037)
+/* Compatibility Error : Volume Type is unsupported by FW */
+#define IR_LOGINFO_COMPAT_ERROR_UNSUPPORTED_VOLUME_TYPE (0x00010038)
+/* Compatibility Error : Disk drive too small for use in volume */
+#define IR_LOGINFO_COMPAT_ERROR_DISK_TOO_SMALL (0x00010039)
+/* Compatibility Error : Phys disk for Create Volume not found */
+#define IR_LOGINFO_COMPAT_ERROR_PHYS_DISK_NOT_FOUND (0x0001003A)
+/* Compatibility Error : membership count error, too many or too few disks for volume type */
+#define IR_LOGINFO_COMPAT_ERROR_MEMBERSHIP_COUNT (0x0001003B)
+/* Compatibility Error : Disk stripe sizes must be 64KB */
+#define IR_LOGINFO_COMPAT_ERROR_NON_64K_STRIPE_SIZE (0x0001003C)
+/* Compatibility Error : IME size limited to < 2TB */
+#define IR_LOGINFO_COMPAT_ERROR_IME_VOL_NOT_CURRENTLY_SUPPORTED (0x0001003D)
+
/****************************************************************************/
-/* Defines for convienence */
+/* Defines for convenience */
/****************************************************************************/
#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.02
+ * mpi_sas.h Version: 01.05.03
*
* Version History
* ---------------
* 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
* Added PrimFlags and Primitive field to SAS IO Unit
* Control request, and added a new operation code.
+ * 03-27-06 01.05.03 Added Force Full Discovery, Transmit Port Select Signal,
+ * and Remove Device operations to SAS IO Unit Control.
+ * Added DevHandle field to SAS IO Unit Control request and
+ * reply.
* --------------------------------------------------------------------------
*/
U8 Reserved1; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
- U16 Reserved2; /* 04h */
+ U16 DevHandle; /* 04h */
U8 Reserved3; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
#define MPI_SAS_OP_MAP_CURRENT (0x09)
#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)
+#define MPI_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
+#define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
+#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D)
/* values for the PrimFlags field */
#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
U8 Reserved1; /* 01h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
- U16 Reserved2; /* 04h */
+ U16 DevHandle; /* 04h */
U8 Reserved3; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
* Title: MPI Target mode messages and structures
* Creation Date: June 22, 2000
*
- * mpi_targ.h Version: 01.05.05
+ * mpi_targ.h Version: 01.05.06
*
* Version History
* ---------------
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
* 06-24-05 01.05.05 Added TargetAssistExtended structures and defines.
+ * 03-27-06 01.05.06 Added a comment.
* --------------------------------------------------------------------------
*/
#define TARGET_ASSIST_FLAGS_CONFIRMED (0x08)
#define TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER (0x80)
-
+/* Standard Target Mode Reply message */
typedef struct _MSG_TARGET_ERROR_REPLY
{
U16 Reserved; /* 00h */
mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
{
MPT_ADAPTER *ioc = bus_id;
- u32 pa;
+ u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
+
+ if (pa == 0xFFFFFFFF)
+ return IRQ_NONE;
/*
* Drain the reply FIFO!
*/
- while (1) {
- pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
- if (pa == 0xFFFFFFFF)
- return IRQ_HANDLED;
- else if (pa & MPI_ADDRESS_REPLY_A_BIT)
+ do {
+ if (pa & MPI_ADDRESS_REPLY_A_BIT)
mpt_reply(ioc, pa);
else
mpt_turbo_reply(ioc, pa);
- }
+ pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
+ } while (pa != 0xFFFFFFFF);
return IRQ_HANDLED;
}
port = psize = 0;
for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
+ if (psize)
+ continue;
/* Get I/O space! */
port = pci_resource_start(pdev, ii);
psize = pci_resource_len(pdev,ii);
} else {
+ if (msize)
+ continue;
/* Get memmap */
mem_phys = pci_resource_start(pdev, ii);
msize = pci_resource_len(pdev,ii);
- break;
}
}
ioc->mem_size = msize;
- if (ii == DEVICE_COUNT_RESOURCE) {
- printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
- kfree(ioc);
- return -EINVAL;
- }
-
- dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
- dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
-
mem = NULL;
/* Get logical ptr for PciMem0 space */
/*mem = ioremap(mem_phys, msize);*/
- mem = ioremap(mem_phys, 0x100);
+ mem = ioremap(mem_phys, msize);
if (mem == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
kfree(ioc);
ioc->bus_type = SAS;
ioc->errata_flag_1064 = 1;
}
- else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
- ioc->prod_name = "LSISAS1066";
- ioc->bus_type = SAS;
- ioc->errata_flag_1064 = 1;
- }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
ioc->prod_name = "LSISAS1068";
ioc->bus_type = SAS;
ioc->prod_name = "LSISAS1064E";
ioc->bus_type = SAS;
}
- else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
- ioc->prod_name = "LSISAS1066E";
- ioc->bus_type = SAS;
- }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
ioc->prod_name = "LSISAS1068E";
ioc->bus_type = SAS;
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
+ ioc->prod_name = "LSISAS1078";
+ ioc->bus_type = SAS;
+ }
if (ioc->errata_flag_1064)
pci_disable_io_access(pdev);
u32 diag1val = 0;
#endif
+ if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
+ drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
+ "address=%p\n", ioc->name, __FUNCTION__,
+ &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
+ CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
+ if (sleepFlag == CAN_SLEEP)
+ msleep(1);
+ else
+ mdelay(1);
+
+ for (count = 0; count < 60; count ++) {
+ doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+ doorbell &= MPI_IOC_STATE_MASK;
+
+ drsprintk((MYIOC_s_INFO_FMT
+ "looking for READY STATE: doorbell=%x"
+ " count=%d\n",
+ ioc->name, doorbell, count));
+ if (doorbell == MPI_IOC_STATE_READY) {
+ return 0;
+ }
+
+ /* wait 1 sec */
+ if (sleepFlag == CAN_SLEEP)
+ msleep(1000);
+ else
+ mdelay(1000);
+ }
+ return -1;
+ }
+
/* Clear any existing interrupts */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.10"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.10"
+#define MPT_LINUX_VERSION_COMMON "3.04.00"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.00"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
u32 HostIndex; /* 50 Host Index register */
u32 Reserved4[15]; /* 54-8F */
u32 Fubar; /* 90 For Fubar usage */
- u32 Reserved5[27]; /* 94-FF */
+ u32 Reserved5[1050];/* 94-10F8 */
+ u32 Reset_1078; /* 10FC Reset 1078 */
} SYSIF_REGS;
/*
u8 negoFlags; /* bit field, see above */
u8 raidVolume; /* set, if RAID Volume */
u8 type; /* byte 0 of Inquiry data */
+ u8 deleted; /* target in process of being removed */
u32 num_luns;
u32 luns[8]; /* Max LUNs is 256 */
} VirtTarget;
struct mutex sas_discovery_mutex;
u8 sas_discovery_runtime;
u8 sas_discovery_ignore_events;
+ u16 handle;
int sas_index; /* index refrencing */
MPT_SAS_MGMT sas_mgmt;
int num_ports;
- struct work_struct mptscsih_persistTask;
+ struct work_struct sas_persist_task;
struct work_struct fc_setup_reset_work;
struct list_head fc_rports;
struct work_struct fc_rescan_work;
char fc_rescan_work_q_name[KOBJ_NAME_LEN];
struct workqueue_struct *fc_rescan_work_q;
+ u8 port_serial_number;
} MPT_ADAPTER;
/*
#define DBG_DUMP_REQUEST_FRAME_HDR(mfp)
#endif
+// debug sas wide ports
+#ifdef MPT_DEBUG_SAS_WIDE
+#define dsaswideprintk(x) printk x
+#else
+#define dsaswideprintk(x)
+#endif
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
*/
static struct pci_device_id mptfc_pci_table[] = {
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
+#include <linux/delay.h> /* for mdelay */
+#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_sas.h>
+#include <scsi/scsi_dbg.h>
#include "mptbase.h"
#include "mptscsih.h"
u32 device_info; /* bitfield detailed info about this device */
};
+/*
+ * Specific details on ports, wide/narrow
+ */
+struct mptsas_portinfo_details{
+ u8 port_id; /* port number provided to transport */
+ u16 num_phys; /* number of phys belong to this port */
+ u64 phy_bitmask; /* TODO, extend support for 255 phys */
+ struct sas_rphy *rphy; /* transport layer rphy object */
+ struct sas_port *port; /* transport layer port object */
+ struct scsi_target *starget;
+ struct mptsas_portinfo *port_info;
+};
+
struct mptsas_phyinfo {
u8 phy_id; /* phy index */
- u8 port_id; /* port number this phy is part of */
+ u8 port_id; /* firmware port identifier */
u8 negotiated_link_rate; /* nego'd link rate for this phy */
u8 hw_link_rate; /* hardware max/min phys link rate */
u8 programmed_link_rate; /* programmed max/min phy link rate */
+ u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
struct mptsas_devinfo identify; /* point to phy device info */
struct mptsas_devinfo attached; /* point to attached device info */
- struct sas_phy *phy;
- struct sas_rphy *rphy;
- struct scsi_target *starget;
+ struct sas_phy *phy; /* transport layer phy object */
+ struct mptsas_portinfo *portinfo;
+ struct mptsas_portinfo_details * port_details;
};
struct mptsas_portinfo {
struct list_head list;
u16 handle; /* unique id to address this */
- u8 num_phys; /* number of phys */
+ u16 num_phys; /* number of phys */
struct mptsas_phyinfo *phy_info;
};
u8 sep_channel; /* SEP channel logical channel id */
};
-#ifdef SASDEBUG
+#ifdef MPT_DEBUG_SAS
static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
{
printk("---- IO UNIT PAGE 0 ------------\n");
static inline int
mptsas_is_end_device(struct mptsas_devinfo * attached)
{
- if ((attached->handle) &&
+ if ((attached->sas_address) &&
(attached->device_info &
MPI_SAS_DEVICE_INFO_END_DEVICE) &&
((attached->device_info &
return 0;
}
+/* no mutex */
+static void
+mptsas_port_delete(struct mptsas_portinfo_details * port_details)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_phyinfo *phy_info;
+ u8 i;
+
+ if (!port_details)
+ return;
+
+ port_info = port_details->port_info;
+ phy_info = port_info->phy_info;
+
+ dsaswideprintk((KERN_DEBUG "%s: [%p]: port=%02d num_phys=%02d "
+ "bitmask=0x%016llX\n",
+ __FUNCTION__, port_details, port_details->port_id,
+ port_details->num_phys, port_details->phy_bitmask));
+
+ for (i = 0; i < port_info->num_phys; i++, phy_info++) {
+ if(phy_info->port_details != port_details)
+ continue;
+ memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+ phy_info->port_details = NULL;
+ }
+ kfree(port_details);
+}
+
+static inline struct sas_rphy *
+mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
+{
+ if (phy_info->port_details)
+ return phy_info->port_details->rphy;
+ else
+ return NULL;
+}
+
+static inline void
+mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
+{
+ if (phy_info->port_details) {
+ phy_info->port_details->rphy = rphy;
+ dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
+ }
+
+#ifdef MPT_DEBUG_SAS_WIDE
+ if (rphy) {
+ dev_printk(KERN_DEBUG, &rphy->dev, "add:");
+ printk("rphy=%p release=%p\n",
+ rphy, rphy->dev.release);
+ }
+#endif
+}
+
+static inline struct sas_port *
+mptsas_get_port(struct mptsas_phyinfo *phy_info)
+{
+ if (phy_info->port_details)
+ return phy_info->port_details->port;
+ else
+ return NULL;
+}
+
+static inline void
+mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
+{
+ if (phy_info->port_details)
+ phy_info->port_details->port = port;
+
+#ifdef MPT_DEBUG_SAS_WIDE
+ if (port) {
+ dev_printk(KERN_DEBUG, &port->dev, "add: ");
+ printk("port=%p release=%p\n",
+ port, port->dev.release);
+ }
+#endif
+}
+
+static inline struct scsi_target *
+mptsas_get_starget(struct mptsas_phyinfo *phy_info)
+{
+ if (phy_info->port_details)
+ return phy_info->port_details->starget;
+ else
+ return NULL;
+}
+
+static inline void
+mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
+starget)
+{
+ if (phy_info->port_details)
+ phy_info->port_details->starget = starget;
+}
+
+
+/*
+ * mptsas_setup_wide_ports
+ *
+ * Updates for new and existing narrow/wide port configuration
+ * in the sas_topology
+ */
+static void
+mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
+{
+ struct mptsas_portinfo_details * port_details;
+ struct mptsas_phyinfo *phy_info, *phy_info_cmp;
+ u64 sas_address;
+ int i, j;
+
+ mutex_lock(&ioc->sas_topology_mutex);
+
+ phy_info = port_info->phy_info;
+ for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
+ if (phy_info->attached.handle)
+ continue;
+ port_details = phy_info->port_details;
+ if (!port_details)
+ continue;
+ if (port_details->num_phys < 2)
+ continue;
+ /*
+ * Removing a phy from a port, letting the last
+ * phy be removed by firmware events.
+ */
+ dsaswideprintk((KERN_DEBUG
+ "%s: [%p]: port=%d deleting phy = %d\n",
+ __FUNCTION__, port_details,
+ port_details->port_id, i));
+ port_details->num_phys--;
+ port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
+ memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+ sas_port_delete_phy(port_details->port, phy_info->phy);
+ phy_info->port_details = NULL;
+ }
+
+ /*
+ * Populate and refresh the tree
+ */
+ phy_info = port_info->phy_info;
+ for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
+ sas_address = phy_info->attached.sas_address;
+ dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
+ i, sas_address));
+ if (!sas_address)
+ continue;
+ port_details = phy_info->port_details;
+ /*
+ * Forming a port
+ */
+ if (!port_details) {
+ port_details = kzalloc(sizeof(*port_details),
+ GFP_KERNEL);
+ if (!port_details)
+ goto out;
+ port_details->num_phys = 1;
+ port_details->port_info = port_info;
+ port_details->port_id = ioc->port_serial_number++;
+ if (phy_info->phy_id < 64 )
+ port_details->phy_bitmask |=
+ (1 << phy_info->phy_id);
+ phy_info->sas_port_add_phy=1;
+ dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
+ "phy_id=%d sas_address=0x%018llX\n",
+ i, sas_address));
+ phy_info->port_details = port_details;
+ }
+
+ if (i == port_info->num_phys - 1)
+ continue;
+ phy_info_cmp = &port_info->phy_info[i + 1];
+ for (j = i + 1 ; j < port_info->num_phys ; j++,
+ phy_info_cmp++) {
+ if (!phy_info_cmp->attached.sas_address)
+ continue;
+ if (sas_address != phy_info_cmp->attached.sas_address)
+ continue;
+ if (phy_info_cmp->port_details == port_details )
+ continue;
+ dsaswideprintk((KERN_DEBUG
+ "\t\tphy_id=%d sas_address=0x%018llX\n",
+ j, phy_info_cmp->attached.sas_address));
+ if (phy_info_cmp->port_details) {
+ port_details->rphy =
+ mptsas_get_rphy(phy_info_cmp);
+ port_details->port =
+ mptsas_get_port(phy_info_cmp);
+ port_details->starget =
+ mptsas_get_starget(phy_info_cmp);
+ port_details->port_id =
+ phy_info_cmp->port_details->port_id;
+ port_details->num_phys =
+ phy_info_cmp->port_details->num_phys;
+// port_info->port_serial_number--;
+ ioc->port_serial_number--;
+ if (!phy_info_cmp->port_details->num_phys)
+ kfree(phy_info_cmp->port_details);
+ } else
+ phy_info_cmp->sas_port_add_phy=1;
+ /*
+ * Adding a phy to a port
+ */
+ phy_info_cmp->port_details = port_details;
+ if (phy_info_cmp->phy_id < 64 )
+ port_details->phy_bitmask |=
+ (1 << phy_info_cmp->phy_id);
+ port_details->num_phys++;
+ }
+ }
+
+ out:
+
+#ifdef MPT_DEBUG_SAS_WIDE
+ for (i = 0; i < port_info->num_phys; i++) {
+ port_details = port_info->phy_info[i].port_details;
+ if (!port_details)
+ continue;
+ dsaswideprintk((KERN_DEBUG
+ "%s: [%p]: phy_id=%02d port_id=%02d num_phys=%02d "
+ "bitmask=0x%016llX\n",
+ __FUNCTION__,
+ port_details, i, port_details->port_id,
+ port_details->num_phys, port_details->phy_bitmask));
+ dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
+ port_details->port, port_details->rphy));
+ }
+ dsaswideprintk((KERN_DEBUG"\n"));
+#endif
+ mutex_unlock(&ioc->sas_topology_mutex);
+}
+
+static void
+mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
+{
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+
+ if (mptscsih_TMHandler(hd,
+ MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+ vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ printk(MYIOC_s_WARN_FMT
+ "Error processing TaskMgmt id=%d TARGET_RESET\n",
+ ioc->name, vtarget->target_id);
+ }
+}
+
static int
mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
u32 form, u32 form_specific)
return mptscsih_slave_configure(sdev);
}
-/*
- * This is pretty ugly. We will be able to seriously clean it up
- * once the DV code in mptscsih goes away and we can properly
- * implement ->target_alloc.
- */
+static int
+mptsas_target_alloc(struct scsi_target *starget)
+{
+ struct Scsi_Host *host = dev_to_shost(&starget->dev);
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ VirtTarget *vtarget;
+ u32 target_id;
+ u32 channel;
+ struct sas_rphy *rphy;
+ struct mptsas_portinfo *p;
+ int i;
+
+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+ if (!vtarget)
+ return -ENOMEM;
+
+ vtarget->starget = starget;
+ vtarget->ioc_id = hd->ioc->id;
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
+
+ target_id = starget->id;
+ channel = 0;
+
+ hd->Targets[target_id] = vtarget;
+
+ /*
+ * RAID volumes placed beyond the last expected port.
+ */
+ if (starget->channel == hd->ioc->num_ports)
+ goto out;
+
+ rphy = dev_to_rphy(starget->dev.parent);
+ mutex_lock(&hd->ioc->sas_topology_mutex);
+ list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+ for (i = 0; i < p->num_phys; i++) {
+ if (p->phy_info[i].attached.sas_address !=
+ rphy->identify.sas_address)
+ continue;
+ target_id = p->phy_info[i].attached.id;
+ channel = p->phy_info[i].attached.channel;
+ mptsas_set_starget(&p->phy_info[i], starget);
+
+ /*
+ * Exposing hidden raid components
+ */
+ if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
+ target_id = mptscsih_raid_id_to_num(hd,
+ target_id);
+ vtarget->tflags |=
+ MPT_TARGET_FLAGS_RAID_COMPONENT;
+ }
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
+ goto out;
+ }
+ }
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
+
+ kfree(vtarget);
+ return -ENXIO;
+
+ out:
+ vtarget->target_id = target_id;
+ vtarget->bus_id = channel;
+ starget->hostdata = vtarget;
+ return 0;
+}
+
+static void
+mptsas_target_destroy(struct scsi_target *starget)
+{
+ struct Scsi_Host *host = dev_to_shost(&starget->dev);
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ struct sas_rphy *rphy;
+ struct mptsas_portinfo *p;
+ int i;
+
+ if (!starget->hostdata)
+ return;
+
+ if (starget->channel == hd->ioc->num_ports)
+ goto out;
+
+ rphy = dev_to_rphy(starget->dev.parent);
+ list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+ for (i = 0; i < p->num_phys; i++) {
+ if (p->phy_info[i].attached.sas_address !=
+ rphy->identify.sas_address)
+ continue;
+ mptsas_set_starget(&p->phy_info[i], NULL);
+ goto out;
+ }
+ }
+
+ out:
+ kfree(starget->hostdata);
+ starget->hostdata = NULL;
+}
+
+
static int
mptsas_slave_alloc(struct scsi_device *sdev)
{
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
struct sas_rphy *rphy;
struct mptsas_portinfo *p;
- VirtTarget *vtarget;
VirtDevice *vdev;
struct scsi_target *starget;
- u32 target_id;
- int i;
+ int i;
vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
if (!vdev) {
- printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+ printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
hd->ioc->name, sizeof(VirtDevice));
return -ENOMEM;
}
- sdev->hostdata = vdev;
starget = scsi_target(sdev);
- vtarget = starget->hostdata;
- vtarget->ioc_id = hd->ioc->id;
- vdev->vtarget = vtarget;
- if (vtarget->num_luns == 0) {
- vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
- hd->Targets[sdev->id] = vtarget;
- }
+ vdev->vtarget = starget->hostdata;
/*
- RAID volumes placed beyond the last expected port.
- */
- if (sdev->channel == hd->ioc->num_ports) {
- target_id = sdev->id;
- vtarget->bus_id = 0;
- vdev->lun = 0;
+ * RAID volumes placed beyond the last expected port.
+ */
+ if (sdev->channel == hd->ioc->num_ports)
goto out;
- }
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
mutex_lock(&hd->ioc->sas_topology_mutex);
list_for_each_entry(p, &hd->ioc->sas_topology, list) {
for (i = 0; i < p->num_phys; i++) {
- if (p->phy_info[i].attached.sas_address ==
- rphy->identify.sas_address) {
- target_id = p->phy_info[i].attached.id;
- vtarget->bus_id = p->phy_info[i].attached.channel;
- vdev->lun = sdev->lun;
- p->phy_info[i].starget = sdev->sdev_target;
- /*
- * Exposing hidden disk (RAID)
- */
- if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
- target_id = mptscsih_raid_id_to_num(hd,
- target_id);
- vdev->vtarget->tflags |=
- MPT_TARGET_FLAGS_RAID_COMPONENT;
- sdev->no_uld_attach = 1;
- }
- mutex_unlock(&hd->ioc->sas_topology_mutex);
- goto out;
- }
+ if (p->phy_info[i].attached.sas_address !=
+ rphy->identify.sas_address)
+ continue;
+ vdev->lun = sdev->lun;
+ /*
+ * Exposing hidden raid components
+ */
+ if (mptscsih_is_phys_disk(hd->ioc,
+ p->phy_info[i].attached.id))
+ sdev->no_uld_attach = 1;
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
+ goto out;
}
}
mutex_unlock(&hd->ioc->sas_topology_mutex);
return -ENXIO;
out:
- vtarget->target_id = target_id;
- vtarget->num_luns++;
+ vdev->vtarget->num_luns++;
+ sdev->hostdata = vdev;
return 0;
}
-static void
-mptsas_slave_destroy(struct scsi_device *sdev)
+static int
+mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
- struct Scsi_Host *host = sdev->host;
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
- VirtDevice *vdev;
+ VirtDevice *vdev = SCpnt->device->hostdata;
- /*
- * Issue target reset to flush firmware outstanding commands.
- */
- vdev = sdev->hostdata;
- if (vdev->configured_lun){
- if (mptscsih_TMHandler(hd,
- MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
- vdev->vtarget->bus_id,
- vdev->vtarget->target_id,
- 0, 0, 5 /* 5 second timeout */)
- < 0){
-
- /* The TM request failed!
- * Fatal error case.
- */
- printk(MYIOC_s_WARN_FMT
- "Error processing TaskMgmt id=%d TARGET_RESET\n",
- hd->ioc->name,
- vdev->vtarget->target_id);
-
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- }
+// scsi_print_command(SCpnt);
+ if (vdev->vtarget->deleted) {
+ SCpnt->result = DID_NO_CONNECT << 16;
+ done(SCpnt);
+ return 0;
}
- mptscsih_slave_destroy(sdev);
+
+ return mptscsih_qcmd(SCpnt,done);
}
+
static struct scsi_host_template mptsas_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptsas",
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
- .queuecommand = mptscsih_qcmd,
- .target_alloc = mptscsih_target_alloc,
+ .queuecommand = mptsas_qcmd,
+ .target_alloc = mptsas_target_alloc,
.slave_alloc = mptsas_slave_alloc,
.slave_configure = mptsas_slave_configure,
- .target_destroy = mptscsih_target_destroy,
- .slave_destroy = mptsas_slave_destroy,
+ .target_destroy = mptsas_target_destroy,
+ .slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
port_info->num_phys = buffer->NumPhys;
port_info->phy_info = kcalloc(port_info->num_phys,
- sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+ sizeof(*port_info->phy_info),GFP_KERNEL);
if (!port_info->phy_info) {
error = -ENOMEM;
goto out_free_consistent;
buffer->PhyData[i].Port;
port_info->phy_info[i].negotiated_link_rate =
buffer->PhyData[i].NegotiatedLinkRate;
+ port_info->phy_info[i].portinfo = port_info;
}
out_free_consistent:
CONFIGPARMS cfg;
SasExpanderPage0_t *buffer;
dma_addr_t dma_handle;
- int error;
+ int i, error;
hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
hdr.ExtPageLength = 0;
port_info->num_phys = buffer->NumPhys;
port_info->handle = le16_to_cpu(buffer->DevHandle);
port_info->phy_info = kcalloc(port_info->num_phys,
- sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+ sizeof(*port_info->phy_info),GFP_KERNEL);
if (!port_info->phy_info) {
error = -ENOMEM;
goto out_free_consistent;
}
+ for (i = 0; i < port_info->num_phys; i++)
+ port_info->phy_info[i].portinfo = port_info;
+
out_free_consistent:
pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
buffer, dma_handle);
{
MPT_ADAPTER *ioc;
struct sas_phy *phy;
- int error;
+ struct sas_port *port;
+ int error = 0;
- if (!dev)
- return -ENODEV;
+ if (!dev) {
+ error = -ENODEV;
+ goto out;
+ }
if (!phy_info->phy) {
phy = sas_phy_alloc(dev, index);
- if (!phy)
- return -ENOMEM;
+ if (!phy) {
+ error = -ENOMEM;
+ goto out;
+ }
} else
phy = phy_info->phy;
- phy->port_identifier = phy_info->port_id;
mptsas_parse_device_info(&phy->identify, &phy_info->identify);
/*
error = sas_phy_add(phy);
if (error) {
sas_phy_free(phy);
- return error;
+ goto out;
}
phy_info->phy = phy;
}
- if ((phy_info->attached.handle) &&
- (!phy_info->rphy)) {
+ if (!phy_info->attached.handle ||
+ !phy_info->port_details)
+ goto out;
+
+ port = mptsas_get_port(phy_info);
+ ioc = phy_to_ioc(phy_info->phy);
+
+ if (phy_info->sas_port_add_phy) {
+
+ if (!port) {
+ port = sas_port_alloc(dev,
+ phy_info->port_details->port_id);
+ dsaswideprintk((KERN_DEBUG
+ "sas_port_alloc: port=%p dev=%p port_id=%d\n",
+ port, dev, phy_info->port_details->port_id));
+ if (!port) {
+ error = -ENOMEM;
+ goto out;
+ }
+ error = sas_port_add(port);
+ if (error) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ goto out;
+ }
+ mptsas_set_port(phy_info, port);
+ }
+ dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
+ phy_info->phy_id));
+ sas_port_add_phy(port, phy_info->phy);
+ phy_info->sas_port_add_phy = 0;
+ }
+
+ if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
struct sas_rphy *rphy;
+ struct device *parent;
struct sas_identify identify;
- ioc = phy_to_ioc(phy_info->phy);
-
+ parent = dev->parent->parent;
/*
* Let the hotplug_work thread handle processing
* the adding/removing of devices that occur
*/
if (ioc->sas_discovery_runtime &&
mptsas_is_end_device(&phy_info->attached))
- return 0;
+ goto out;
mptsas_parse_device_info(&identify, &phy_info->attached);
+ if (scsi_is_host_device(parent)) {
+ struct mptsas_portinfo *port_info;
+ int i;
+
+ mutex_lock(&ioc->sas_topology_mutex);
+ port_info = mptsas_find_portinfo_by_handle(ioc,
+ ioc->handle);
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ for (i = 0; i < port_info->num_phys; i++)
+ if (port_info->phy_info[i].identify.sas_address ==
+ identify.sas_address)
+ goto out;
+
+ } else if (scsi_is_sas_rphy(parent)) {
+ struct sas_rphy *parent_rphy = dev_to_rphy(parent);
+ if (identify.sas_address ==
+ parent_rphy->identify.sas_address)
+ goto out;
+ }
+
switch (identify.device_type) {
case SAS_END_DEVICE:
- rphy = sas_end_device_alloc(phy);
+ rphy = sas_end_device_alloc(port);
break;
case SAS_EDGE_EXPANDER_DEVICE:
case SAS_FANOUT_EXPANDER_DEVICE:
- rphy = sas_expander_alloc(phy, identify.device_type);
+ rphy = sas_expander_alloc(port, identify.device_type);
break;
default:
rphy = NULL;
break;
}
- if (!rphy)
- return 0; /* non-fatal: an rphy can be added later */
+ if (!rphy) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ goto out;
+ }
rphy->identify = identify;
-
error = sas_rphy_add(rphy);
if (error) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
sas_rphy_free(rphy);
- return error;
+ goto out;
}
-
- phy_info->rphy = rphy;
+ mptsas_set_rphy(phy_info, rphy);
}
- return 0;
+ out:
+ return error;
}
static int
goto out_free_port_info;
mutex_lock(&ioc->sas_topology_mutex);
+ ioc->handle = hba->handle;
port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
if (!port_info) {
port_info = hba;
for (i = 0; i < hba->num_phys; i++)
port_info->phy_info[i].negotiated_link_rate =
hba->phy_info[i].negotiated_link_rate;
- if (hba->phy_info)
- kfree(hba->phy_info);
+ kfree(hba->phy_info);
kfree(hba);
hba = NULL;
}
port_info->phy_info[i].phy_id;
handle = port_info->phy_info[i].identify.handle;
- if (port_info->phy_info[i].attached.handle) {
+ if (port_info->phy_info[i].attached.handle)
mptsas_sas_device_pg0(ioc,
&port_info->phy_info[i].attached,
(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
port_info->phy_info[i].attached.handle);
- }
+ }
+
+ mptsas_setup_wide_ports(ioc, port_info);
+ for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
mptsas_probe_one_phy(&ioc->sh->shost_gendev,
&port_info->phy_info[i], ioc->sas_index, 1);
- ioc->sas_index++;
- }
return 0;
mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
{
struct mptsas_portinfo *port_info, *p, *ex;
+ struct device *parent;
+ struct sas_rphy *rphy;
int error = -ENOMEM, i, j;
ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
list_add_tail(&port_info->list, &ioc->sas_topology);
} else {
port_info->handle = ex->handle;
- if (ex->phy_info)
- kfree(ex->phy_info);
+ kfree(ex->phy_info);
kfree(ex);
ex = NULL;
}
mutex_unlock(&ioc->sas_topology_mutex);
for (i = 0; i < port_info->num_phys; i++) {
- struct device *parent;
-
mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
(MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
port_info->phy_info[i].attached.phy_id =
port_info->phy_info[i].phy_id;
}
+ }
- /*
- * If we find a parent port handle this expander is
- * attached to another expander, else it hangs of the
- * HBA phys.
- */
- parent = &ioc->sh->shost_gendev;
+ parent = &ioc->sh->shost_gendev;
+ for (i = 0; i < port_info->num_phys; i++) {
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(p, &ioc->sas_topology, list) {
for (j = 0; j < p->num_phys; j++) {
- if (port_info->phy_info[i].identify.handle ==
+ if (port_info->phy_info[i].identify.handle !=
p->phy_info[j].attached.handle)
- parent = &p->phy_info[j].rphy->dev;
+ continue;
+ rphy = mptsas_get_rphy(&p->phy_info[j]);
+ parent = &rphy->dev;
}
}
mutex_unlock(&ioc->sas_topology_mutex);
+ }
+
+ mptsas_setup_wide_ports(ioc, port_info);
+ for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
mptsas_probe_one_phy(parent, &port_info->phy_info[i],
ioc->sas_index, 0);
- ioc->sas_index++;
- }
return 0;
out_free_port_info:
if (ex) {
- if (ex->phy_info)
- kfree(ex->phy_info);
+ kfree(ex->phy_info);
kfree(ex);
}
out:
{
struct mptsas_portinfo buffer;
struct mptsas_portinfo *port_info, *n, *parent;
+ struct mptsas_phyinfo *phy_info;
+ struct scsi_target * starget;
+ VirtTarget * vtarget;
+ struct sas_port * port;
int i;
+ u64 expander_sas_address;
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
(MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
+ /*
+ * Issue target reset to all child end devices
+ * then mark them deleted to prevent further
+ * IO going to them.
+ */
+ phy_info = port_info->phy_info;
+ for (i = 0; i < port_info->num_phys; i++, phy_info++) {
+ starget = mptsas_get_starget(phy_info);
+ if (!starget)
+ continue;
+ vtarget = starget->hostdata;
+ if(vtarget->deleted)
+ continue;
+ vtarget->deleted = 1;
+ mptsas_target_reset(ioc, vtarget);
+ sas_port_delete(mptsas_get_port(phy_info));
+ mptsas_port_delete(phy_info->port_details);
+ }
+
/*
* Obtain the port_info instance to the parent port
*/
if (!parent)
goto next_port;
+ expander_sas_address =
+ port_info->phy_info[0].identify.sas_address;
+
/*
* Delete rphys in the parent that point
* to this expander. The transport layer will
* cleanup all the children.
*/
- for (i = 0; i < parent->num_phys; i++) {
- if ((!parent->phy_info[i].rphy) ||
- (parent->phy_info[i].attached.sas_address !=
- port_info->phy_info[i].identify.sas_address))
+ phy_info = parent->phy_info;
+ for (i = 0; i < parent->num_phys; i++, phy_info++) {
+ port = mptsas_get_port(phy_info);
+ if (!port)
+ continue;
+ if (phy_info->attached.sas_address !=
+ expander_sas_address)
continue;
- sas_rphy_delete(parent->phy_info[i].rphy);
- memset(&parent->phy_info[i].attached, 0,
- sizeof(struct mptsas_devinfo));
- parent->phy_info[i].rphy = NULL;
- parent->phy_info[i].starget = NULL;
+#ifdef MPT_DEBUG_SAS_WIDE
+ dev_printk(KERN_DEBUG, &port->dev, "delete\n");
+#endif
+ sas_port_delete(port);
+ mptsas_port_delete(phy_info->port_details);
}
next_port:
+
+ phy_info = port_info->phy_info;
+ for (i = 0; i < port_info->num_phys; i++, phy_info++)
+ mptsas_port_delete(phy_info->port_details);
+
list_del(&port_info->list);
- if (port_info->phy_info)
- kfree(port_info->phy_info);
+ kfree(port_info->phy_info);
kfree(port_info);
}
/*
* Free this memory allocated from inside
* mptsas_sas_expander_pg0
*/
- if (buffer.phy_info)
- kfree(buffer.phy_info);
+ kfree(buffer.phy_info);
}
mutex_unlock(&ioc->sas_topology_mutex);
}
/*
* Work queue thread to handle Runtime discovery
* Mere purpose is the hot add/delete of expanders
+ *(Mutex UNLOCKED)
*/
static void
-mptscsih_discovery_work(void * arg)
+__mptsas_discovery_work(MPT_ADAPTER *ioc)
{
- struct mptsas_discovery_event *ev = arg;
- MPT_ADAPTER *ioc = ev->ioc;
u32 handle = 0xFFFF;
- mutex_lock(&ioc->sas_discovery_mutex);
ioc->sas_discovery_runtime=1;
mptsas_delete_expander_phys(ioc);
mptsas_probe_hba_phys(ioc);
while (!mptsas_probe_expander_phys(ioc, &handle))
;
- kfree(ev);
ioc->sas_discovery_runtime=0;
+}
+
+/*
+ * Work queue thread to handle Runtime discovery
+ * Mere purpose is the hot add/delete of expanders
+ *(Mutex LOCKED)
+ */
+static void
+mptsas_discovery_work(void * arg)
+{
+ struct mptsas_discovery_event *ev = arg;
+ MPT_ADAPTER *ioc = ev->ioc;
+
+ mutex_lock(&ioc->sas_discovery_mutex);
+ __mptsas_discovery_work(ioc);
mutex_unlock(&ioc->sas_discovery_mutex);
+ kfree(ev);
}
static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
{
struct mptsas_portinfo *port_info;
- struct mptsas_devinfo device_info;
struct mptsas_phyinfo *phy_info = NULL;
- int i, error;
-
- /*
- * Retrieve the parent sas_address
- */
- error = mptsas_sas_device_pg0(ioc, &device_info,
- (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
- MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
- parent_handle);
- if (error)
- return NULL;
+ int i;
- /*
- * The phy_info structures are never deallocated during lifetime of
- * a host, so the code below is safe without additional refcounting.
- */
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(port_info, &ioc->sas_topology, list) {
for (i = 0; i < port_info->num_phys; i++) {
- if (port_info->phy_info[i].identify.sas_address ==
- device_info.sas_address &&
- port_info->phy_info[i].phy_id == phy_id) {
- phy_info = &port_info->phy_info[i];
- break;
- }
+ if (port_info->phy_info[i].attached.sas_address
+ != sas_address)
+ continue;
+ if (!mptsas_is_end_device(
+ &port_info->phy_info[i].attached))
+ continue;
+ phy_info = &port_info->phy_info[i];
+ break;
}
}
mutex_unlock(&ioc->sas_topology_mutex);
-
return phy_info;
}
struct mptsas_phyinfo *phy_info = NULL;
int i;
- /*
- * The phy_info structures are never deallocated during lifetime of
- * a host, so the code below is safe without additional refcounting.
- */
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(port_info, &ioc->sas_topology, list) {
- for (i = 0; i < port_info->num_phys; i++)
- if (mptsas_is_end_device(&port_info->phy_info[i].attached))
- if (port_info->phy_info[i].attached.id == id) {
- phy_info = &port_info->phy_info[i];
- break;
- }
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].attached.id != id)
+ continue;
+ if (!mptsas_is_end_device(
+ &port_info->phy_info[i].attached))
+ continue;
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
}
mutex_unlock(&ioc->sas_topology_mutex);
-
return phy_info;
}
* Work queue thread to clear the persitency table
*/
static void
-mptscsih_sas_persist_clear_table(void * arg)
+mptsas_persist_clear_table(void * arg)
{
MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
mptsas_reprobe_lun);
}
-
/*
* Work queue thread to handle SAS hotplug events
*/
MPT_ADAPTER *ioc = ev->ioc;
struct mptsas_phyinfo *phy_info;
struct sas_rphy *rphy;
+ struct sas_port *port;
struct scsi_device *sdev;
+ struct scsi_target * starget;
struct sas_identify identify;
char *ds = NULL;
struct mptsas_devinfo sas_device;
VirtTarget *vtarget;
+ VirtDevice *vdevice;
- mutex_lock(&ioc->sas_discovery_mutex);
+ mutex_lock(&ioc->sas_discovery_mutex);
switch (ev->event_type) {
case MPTSAS_DEL_DEVICE:
/*
* Sanity checks, for non-existing phys and remote rphys.
*/
- if (!phy_info)
+ if (!phy_info || !phy_info->port_details) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break;
- if (!phy_info->rphy)
+ }
+ rphy = mptsas_get_rphy(phy_info);
+ if (!rphy) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break;
- if (phy_info->starget) {
- vtarget = phy_info->starget->hostdata;
+ }
+ port = mptsas_get_port(phy_info);
+ if (!port) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ break;
+ }
- if (!vtarget)
+ starget = mptsas_get_starget(phy_info);
+ if (starget) {
+ vtarget = starget->hostdata;
+
+ if (!vtarget) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break;
+ }
+
/*
* Handling RAID components
*/
if (ev->phys_disk_num_valid) {
vtarget->target_id = ev->phys_disk_num;
vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
- mptsas_reprobe_target(vtarget->starget, 1);
+ mptsas_reprobe_target(starget, 1);
break;
}
+
+ vtarget->deleted = 1;
+ mptsas_target_reset(ioc, vtarget);
}
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
"removing %s device, channel %d, id %d, phy %d\n",
ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
- sas_rphy_delete(phy_info->rphy);
- memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
- phy_info->rphy = NULL;
- phy_info->starget = NULL;
+#ifdef MPT_DEBUG_SAS_WIDE
+ dev_printk(KERN_DEBUG, &port->dev, "delete\n");
+#endif
+ sas_port_delete(port);
+ mptsas_port_delete(phy_info->port_details);
break;
case MPTSAS_ADD_DEVICE:
*/
if (mptsas_sas_device_pg0(ioc, &sas_device,
(MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
- MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break;
+ }
- phy_info = mptsas_find_phyinfo_by_parent(ioc,
- sas_device.handle_parent, sas_device.phy_id);
+ ssleep(2);
+ __mptsas_discovery_work(ioc);
- if (!phy_info) {
- u32 handle = 0xFFFF;
+ phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+ sas_device.sas_address);
- /*
- * Its possible when an expander has been hot added
- * containing attached devices, the sas firmware
- * may send a RC_ADDED event prior to the
- * DISCOVERY STOP event. If that occurs, our
- * view of the topology in the driver in respect to this
- * expander might of not been setup, and we hit this
- * condition.
- * Therefore, this code kicks off discovery to
- * refresh the data.
- * Then again, we check whether the parent phy has
- * been created.
- */
- ioc->sas_discovery_runtime=1;
- mptsas_delete_expander_phys(ioc);
- mptsas_probe_hba_phys(ioc);
- while (!mptsas_probe_expander_phys(ioc, &handle))
- ;
- ioc->sas_discovery_runtime=0;
-
- phy_info = mptsas_find_phyinfo_by_parent(ioc,
- sas_device.handle_parent, sas_device.phy_id);
- if (!phy_info)
- break;
+ if (!phy_info || !phy_info->port_details) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ break;
}
- if (phy_info->starget) {
- vtarget = phy_info->starget->hostdata;
+ starget = mptsas_get_starget(phy_info);
+ if (starget) {
+ vtarget = starget->hostdata;
- if (!vtarget)
+ if (!vtarget) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break;
+ }
/*
* Handling RAID components
*/
if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
vtarget->target_id = ev->id;
- mptsas_reprobe_target(phy_info->starget, 0);
+ mptsas_reprobe_target(starget, 0);
}
break;
}
- if (phy_info->rphy)
+ if (mptsas_get_rphy(phy_info)) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break;
+ }
+ port = mptsas_get_port(phy_info);
+ if (!port) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ break;
+ }
memcpy(&phy_info->attached, &sas_device,
sizeof(struct mptsas_devinfo));
ioc->name, ds, ev->channel, ev->id, ev->phy_id);
mptsas_parse_device_info(&identify, &phy_info->attached);
- switch (identify.device_type) {
- case SAS_END_DEVICE:
- rphy = sas_end_device_alloc(phy_info->phy);
- break;
- case SAS_EDGE_EXPANDER_DEVICE:
- case SAS_FANOUT_EXPANDER_DEVICE:
- rphy = sas_expander_alloc(phy_info->phy, identify.device_type);
- break;
- default:
- rphy = NULL;
- break;
- }
- if (!rphy)
+ rphy = sas_end_device_alloc(port);
+ if (!rphy) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
break; /* non-fatal: an rphy can be added later */
+ }
rphy->identify = identify;
if (sas_rphy_add(rphy)) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
sas_rphy_free(rphy);
break;
}
-
- phy_info->rphy = rphy;
+ mptsas_set_rphy(phy_info, rphy);
break;
case MPTSAS_ADD_RAID:
sdev = scsi_device_lookup(
printk(MYIOC_s_INFO_FMT
"removing raid volume, channel %d, id %d\n",
ioc->name, ioc->num_ports, ev->id);
+ vdevice = sdev->hostdata;
+ vdevice->vtarget->deleted = 1;
+ mptsas_target_reset(ioc, vdevice->vtarget);
scsi_remove_device(sdev);
scsi_device_put(sdev);
mpt_findImVolumes(ioc);
break;
}
- kfree(ev);
mutex_unlock(&ioc->sas_discovery_mutex);
+ kfree(ev);
+
}
static void
-mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+mptsas_send_sas_event(MPT_ADAPTER *ioc,
EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
{
struct mptsas_hotplug_event *ev;
switch (sas_event_data->ReasonCode) {
case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
- ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) {
printk(KERN_WARNING "mptsas: lost hotplug event\n");
break;
/*
* Persistent table is full.
*/
- INIT_WORK(&ioc->mptscsih_persistTask,
- mptscsih_sas_persist_clear_table,
- (void *)ioc);
- schedule_work(&ioc->mptscsih_persistTask);
+ INIT_WORK(&ioc->sas_persist_task,
+ mptsas_persist_clear_table, (void *)ioc);
+ schedule_work(&ioc->sas_persist_task);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
/* TODO */
}
static void
-mptscsih_send_raid_event(MPT_ADAPTER *ioc,
+mptsas_send_raid_event(MPT_ADAPTER *ioc,
EVENT_DATA_RAID *raid_event_data)
{
struct mptsas_hotplug_event *ev;
if (ioc->bus_type != SAS)
return;
- ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) {
printk(KERN_WARNING "mptsas: lost hotplug event\n");
return;
}
- memset(ev,0,sizeof(struct mptsas_hotplug_event));
INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
ev->ioc = ioc;
ev->id = raid_event_data->VolumeID;
}
static void
-mptscsih_send_discovery(MPT_ADAPTER *ioc,
+mptsas_send_discovery_event(MPT_ADAPTER *ioc,
EVENT_DATA_SAS_DISCOVERY *discovery_data)
{
struct mptsas_discovery_event *ev;
if (discovery_data->DiscoveryStatus)
return;
- ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev)
return;
- memset(ev,0,sizeof(struct mptsas_discovery_event));
- INIT_WORK(&ev->work, mptscsih_discovery_work, ev);
+ INIT_WORK(&ev->work, mptsas_discovery_work, ev);
ev->ioc = ioc;
schedule_work(&ev->work);
};
switch (event) {
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
- mptscsih_send_sas_event(ioc,
+ mptsas_send_sas_event(ioc,
(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
break;
case MPI_EVENT_INTEGRATED_RAID:
- mptscsih_send_raid_event(ioc,
+ mptsas_send_raid_event(ioc,
(EVENT_DATA_RAID *)reply->Data);
break;
case MPI_EVENT_PERSISTENT_TABLE_FULL:
- INIT_WORK(&ioc->mptscsih_persistTask,
- mptscsih_sas_persist_clear_table,
+ INIT_WORK(&ioc->sas_persist_task,
+ mptsas_persist_clear_table,
(void *)ioc);
- schedule_work(&ioc->mptscsih_persistTask);
+ schedule_work(&ioc->sas_persist_task);
break;
case MPI_EVENT_SAS_DISCOVERY:
- mptscsih_send_discovery(ioc,
+ mptsas_send_discovery_event(ioc,
(EVENT_DATA_SAS_DISCOVERY *)reply->Data);
break;
default:
return 0;
-out_mptsas_probe:
+ out_mptsas_probe:
mptscsih_remove(pdev);
return error;
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct mptsas_portinfo *p, *n;
+ int i;
ioc->sas_discovery_ignore_events=1;
sas_remove_host(ioc->sh);
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
list_del(&p->list);
- if (p->phy_info)
- kfree(p->phy_info);
+ for (i = 0 ; i < p->num_phys ; i++)
+ mptsas_port_delete(p->phy_info[i].port_details);
+ kfree(p->phy_info);
kfree(p);
}
mutex_unlock(&ioc->sas_topology_mutex);
}
static struct pci_device_id mptsas_pci_table[] = {
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
*/
static struct pci_device_id mptspi_pci_table[] = {
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
+ { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
+STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
STATIC struct scsi_transport_template *NCR_700_transport_template = NULL;
-struct NCR_700_sense {
- unsigned char cmnd[MAX_COMMAND_SIZE];
-};
-
static char *NCR_700_phase[] = {
"",
"after selection",
tpnt->use_clustering = ENABLE_CLUSTERING;
tpnt->slave_configure = NCR_700_slave_configure;
tpnt->slave_destroy = NCR_700_slave_destroy;
+ tpnt->slave_alloc = NCR_700_slave_alloc;
tpnt->change_queue_depth = NCR_700_change_queue_depth;
tpnt->change_queue_type = NCR_700_change_queue_type;
struct NCR_700_command_slot *slot =
(struct NCR_700_command_slot *)SCp->host_scribble;
- NCR_700_unmap(hostdata, SCp, slot);
+ dma_unmap_single(hostdata->dev, slot->pCmd,
+ sizeof(SCp->cmnd), DMA_TO_DEVICE);
if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
- struct NCR_700_sense *sense = SCp->device->hostdata;
+ char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
#ifdef NCR_700_DEBUG
printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n",
SCp, SCp->cmnd[7], result);
/* restore the old result if the request sense was
* successful */
if(result == 0)
- result = sense->cmnd[7];
+ result = cmnd[7];
} else
- dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ NCR_700_unmap(hostdata, SCp, slot);
free_slot(slot, hostdata);
#ifdef NCR_700_DEBUG
status_byte(hostdata->status[0]) == COMMAND_TERMINATED) {
struct NCR_700_command_slot *slot =
(struct NCR_700_command_slot *)SCp->host_scribble;
- if(SCp->cmnd[0] == REQUEST_SENSE) {
+ if(slot->flags == NCR_700_FLAG_AUTOSENSE) {
/* OOPS: bad device, returning another
* contingent allegiance condition */
scmd_printk(KERN_ERR, SCp,
"broken device is looping in contingent allegiance: ignoring\n");
NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]);
} else {
- struct NCR_700_sense *sense = SCp->device->hostdata;
+ char *cmnd =
+ NCR_700_get_sense_cmnd(SCp->device);
#ifdef NCR_DEBUG
scsi_print_command(SCp);
printk(" cmd %p has status %d, requesting sense\n",
sizeof(SCp->cmnd),
DMA_TO_DEVICE);
- sense->cmnd[0] = REQUEST_SENSE;
- sense->cmnd[1] = (SCp->device->lun & 0x7) << 5;
- sense->cmnd[2] = 0;
- sense->cmnd[3] = 0;
- sense->cmnd[4] = sizeof(SCp->sense_buffer);
- sense->cmnd[5] = 0;
+ cmnd[0] = REQUEST_SENSE;
+ cmnd[1] = (SCp->device->lun & 0x7) << 5;
+ cmnd[2] = 0;
+ cmnd[3] = 0;
+ cmnd[4] = sizeof(SCp->sense_buffer);
+ cmnd[5] = 0;
/* Here's a quiet hack: the
* REQUEST_SENSE command is six bytes,
* so store a flag indicating that
* this was an internal sense request
* and the original status at the end
* of the command */
- sense->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
- sense->cmnd[7] = hostdata->status[0];
- slot->pCmd = dma_map_single(hostdata->dev, sense->cmnd, sizeof(sense->cmnd), DMA_TO_DEVICE);
+ cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
+ cmnd[7] = hostdata->status[0];
+ slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE);
slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
slot->SG[0].pAddr = bS_to_host(slot->dma_handle);
/* clear all the negotiated parameters */
__shost_for_each_device(SDp, host)
- SDp->hostdata = NULL;
+ NCR_700_clear_flag(SDp, ~0);
/* clear all the slots and their pending commands */
for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) {
spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION;
}
+STATIC int
+NCR_700_slave_alloc(struct scsi_device *SDp)
+{
+ SDp->hostdata = kzalloc(sizeof(struct NCR_700_Device_Parameters),
+ GFP_KERNEL);
+ if (!SDp->hostdata)
+ return -ENOMEM;
+
+ return 0;
+}
STATIC int
NCR_700_slave_configure(struct scsi_device *SDp)
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
- SDp->hostdata = kmalloc(GFP_KERNEL, sizeof(struct NCR_700_sense));
-
- if (!SDp->hostdata)
- return -ENOMEM;
-
/* to do here: allocate memory; build a queue_full list */
if(SDp->tagged_supported) {
scsi_set_tag_type(SDp, MSG_ORDERED_TAG);
#include <asm/io.h>
#include <scsi/scsi_device.h>
-
+#include <scsi/scsi_cmnd.h>
/* Turn on for general debugging---too verbose for normal use */
#undef NCR_700_DEBUG
#define SCRIPT_RETURN 0x90080000
};
-/* We use device->hostdata to store negotiated parameters. This is
- * supposed to be a pointer to a device private area, but we cannot
- * really use it as such since it will never be freed, so just use the
- * 32 bits to cram the information. The SYNC negotiation sequence looks
- * like:
+struct NCR_700_Device_Parameters {
+ /* space for creating a request sense command. Really, except
+ * for the annoying SCSI-2 requirement for LUN information in
+ * cmnd[1], this could be in static storage */
+ unsigned char cmnd[MAX_COMMAND_SIZE];
+ __u8 depth;
+};
+
+
+/* The SYNC negotiation sequence looks like:
*
* If DEV_NEGOTIATED_SYNC not set, tack and SDTR message on to the
* initial identify for the device and set DEV_BEGIN_SYNC_NEGOTATION
#define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17)
#define NCR_700_DEV_PRINT_SYNC_NEGOTIATION (1<<19)
+static inline char *NCR_700_get_sense_cmnd(struct scsi_device *SDp)
+{
+ struct NCR_700_Device_Parameters *hostdata = SDp->hostdata;
+
+ return hostdata->cmnd;
+}
+
static inline void
NCR_700_set_depth(struct scsi_device *SDp, __u8 depth)
{
- long l = (long)SDp->hostdata;
+ struct NCR_700_Device_Parameters *hostdata = SDp->hostdata;
- l &= 0xffff00ff;
- l |= 0xff00 & (depth << 8);
- SDp->hostdata = (void *)l;
+ hostdata->depth = depth;
}
static inline __u8
NCR_700_get_depth(struct scsi_device *SDp)
{
- return ((((unsigned long)SDp->hostdata) & 0xff00)>>8);
+ struct NCR_700_Device_Parameters *hostdata = SDp->hostdata;
+
+ return hostdata->depth;
}
static inline int
NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag)
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
- /*
- * number of 4k pages of host physical memory. The aacraid fw needs
- * this number to be less than 4gb worth of pages. num_physpages is in
- * system page units. New firmware doesn't have any issues with the
- * mapping system, but older Firmware did, and had *troubles* dealing
- * with the math overloading past 32 bits, thus we must limit this
- * field.
- *
- * This assumes the memory is mapped zero->n, which isnt
- * always true on real computers. It also has some slight problems
- * with the GART on x86-64. I've btw never tried DMA from PCI space
- * on this platform but don't be surprised if its problematic.
- * [AK: something is very very wrong when a driver tests this symbol.
- * Someone should figure out what the comment writer really meant here and fix
- * the code. Or just remove that bad code. ]
- */
-#ifndef CONFIG_IOMMU
- if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) {
- init->HostPhysMemPages =
- cpu_to_le32(num_physpages << (PAGE_SHIFT-12));
- } else
-#endif
- {
- init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
- }
+ init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
init->InitFlags = 0;
if (dev->new_comm_interface) {
} ahd_queue_alg;
void ahd_set_tags(struct ahd_softc *ahd,
+ struct scsi_cmnd *cmd,
struct ahd_devinfo *devinfo,
ahd_queue_alg alg);
/* Notify XPT */
ahd_send_async(ahd, devinfo.channel, devinfo.target,
- CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+ CAM_LUN_WILDCARD, AC_SENT_BDR);
/*
* Allow the sequencer to continue with
tinfo->curr.ppr_options = ppr_options;
ahd_send_async(ahd, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
+ CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
if (bootverbose) {
if (offset != 0) {
int options;
tinfo->curr.width = width;
ahd_send_async(ahd, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
+ CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
if (bootverbose) {
printf("%s: target %d using %dbit transfers\n",
ahd_name(ahd), devinfo->target,
* Update the current state of tagged queuing for a given target.
*/
void
-ahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
- ahd_queue_alg alg)
+ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
+ struct ahd_devinfo *devinfo, ahd_queue_alg alg)
{
- ahd_platform_set_tags(ahd, devinfo, alg);
+ struct scsi_device *sdev = cmd->device;
+
+ ahd_platform_set_tags(ahd, sdev, devinfo, alg);
ahd_send_async(ahd, devinfo->channel, devinfo->target,
- devinfo->lun, AC_TRANSFER_NEG, &alg);
+ devinfo->lun, AC_TRANSFER_NEG);
}
static void
printf("(%s:%c:%d:%d): refuses tagged commands. "
"Performing non-tagged I/O\n", ahd_name(ahd),
devinfo->channel, devinfo->target, devinfo->lun);
- ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE);
+ ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_NONE);
mask = ~0x23;
} else {
printf("(%s:%c:%d:%d): refuses %s tagged commands. "
ahd_name(ahd), devinfo->channel, devinfo->target,
devinfo->lun, tag_type == MSG_ORDERED_TASK
? "ordered" : "head of queue");
- ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC);
+ ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_BASIC);
mask = ~0x03;
}
if (status != CAM_SEL_TIMEOUT)
ahd_send_async(ahd, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+ CAM_LUN_WILDCARD, AC_SENT_BDR);
if (message != NULL && bootverbose)
printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
#endif
/* Notify the XPT that a bus reset occurred */
ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
+ CAM_LUN_WILDCARD, AC_BUS_RESET);
/*
* Revert to async/narrow transfers until we renegotiate.
struct seeprom_config *sc = ahd->seep_config;
unsigned long flags;
struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
- struct ahd_linux_target *targ = scsi_transport_target_data(starget);
struct ahd_devinfo devinfo;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
BUG_ON(*ahd_targp != NULL);
*ahd_targp = starget;
- memset(targ, 0, sizeof(*targ));
if (sc) {
int flags = sc->device_flags[starget->id];
{
struct ahd_softc *ahd =
*((struct ahd_softc **)sdev->host->hostdata);
- struct scsi_target *starget = sdev->sdev_target;
- struct ahd_linux_target *targ = scsi_transport_target_data(starget);
struct ahd_linux_device *dev;
if (bootverbose)
printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
- BUG_ON(targ->sdev[sdev->lun] != NULL);
-
dev = scsi_transport_device_data(sdev);
memset(dev, 0, sizeof(*dev));
*/
dev->maxtags = 0;
- targ->sdev[sdev->lun] = sdev;
-
return (0);
}
return 0;
}
-static void
-ahd_linux_slave_destroy(struct scsi_device *sdev)
-{
- struct ahd_softc *ahd;
- struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
- struct ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
-
- ahd = *((struct ahd_softc **)sdev->host->hostdata);
- if (bootverbose)
- printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
-
- BUG_ON(dev->active);
-
- targ->sdev[sdev->lun] = NULL;
-
-}
-
#if defined(__i386__)
/*
* Return the disk geometry for the given SCSI device.
.use_clustering = ENABLE_CLUSTERING,
.slave_alloc = ahd_linux_slave_alloc,
.slave_configure = ahd_linux_slave_configure,
- .slave_destroy = ahd_linux_slave_destroy,
.target_alloc = ahd_linux_target_alloc,
.target_destroy = ahd_linux_target_destroy,
};
ahd_platform_free(struct ahd_softc *ahd)
{
struct scsi_target *starget;
- int i, j;
+ int i;
if (ahd->platform_data != NULL) {
/* destroy all of the device and target objects */
for (i = 0; i < AHD_NUM_TARGETS; i++) {
starget = ahd->platform_data->starget[i];
if (starget != NULL) {
- for (j = 0; j < AHD_NUM_LUNS; j++) {
- struct ahd_linux_target *targ =
- scsi_transport_target_data(starget);
- if (targ->sdev[j] == NULL)
- continue;
- targ->sdev[j] = NULL;
- }
ahd->platform_data->starget[i] = NULL;
}
}
}
void
-ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
- ahd_queue_alg alg)
+ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
+ struct ahd_devinfo *devinfo, ahd_queue_alg alg)
{
- struct scsi_target *starget;
- struct ahd_linux_target *targ;
struct ahd_linux_device *dev;
- struct scsi_device *sdev;
int was_queuing;
int now_queuing;
- starget = ahd->platform_data->starget[devinfo->target];
- targ = scsi_transport_target_data(starget);
- BUG_ON(targ == NULL);
- sdev = targ->sdev[devinfo->lun];
if (sdev == NULL)
return;
tags = ahd_linux_user_tagdepth(ahd, &devinfo);
if (tags != 0 && sdev->tagged_supported != 0) {
- ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
+ ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_TAGGED);
+ ahd_send_async(ahd, devinfo.channel, devinfo.target,
+ devinfo.lun, AC_TRANSFER_NEG);
ahd_print_devinfo(ahd, &devinfo);
printf("Tagged Queuing enabled. Depth %d\n", tags);
} else {
- ahd_set_tags(ahd, &devinfo, AHD_QUEUE_NONE);
+ ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE);
+ ahd_send_async(ahd, devinfo.channel, devinfo.target,
+ devinfo.lun, AC_TRANSFER_NEG);
}
}
void
ahd_send_async(struct ahd_softc *ahd, char channel,
- u_int target, u_int lun, ac_code code, void *arg)
+ u_int target, u_int lun, ac_code code)
{
switch (code) {
case AC_TRANSFER_NEG:
}
ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
ahd_set_scsi_status(scb, SCSI_STATUS_OK);
- ahd_platform_set_tags(ahd, &devinfo,
+ ahd_platform_set_tags(ahd, sdev, &devinfo,
(dev->flags & AHD_DEV_Q_BASIC)
? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
break;
* as if the target returned BUSY SCSI status.
*/
dev->openings = 1;
- ahd_platform_set_tags(ahd, &devinfo,
+ ahd_platform_set_tags(ahd, sdev, &devinfo,
(dev->flags & AHD_DEV_Q_BASIC)
? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
if (!ahd_linux_transport_template)
return -ENODEV;
- scsi_transport_reserve_target(ahd_linux_transport_template,
- sizeof(struct ahd_linux_target));
scsi_transport_reserve_device(ahd_linux_transport_template,
sizeof(struct ahd_linux_device));
AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
} ahd_linux_dev_flags;
-struct ahd_linux_target;
struct ahd_linux_device {
TAILQ_ENTRY(ahd_linux_device) links;
#define AHD_OTAG_THRESH 500
};
-struct ahd_linux_target {
- struct scsi_device *sdev[AHD_NUM_LUNS];
- struct ahd_transinfo last_tinfo;
- struct ahd_softc *ahd;
-};
-
/********************* Definitions Required by the Core ***********************/
/*
* Number of SG segments we require. So long as the S/G segments for
}
}
-void ahd_platform_set_tags(struct ahd_softc *ahd,
+void ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
struct ahd_devinfo *devinfo, ahd_queue_alg);
int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
char channel, int lun, u_int tag,
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahd_done(struct ahd_softc*, struct scb*);
void ahd_send_async(struct ahd_softc *, char channel,
- u_int target, u_int lun, ac_code, void *);
+ u_int target, u_int lun, ac_code);
void ahd_print_path(struct ahd_softc *, struct scb *);
#ifdef CONFIG_PCI
static void ahd_dump_target_state(struct ahd_softc *ahd,
struct info_str *info,
u_int our_id, char channel,
- u_int target_id, u_int target_offset);
+ u_int target_id);
static void ahd_dump_device_state(struct info_str *info,
struct scsi_device *sdev);
static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
static void
ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
- u_int our_id, char channel, u_int target_id,
- u_int target_offset)
+ u_int our_id, char channel, u_int target_id)
{
- struct ahd_linux_target *targ;
struct scsi_target *starget;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahd_format_transinfo(info, &tinfo->user);
- starget = ahd->platform_data->starget[target_offset];
+ starget = ahd->platform_data->starget[target_id];
if (starget == NULL)
return;
- targ = scsi_transport_target_data(starget);
copy_info(info, "\tGoal: ");
ahd_format_transinfo(info, &tinfo->goal);
for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
struct scsi_device *dev;
- dev = targ->sdev[lun];
+ dev = scsi_device_lookup_by_target(starget, lun);
if (dev == NULL)
continue;
copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahd->scb_data.numscbs, AHD_NSEG);
- max_targ = 15;
+ max_targ = 16;
if (ahd->seep_config == NULL)
copy_info(&info, "No Serial EEPROM\n");
copy_info(&info, "\n");
if ((ahd->features & AHD_WIDE) == 0)
- max_targ = 7;
+ max_targ = 8;
- for (i = 0; i <= max_targ; i++) {
+ for (i = 0; i < max_targ; i++) {
ahd_dump_target_state(ahd, &info, ahd->our_id, 'A',
- /*target_id*/i, /*target_offset*/i);
+ /*target_id*/i);
}
retval = info.pos > info.offset ? info.pos - info.offset : 0;
done:
unsigned int base_io, tmport, error,n;
unsigned char host_id;
struct Scsi_Host *shpnt = NULL;
- struct atp_unit atp_dev, *p;
+ struct atp_unit *atpdev, *p;
unsigned char setupdata[2][16];
int count = 0;
-
+
+ atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
+ if (!atpdev)
+ return -ENOMEM;
+
if (pci_enable_device(pdev))
- return -EIO;
+ goto err_eio;
if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
} else {
printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
- return -EIO;
+ goto err_eio;
}
- memset(&atp_dev, 0, sizeof atp_dev);
/*
* It's probably easier to weed out some revisions like
* this than via the PCI device table
*/
if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
- error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
- if (atp_dev.chip_ver < 2)
- return -EIO;
+ error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
+ if (atpdev->chip_ver < 2)
+ goto err_eio;
}
switch (ent->device) {
case ATP880_DEVID1:
case ATP880_DEVID2:
case ATP885_DEVID:
- atp_dev.chip_ver = 0x04;
+ atpdev->chip_ver = 0x04;
default:
break;
}
base_io = pci_resource_start(pdev, 0);
base_io &= 0xfffffff8;
-
+
if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
- error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+ error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
host_id = inb(base_io + 0x39);
printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
" IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
- atp_dev.ioport[0] = base_io + 0x40;
- atp_dev.pciport[0] = base_io + 0x28;
- atp_dev.dev_id = ent->device;
- atp_dev.host_id[0] = host_id;
+ atpdev->ioport[0] = base_io + 0x40;
+ atpdev->pciport[0] = base_io + 0x28;
+ atpdev->dev_id = ent->device;
+ atpdev->host_id[0] = host_id;
tmport = base_io + 0x22;
- atp_dev.scam_on = inb(tmport);
+ atpdev->scam_on = inb(tmport);
tmport += 0x13;
- atp_dev.global_map[0] = inb(tmport);
+ atpdev->global_map[0] = inb(tmport);
tmport += 0x07;
- atp_dev.ultra_map[0] = inw(tmport);
+ atpdev->ultra_map[0] = inw(tmport);
n = 0x3f09;
next_fblk_880:
if (inb(base_io + 0x30) == 0xff)
goto flash_ok_880;
- atp_dev.sp[0][m++] = inb(base_io + 0x30);
- atp_dev.sp[0][m++] = inb(base_io + 0x31);
- atp_dev.sp[0][m++] = inb(base_io + 0x32);
- atp_dev.sp[0][m++] = inb(base_io + 0x33);
+ atpdev->sp[0][m++] = inb(base_io + 0x30);
+ atpdev->sp[0][m++] = inb(base_io + 0x31);
+ atpdev->sp[0][m++] = inb(base_io + 0x32);
+ atpdev->sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34);
n += 0x0002;
- atp_dev.sp[0][m++] = inb(base_io + 0x30);
- atp_dev.sp[0][m++] = inb(base_io + 0x31);
- atp_dev.sp[0][m++] = inb(base_io + 0x32);
- atp_dev.sp[0][m++] = inb(base_io + 0x33);
+ atpdev->sp[0][m++] = inb(base_io + 0x30);
+ atpdev->sp[0][m++] = inb(base_io + 0x31);
+ atpdev->sp[0][m++] = inb(base_io + 0x32);
+ atpdev->sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34);
n += 0x0002;
- atp_dev.sp[0][m++] = inb(base_io + 0x30);
- atp_dev.sp[0][m++] = inb(base_io + 0x31);
- atp_dev.sp[0][m++] = inb(base_io + 0x32);
- atp_dev.sp[0][m++] = inb(base_io + 0x33);
+ atpdev->sp[0][m++] = inb(base_io + 0x30);
+ atpdev->sp[0][m++] = inb(base_io + 0x31);
+ atpdev->sp[0][m++] = inb(base_io + 0x32);
+ atpdev->sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34);
n += 0x0002;
- atp_dev.sp[0][m++] = inb(base_io + 0x30);
- atp_dev.sp[0][m++] = inb(base_io + 0x31);
- atp_dev.sp[0][m++] = inb(base_io + 0x32);
- atp_dev.sp[0][m++] = inb(base_io + 0x33);
+ atpdev->sp[0][m++] = inb(base_io + 0x30);
+ atpdev->sp[0][m++] = inb(base_io + 0x31);
+ atpdev->sp[0][m++] = inb(base_io + 0x32);
+ atpdev->sp[0][m++] = inb(base_io + 0x33);
n += 0x0018;
goto next_fblk_880;
flash_ok_880:
outw(0, base_io + 0x34);
- atp_dev.ultra_map[0] = 0;
- atp_dev.async[0] = 0;
+ atpdev->ultra_map[0] = 0;
+ atpdev->async[0] = 0;
for (k = 0; k < 16; k++) {
n = 1;
n = n << k;
- if (atp_dev.sp[0][k] > 1) {
- atp_dev.ultra_map[0] |= n;
+ if (atpdev->sp[0][k] > 1) {
+ atpdev->ultra_map[0] |= n;
} else {
- if (atp_dev.sp[0][k] == 0)
- atp_dev.async[0] |= n;
+ if (atpdev->sp[0][k] == 0)
+ atpdev->async[0] |= n;
}
}
- atp_dev.async[0] = ~(atp_dev.async[0]);
- outb(atp_dev.global_map[0], base_io + 0x35);
+ atpdev->async[0] = ~(atpdev->async[0]);
+ outb(atpdev->global_map[0], base_io + 0x35);
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
- return -ENOMEM;
+ goto err_nomem;
p = (struct atp_unit *)&shpnt->hostdata;
- atp_dev.host = shpnt;
- atp_dev.pdev = pdev;
+ atpdev->host = shpnt;
+ atpdev->pdev = pdev;
pci_set_drvdata(pdev, p);
- memcpy(p, &atp_dev, sizeof atp_dev);
+ memcpy(p, atpdev, sizeof(*atpdev));
if (atp870u_init_tables(shpnt) < 0) {
printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
goto unregister;
printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n"
, base_io, pdev->irq);
- atp_dev.pdev = pdev;
- atp_dev.dev_id = ent->device;
- atp_dev.baseport = base_io;
- atp_dev.ioport[0] = base_io + 0x80;
- atp_dev.ioport[1] = base_io + 0xc0;
- atp_dev.pciport[0] = base_io + 0x40;
- atp_dev.pciport[1] = base_io + 0x50;
+ atpdev->pdev = pdev;
+ atpdev->dev_id = ent->device;
+ atpdev->baseport = base_io;
+ atpdev->ioport[0] = base_io + 0x80;
+ atpdev->ioport[1] = base_io + 0xc0;
+ atpdev->pciport[0] = base_io + 0x40;
+ atpdev->pciport[1] = base_io + 0x50;
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
- return -ENOMEM;
+ goto err_nomem;
p = (struct atp_unit *)&shpnt->hostdata;
- atp_dev.host = shpnt;
- atp_dev.pdev = pdev;
+ atpdev->host = shpnt;
+ atpdev->pdev = pdev;
pci_set_drvdata(pdev, p);
- memcpy(p, &atp_dev, sizeof(struct atp_unit));
+ memcpy(p, atpdev, sizeof(struct atp_unit));
if (atp870u_init_tables(shpnt) < 0)
goto unregister;
printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
- atp_dev.ioport[0] = base_io;
- atp_dev.pciport[0] = base_io + 0x20;
- atp_dev.dev_id = ent->device;
+ atpdev->ioport[0] = base_io;
+ atpdev->pciport[0] = base_io + 0x20;
+ atpdev->dev_id = ent->device;
host_id &= 0x07;
- atp_dev.host_id[0] = host_id;
+ atpdev->host_id[0] = host_id;
tmport = base_io + 0x22;
- atp_dev.scam_on = inb(tmport);
+ atpdev->scam_on = inb(tmport);
tmport += 0x0b;
- atp_dev.global_map[0] = inb(tmport++);
- atp_dev.ultra_map[0] = inw(tmport);
+ atpdev->global_map[0] = inb(tmport++);
+ atpdev->ultra_map[0] = inw(tmport);
- if (atp_dev.ultra_map[0] == 0) {
- atp_dev.scam_on = 0x00;
- atp_dev.global_map[0] = 0x20;
- atp_dev.ultra_map[0] = 0xffff;
+ if (atpdev->ultra_map[0] == 0) {
+ atpdev->scam_on = 0x00;
+ atpdev->global_map[0] = 0x20;
+ atpdev->ultra_map[0] = 0xffff;
}
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
- return -ENOMEM;
+ goto err_nomem;
p = (struct atp_unit *)&shpnt->hostdata;
- atp_dev.host = shpnt;
- atp_dev.pdev = pdev;
+ atpdev->host = shpnt;
+ atpdev->pdev = pdev;
pci_set_drvdata(pdev, p);
- memcpy(p, &atp_dev, sizeof atp_dev);
+ memcpy(p, atpdev, sizeof(*atpdev));
if (atp870u_init_tables(shpnt) < 0)
goto unregister;
}
spin_lock_irqsave(shpnt->host_lock, flags);
- if (atp_dev.chip_ver > 0x07) { /* check if atp876 chip then enable terminator */
+ if (atpdev->chip_ver > 0x07) { /* check if atp876 chip then enable terminator */
tmport = base_io + 0x3e;
outb(0x00, tmport);
}
outb((inb(tmport) & 0xef), tmport);
tmport++;
outb((inb(tmport) | 0x20), tmport);
- if (atp_dev.chip_ver == 4)
+ if (atpdev->chip_ver == 4)
shpnt->max_id = 16;
else
shpnt->max_id = 8;
printk("atp870u_prob:unregister\n");
scsi_host_put(shpnt);
return -1;
+err_eio:
+ kfree(atpdev);
+ return -EIO;
+err_nomem:
+ kfree(atpdev);
+ return -ENOMEM;
}
/* The abort command does not leave the device in a clean state where
struct ibmvscsi_host_data *hostdata)
{
u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
+ int request_status;
int rc;
/* If we have exhausted our request limit, just fail this request.
* (such as task management requests) that the mid layer may think we
* can handle more requests (can_queue) when we actually can't
*/
- if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
- (atomic_dec_if_positive(&hostdata->request_limit) < 0))
- goto send_error;
+ if (evt_struct->crq.format == VIOSRP_SRP_FORMAT) {
+ request_status =
+ atomic_dec_if_positive(&hostdata->request_limit);
+ /* If request limit was -1 when we started, it is now even
+ * less than that
+ */
+ if (request_status < -1)
+ goto send_error;
+ /* Otherwise, if we have run out of requests */
+ else if (request_status < 0)
+ goto send_busy;
+ }
/* Copy the IU into the transfer area */
*evt_struct->xfer_iu = evt_struct->iu;
return 0;
- send_error:
+ send_busy:
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
+
+ send_error:
+ unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
+
+ if (evt_struct->cmnd != NULL) {
+ evt_struct->cmnd->result = DID_ERROR << 16;
+ evt_struct->cmnd_done(evt_struct->cmnd);
+ } else if (evt_struct->done)
+ evt_struct->done(evt_struct);
+
+ free_event_struct(&hostdata->pool, evt_struct);
+ return 0;
}
/**
return;
case 0xFF: /* Hypervisor telling us the connection is closed */
scsi_block_requests(hostdata->host);
+ atomic_set(&hostdata->request_limit, 0);
if (crq->format == 0x06) {
/* We need to re-setup the interpartition connection */
printk(KERN_INFO
"ibmvscsi: Re-enabling adapter!\n");
- atomic_set(&hostdata->request_limit, -1);
purge_requests(hostdata, DID_REQUEUE);
- if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
- hostdata) == 0)
- if (ibmvscsi_send_crq(hostdata,
- 0xC001000000000000LL, 0))
+ if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
+ hostdata) == 0) ||
+ (ibmvscsi_send_crq(hostdata,
+ 0xC001000000000000LL, 0))) {
+ atomic_set(&hostdata->request_limit,
+ -1);
printk(KERN_ERR
- "ibmvscsi: transmit error after"
+ "ibmvscsi: error after"
" enable\n");
+ }
} else {
printk(KERN_INFO
"ibmvscsi: Virtual adapter failed rc %d!\n",
crq->format);
- atomic_set(&hostdata->request_limit, -1);
purge_requests(hostdata, DID_ERROR);
- ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+ if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
+ hostdata)) ||
+ (ibmvscsi_send_crq(hostdata,
+ 0xC001000000000000LL, 0))) {
+ atomic_set(&hostdata->request_limit,
+ -1);
+ printk(KERN_ERR
+ "ibmvscsi: error after reset\n");
+ }
}
scsi_unblock_requests(hostdata->host);
return;
struct Scsi_Host *host;
struct device *dev = &vdev->dev;
unsigned long wait_switch = 0;
+ int rc;
vdev->dev.driver_data = NULL;
atomic_set(&hostdata->request_limit, -1);
hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
- if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
- max_requests) != 0) {
+ rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+ if (rc != 0 && rc != H_RESOURCE) {
printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
goto init_crq_failed;
}
* to fail if the other end is not acive. In that case we don't
* want to scan
*/
- if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0) {
+ if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+ || rc == H_RESOURCE) {
/*
* Wait around max init_timeout secs for the adapter to finish
* initializing. When we are done initializing, we will have a
int max_requests)
{
int rc;
+ int retrc;
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
gather_partition_info();
set_adapter_info(hostdata);
- rc = plpar_hcall_norets(H_REG_CRQ,
+ retrc = rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
if (rc == H_RESOURCE)
tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
(unsigned long)hostdata);
- return 0;
+ return retrc;
req_irq_failed:
do {
static int
iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
- uint32_t value)
+ char *buf, int buflen)
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ int value;
switch(param) {
case ISCSI_PARAM_MAX_RECV_DLENGTH: {
char *saveptr = tcp_conn->data;
gfp_t flags = GFP_KERNEL;
+ sscanf(buf, "%d", &value);
if (tcp_conn->data_size >= value) {
- conn->max_recv_dlength = value;
+ iscsi_set_param(cls_conn, param, buf, buflen);
break;
}
else
free_pages((unsigned long)saveptr,
get_order(tcp_conn->data_size));
- conn->max_recv_dlength = value;
+ iscsi_set_param(cls_conn, param, buf, buflen);
tcp_conn->data_size = value;
- }
- break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- conn->max_xmit_dlength = value;
break;
+ }
case ISCSI_PARAM_HDRDGST_EN:
- conn->hdrdgst_en = value;
+ iscsi_set_param(cls_conn, param, buf, buflen);
tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
if (conn->hdrdgst_en) {
tcp_conn->hdr_size += sizeof(__u32);
}
break;
case ISCSI_PARAM_DATADGST_EN:
- conn->datadgst_en = value;
+ iscsi_set_param(cls_conn, param, buf, buflen);
if (conn->datadgst_en) {
if (!tcp_conn->data_tx_tfm)
tcp_conn->data_tx_tfm =
tcp_conn->sendpage = conn->datadgst_en ?
sock_no_sendpage : tcp_conn->sock->ops->sendpage;
break;
- case ISCSI_PARAM_INITIAL_R2T_EN:
- session->initial_r2t_en = value;
- break;
case ISCSI_PARAM_MAX_R2T:
+ sscanf(buf, "%d", &value);
if (session->max_r2t == roundup_pow_of_two(value))
break;
iscsi_r2tpool_free(session);
- session->max_r2t = value;
+ iscsi_set_param(cls_conn, param, buf, buflen);
if (session->max_r2t & (session->max_r2t - 1))
session->max_r2t = roundup_pow_of_two(session->max_r2t);
if (iscsi_r2tpool_alloc(session))
return -ENOMEM;
break;
- case ISCSI_PARAM_IMM_DATA_EN:
- session->imm_data_en = value;
- break;
- case ISCSI_PARAM_FIRST_BURST:
- session->first_burst = value;
- break;
- case ISCSI_PARAM_MAX_BURST:
- session->max_burst = value;
- break;
- case ISCSI_PARAM_PDU_INORDER_EN:
- session->pdu_inorder_en = value;
- break;
- case ISCSI_PARAM_DATASEQ_INORDER_EN:
- session->dataseq_inorder_en = value;
- break;
- case ISCSI_PARAM_ERL:
- session->erl = value;
- break;
- case ISCSI_PARAM_IFMARKER_EN:
- BUG_ON(value);
- session->ifmarker_en = value;
- break;
- case ISCSI_PARAM_OFMARKER_EN:
- BUG_ON(value);
- session->ofmarker_en = value;
- break;
- case ISCSI_PARAM_EXP_STATSN:
- conn->exp_statsn = value;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int
-iscsi_session_get_param(struct iscsi_cls_session *cls_session,
- enum iscsi_param param, uint32_t *value)
-{
- struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
- struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
-
- switch(param) {
- case ISCSI_PARAM_INITIAL_R2T_EN:
- *value = session->initial_r2t_en;
- break;
- case ISCSI_PARAM_MAX_R2T:
- *value = session->max_r2t;
- break;
- case ISCSI_PARAM_IMM_DATA_EN:
- *value = session->imm_data_en;
- break;
- case ISCSI_PARAM_FIRST_BURST:
- *value = session->first_burst;
- break;
- case ISCSI_PARAM_MAX_BURST:
- *value = session->max_burst;
- break;
- case ISCSI_PARAM_PDU_INORDER_EN:
- *value = session->pdu_inorder_en;
- break;
- case ISCSI_PARAM_DATASEQ_INORDER_EN:
- *value = session->dataseq_inorder_en;
- break;
- case ISCSI_PARAM_ERL:
- *value = session->erl;
- break;
- case ISCSI_PARAM_IFMARKER_EN:
- *value = session->ifmarker_en;
- break;
- case ISCSI_PARAM_OFMARKER_EN:
- *value = session->ofmarker_en;
- break;
default:
- return -EINVAL;
+ return iscsi_set_param(cls_conn, param, buf, buflen);
}
return 0;
}
static int
-iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
- enum iscsi_param param, uint32_t *value)
+iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, char *buf)
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct inet_sock *inet;
+ struct ipv6_pinfo *np;
+ struct sock *sk;
+ int len;
switch(param) {
- case ISCSI_PARAM_MAX_RECV_DLENGTH:
- *value = conn->max_recv_dlength;
- break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- *value = conn->max_xmit_dlength;
- break;
- case ISCSI_PARAM_HDRDGST_EN:
- *value = conn->hdrdgst_en;
- break;
- case ISCSI_PARAM_DATADGST_EN:
- *value = conn->datadgst_en;
- break;
case ISCSI_PARAM_CONN_PORT:
mutex_lock(&conn->xmitmutex);
if (!tcp_conn->sock) {
}
inet = inet_sk(tcp_conn->sock->sk);
- *value = be16_to_cpu(inet->dport);
+ len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
mutex_unlock(&conn->xmitmutex);
- case ISCSI_PARAM_EXP_STATSN:
- *value = conn->exp_statsn;
break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
- enum iscsi_param param, char *buf)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct sock *sk;
- struct inet_sock *inet;
- struct ipv6_pinfo *np;
- int len = 0;
-
- switch (param) {
case ISCSI_PARAM_CONN_ADDRESS:
mutex_lock(&conn->xmitmutex);
if (!tcp_conn->sock) {
mutex_unlock(&conn->xmitmutex);
break;
default:
- return -EINVAL;
+ return iscsi_conn_get_param(cls_conn, param, buf);
}
return len;
ISCSI_ERL |
ISCSI_CONN_PORT |
ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN,
+ ISCSI_EXP_STATSN |
+ ISCSI_PERSISTENT_PORT |
+ ISCSI_PERSISTENT_ADDRESS |
+ ISCSI_TARGET_NAME |
+ ISCSI_TPGT,
.host_template = &iscsi_sht,
.conndata_size = sizeof(struct iscsi_conn),
.max_conn = 1,
.bind_conn = iscsi_tcp_conn_bind,
.destroy_conn = iscsi_tcp_conn_destroy,
.set_param = iscsi_conn_set_param,
- .get_conn_param = iscsi_conn_get_param,
- .get_conn_str_param = iscsi_conn_get_str_param,
+ .get_conn_param = iscsi_tcp_conn_get_param,
.get_session_param = iscsi_session_get_param,
.start_conn = iscsi_conn_start,
.stop_conn = iscsi_conn_stop,
if (scsi_add_host(shost, NULL))
goto add_host_fail;
+ if (!try_module_get(iscsit->owner))
+ goto cls_session_fail;
+
cls_session = iscsi_create_session(shost, iscsit, 0);
if (!cls_session)
- goto cls_session_fail;
+ goto module_put;
*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
return cls_session;
+module_put:
+ module_put(iscsit->owner);
cls_session_fail:
scsi_remove_host(shost);
add_host_fail:
iscsi_destroy_session(cls_session);
scsi_host_put(shost);
+ module_put(cls_session->transport->owner);
}
EXPORT_SYMBOL_GPL(iscsi_session_teardown);
}
EXPORT_SYMBOL_GPL(iscsi_conn_bind);
+
+int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, char *buf, int buflen)
+{
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_session *session = conn->session;
+ uint32_t value;
+
+ switch(param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ sscanf(buf, "%d", &conn->max_recv_dlength);
+ break;
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ sscanf(buf, "%d", &conn->max_xmit_dlength);
+ break;
+ case ISCSI_PARAM_HDRDGST_EN:
+ sscanf(buf, "%d", &conn->hdrdgst_en);
+ break;
+ case ISCSI_PARAM_DATADGST_EN:
+ sscanf(buf, "%d", &conn->datadgst_en);
+ break;
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ sscanf(buf, "%d", &session->initial_r2t_en);
+ break;
+ case ISCSI_PARAM_MAX_R2T:
+ sscanf(buf, "%d", &session->max_r2t);
+ break;
+ case ISCSI_PARAM_IMM_DATA_EN:
+ sscanf(buf, "%d", &session->imm_data_en);
+ break;
+ case ISCSI_PARAM_FIRST_BURST:
+ sscanf(buf, "%d", &session->first_burst);
+ break;
+ case ISCSI_PARAM_MAX_BURST:
+ sscanf(buf, "%d", &session->max_burst);
+ break;
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ sscanf(buf, "%d", &session->pdu_inorder_en);
+ break;
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ sscanf(buf, "%d", &session->dataseq_inorder_en);
+ break;
+ case ISCSI_PARAM_ERL:
+ sscanf(buf, "%d", &session->erl);
+ break;
+ case ISCSI_PARAM_IFMARKER_EN:
+ sscanf(buf, "%d", &value);
+ BUG_ON(value);
+ break;
+ case ISCSI_PARAM_OFMARKER_EN:
+ sscanf(buf, "%d", &value);
+ BUG_ON(value);
+ break;
+ case ISCSI_PARAM_EXP_STATSN:
+ sscanf(buf, "%u", &conn->exp_statsn);
+ break;
+ case ISCSI_PARAM_TARGET_NAME:
+ /* this should not change between logins */
+ if (session->targetname)
+ break;
+
+ session->targetname = kstrdup(buf, GFP_KERNEL);
+ if (!session->targetname)
+ return -ENOMEM;
+ break;
+ case ISCSI_PARAM_TPGT:
+ sscanf(buf, "%d", &session->tpgt);
+ break;
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ sscanf(buf, "%d", &conn->persistent_port);
+ break;
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ /*
+ * this is the address returned in discovery so it should
+ * not change between logins.
+ */
+ if (conn->persistent_address)
+ break;
+
+ conn->persistent_address = kstrdup(buf, GFP_KERNEL);
+ if (!conn->persistent_address)
+ return -ENOMEM;
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_set_param);
+
+int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ enum iscsi_param param, char *buf)
+{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ int len;
+
+ switch(param) {
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ len = sprintf(buf, "%d\n", session->initial_r2t_en);
+ break;
+ case ISCSI_PARAM_MAX_R2T:
+ len = sprintf(buf, "%hu\n", session->max_r2t);
+ break;
+ case ISCSI_PARAM_IMM_DATA_EN:
+ len = sprintf(buf, "%d\n", session->imm_data_en);
+ break;
+ case ISCSI_PARAM_FIRST_BURST:
+ len = sprintf(buf, "%u\n", session->first_burst);
+ break;
+ case ISCSI_PARAM_MAX_BURST:
+ len = sprintf(buf, "%u\n", session->max_burst);
+ break;
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ len = sprintf(buf, "%d\n", session->pdu_inorder_en);
+ break;
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ len = sprintf(buf, "%d\n", session->dataseq_inorder_en);
+ break;
+ case ISCSI_PARAM_ERL:
+ len = sprintf(buf, "%d\n", session->erl);
+ break;
+ case ISCSI_PARAM_TARGET_NAME:
+ len = sprintf(buf, "%s\n", session->targetname);
+ break;
+ case ISCSI_PARAM_TPGT:
+ len = sprintf(buf, "%d\n", session->tpgt);
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(iscsi_session_get_param);
+
+int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, char *buf)
+{
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ int len;
+
+ switch(param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ len = sprintf(buf, "%u\n", conn->max_recv_dlength);
+ break;
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ len = sprintf(buf, "%u\n", conn->max_xmit_dlength);
+ break;
+ case ISCSI_PARAM_HDRDGST_EN:
+ len = sprintf(buf, "%d\n", conn->hdrdgst_en);
+ break;
+ case ISCSI_PARAM_DATADGST_EN:
+ len = sprintf(buf, "%d\n", conn->datadgst_en);
+ break;
+ case ISCSI_PARAM_IFMARKER_EN:
+ len = sprintf(buf, "%d\n", conn->ifmarker_en);
+ break;
+ case ISCSI_PARAM_OFMARKER_EN:
+ len = sprintf(buf, "%d\n", conn->ofmarker_en);
+ break;
+ case ISCSI_PARAM_EXP_STATSN:
+ len = sprintf(buf, "%u\n", conn->exp_statsn);
+ break;
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ len = sprintf(buf, "%d\n", conn->persistent_port);
+ break;
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ len = sprintf(buf, "%s\n", conn->persistent_address);
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
+
MODULE_AUTHOR("Mike Christie");
MODULE_DESCRIPTION("iSCSI library functions");
MODULE_LICENSE("GPL");
dma_addr_t slim2p_mapping;
uint16_t pci_cfg_value;
- struct semaphore hba_can_block;
int32_t hba_state;
#define LPFC_STATE_UNKNOWN 0 /* HBA state is unknown */
pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
- elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, 0, did,
+ elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
ELS_CMD_PLOGI);
if (!elsiocb)
return 1;
ndlp = (struct lpfc_nodelist *) pmb->context2;
xri = (uint16_t) ((unsigned long)(pmb->context1));
- pmb->context1 = 0;
- pmb->context2 = 0;
+ pmb->context1 = NULL;
+ pmb->context2 = NULL;
if (mb->mbxStatus) {
mempool_free( pmb, phba->mbox_mem_pool);
"10-port ", "PCIe"};
break;
default:
- m = (typeof(m)){ 0 };
+ m = (typeof(m)){ NULL };
break;
}
break;
default:
- m = (typeof(m)){ 0 };
+ m = (typeof(m)){ NULL };
break;
}
goto out_put_host;
host->unique_id = phba->brd_no;
- init_MUTEX(&phba->hba_can_block);
INIT_LIST_HEAD(&phba->ctrspbuflist);
INIT_LIST_HEAD(&phba->rnidrspbuflist);
INIT_LIST_HEAD(&phba->freebufList);
#define LPFC_ABORT_WAIT 2
-static inline void
-lpfc_block_requests(struct lpfc_hba * phba)
-{
- down(&phba->hba_can_block);
- scsi_block_requests(phba->host);
-}
-
-static inline void
-lpfc_unblock_requests(struct lpfc_hba * phba)
-{
- scsi_unblock_requests(phba->host);
- up(&phba->hba_can_block);
-}
-
/*
* This routine allocates a scsi buffer, which contains all the necessary
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
unsigned int loop_count = 0;
int ret = SUCCESS;
- lpfc_block_requests(phba);
spin_lock_irq(shost->host_lock);
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
cmnd->device->lun, cmnd->serial_number);
spin_unlock_irq(shost->host_lock);
- lpfc_unblock_requests(phba);
return ret;
}
int ret = FAILED;
int cnt, loopcnt;
- lpfc_block_requests(phba);
spin_lock_irq(shost->host_lock);
/*
* If target is not in a MAPPED state, delay the reset until
out:
spin_unlock_irq(shost->host_lock);
- lpfc_unblock_requests(phba);
return ret;
}
int cnt, loopcnt;
struct lpfc_scsi_buf * lpfc_cmd;
- lpfc_block_requests(phba);
spin_lock_irq(shost->host_lock);
lpfc_cmd = lpfc_get_scsi_buf(phba);
phba->brd_no, ret);
out:
spin_unlock_irq(shost->host_lock);
- lpfc_unblock_requests(phba);
return ret;
}
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.02.04
+ * Version : v00.00.03.01
*
* Authors:
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP
+ PCI_DEVICE_ID_LSI_SAS1064R, /* xscale IOP */
PCI_ANY_ID,
PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
+ PCI_DEVICE_ID_LSI_SAS1078R, /* ppc IOP */
PCI_ANY_ID,
PCI_ANY_ID,
},
+ {
+ PCI_VENDOR_ID_LSI_LOGIC,
+ PCI_DEVICE_ID_LSI_VERDE_ZCR, /* xscale IOP, vega */
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ },
{
PCI_VENDOR_ID_DELL,
- PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
+ PCI_DEVICE_ID_DELL_PERC5, /* xscale IOP */
PCI_ANY_ID,
PCI_ANY_ID,
},
* @regs: MFI register set
*/
static inline void
-megasas_disable_intr(struct megasas_register_set __iomem * regs)
+megasas_disable_intr(struct megasas_instance *instance)
{
u32 mask = 0x1f;
+ struct megasas_register_set __iomem *regs = instance->reg_set;
+
+ if(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078R)
+ mask = 0xffffffff;
+
writel(mask, ®s->outbound_intr_mask);
/* Dummy readl to force pci flush */
/*
* Bring it to READY state; assuming max wait 2 secs
*/
- megasas_disable_intr(instance->reg_set);
+ megasas_disable_intr(instance);
writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
max_wait = 10;
init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
+ /*
+ * disable the intr before firing the init frame to FW
+ */
+ megasas_disable_intr(instance);
+
/*
* Issue the init frame in polled mode
*/
megasas_mgmt_info.max_index--;
pci_set_drvdata(pdev, NULL);
- megasas_disable_intr(instance->reg_set);
+ megasas_disable_intr(instance);
free_irq(instance->pdev->irq, instance);
megasas_release_mfi(instance);
pci_set_drvdata(instance->pdev, NULL);
- megasas_disable_intr(instance->reg_set);
+ megasas_disable_intr(instance);
free_irq(instance->pdev->irq, instance);
/**
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.02.04"
-#define MEGASAS_RELDATE "Feb 03, 2006"
-#define MEGASAS_EXT_VERSION "Fri Feb 03 14:31:44 PST 2006"
+#define MEGASAS_VERSION "00.00.03.01"
+#define MEGASAS_RELDATE "May 14, 2006"
+#define MEGASAS_EXT_VERSION "Sun May 14 22:49:52 PDT 2006"
+
+/*
+ * Device IDs
+ */
+#define PCI_DEVICE_ID_LSI_SAS1078R 0x0060
+#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413
+
/*
* =====================================
* MegaRAID SAS MFI firmware definitions
#define MFI_POLL_TIMEOUT_SECS 10
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
-#define PCI_DEVICE_ID_LSI_SAS1078R 0x00000060
+
+/*
+* register set for both 1068 and 1078 controllers
+* structure extended for 1078 registers
+*/
struct megasas_register_set {
u32 reserved_0[4]; /*0000h*/
struct compat_iovec sgl[MAX_IOCTL_SGE];
} __attribute__ ((packed));
+#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket)
#endif
#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket)
-#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket)
#define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen)
struct megasas_mgmt_info {
*/
nsp32_do_bus_reset(data);
- ret = request_irq(host->irq, do_nsp32_isr,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM, "nsp32", data);
+ ret = request_irq(host->irq, do_nsp32_isr, IRQF_SHARED, "nsp32", data);
if (ret < 0) {
nsp32_msg(KERN_ERR, "Unable to allocate IRQ for NinjaSCSI32 "
"SCSI PCI controller. Interrupt: %d", host->irq);
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
- scsi_add_host (host, &PCIDEV->dev);
+ ret = scsi_add_host(host, &PCIDEV->dev);
+ if (ret) {
+ nsp32_msg(KERN_ERR, "failed to add scsi host");
+ goto free_region;
+ }
scsi_scan_host(host);
#endif
pci_set_drvdata(PCIDEV, host);
return DETECT_OK;
+ free_region:
+ release_region(host->io_port, host->n_io_port);
+
free_irq:
free_irq(host->irq, data);
/* Interrupt handler */
link->irq.Handler = &nspintr;
link->irq.Instance = info;
- link->irq.Attributes |= (IRQF_SHARED | IRQF_SAMPLE_RANDOM);
+ link->irq.Attributes |= IRQF_SHARED;
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
}
-static int
+static int __init
qla1280_get_token(char *str)
{
char *sep;
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
+ char *rbuf = (char *)ha->fw_dump;
if (ha->fw_dump_reading == 0)
return 0;
- if (off > ha->fw_dump_buffer_len)
- return 0;
- if (off + count > ha->fw_dump_buffer_len)
- count = ha->fw_dump_buffer_len - off;
+ if (off > ha->fw_dump_len)
+ return 0;
+ if (off + count > ha->fw_dump_len)
+ count = ha->fw_dump_len - off;
- memcpy(buf, &ha->fw_dump_buffer[off], count);
+ memcpy(buf, &rbuf[off], count);
return (count);
}
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
int reading;
- uint32_t dump_size;
if (off != 0)
return (0);
reading = simple_strtol(buf, NULL, 10);
switch (reading) {
case 0:
- if (ha->fw_dump_reading == 1) {
- qla_printk(KERN_INFO, ha,
- "Firmware dump cleared on (%ld).\n", ha->host_no);
+ if (!ha->fw_dump_reading)
+ break;
- vfree(ha->fw_dump_buffer);
- ha->fw_dump_buffer = NULL;
- ha->fw_dump_reading = 0;
- ha->fw_dumped = 0;
- }
+ qla_printk(KERN_INFO, ha,
+ "Firmware dump cleared on (%ld).\n", ha->host_no);
+
+ ha->fw_dump_reading = 0;
+ ha->fw_dumped = 0;
break;
case 1:
if (ha->fw_dumped && !ha->fw_dump_reading) {
ha->fw_dump_reading = 1;
- if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
- dump_size = FW_DUMP_SIZE_24XX;
- else {
- dump_size = FW_DUMP_SIZE_1M;
- if (ha->fw_memory_size < 0x20000)
- dump_size = FW_DUMP_SIZE_128K;
- else if (ha->fw_memory_size < 0x80000)
- dump_size = FW_DUMP_SIZE_512K;
- }
- ha->fw_dump_buffer = (char *)vmalloc(dump_size);
- if (ha->fw_dump_buffer == NULL) {
- qla_printk(KERN_WARNING, ha,
- "Unable to allocate memory for firmware "
- "dump buffer (%d).\n", dump_size);
-
- ha->fw_dump_reading = 0;
- return (count);
- }
qla_printk(KERN_INFO, ha,
- "Firmware dump ready for read on (%ld).\n",
+ "Raw firmware dump ready for read on (%ld).\n",
ha->host_no);
- memset(ha->fw_dump_buffer, 0, dump_size);
- ha->isp_ops.ascii_fw_dump(ha);
- ha->fw_dump_buffer_len = strlen(ha->fw_dump_buffer);
}
break;
+ case 2:
+ qla2x00_alloc_fw_dump(ha);
+ break;
}
return (count);
}
if (!capable(CAP_SYS_ADMIN) || off != 0)
return 0;
- if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
- return -ENOTSUPP;
-
/* Read NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size);
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
return 0;
- if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
- return -ENOTSUPP;
-
/* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
.write = qla2x00_sysfs_write_vpd,
};
+static ssize_t
+qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ uint16_t iter, addr, offset;
+ int rval;
+
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
+ return 0;
+
+ addr = 0xa0;
+ for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
+ iter++, offset += SFP_BLOCK_SIZE) {
+ if (iter == 4) {
+ /* Skip to next device address. */
+ addr = 0xa2;
+ offset = 0;
+ }
+
+ rval = qla2x00_read_sfp(ha, ha->sfp_data_dma, addr, offset,
+ SFP_BLOCK_SIZE);
+ if (rval != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to read SFP data (%x/%x/%x).\n", rval,
+ addr, offset);
+ count = 0;
+ break;
+ }
+ memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
+ buf += SFP_BLOCK_SIZE;
+ }
+
+ return count;
+}
+
+static struct bin_attribute sysfs_sfp_attr = {
+ .attr = {
+ .name = "sfp",
+ .mode = S_IRUSR | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = SFP_DEV_SIZE * 2,
+ .read = qla2x00_sysfs_read_sfp,
+};
+
void
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
{
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
sysfs_create_bin_file(&host->shost_gendev.kobj,
&sysfs_optrom_ctl_attr);
- sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
+ if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ sysfs_create_bin_file(&host->shost_gendev.kobj,
+ &sysfs_vpd_attr);
+ sysfs_create_bin_file(&host->shost_gendev.kobj,
+ &sysfs_sfp_attr);
+ }
}
void
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
sysfs_remove_bin_file(&host->shost_gendev.kobj,
&sysfs_optrom_ctl_attr);
- sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
+ if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ sysfs_remove_bin_file(&host->shost_gendev.kobj,
+ &sysfs_vpd_attr);
+ sysfs_remove_bin_file(&host->shost_gendev.kobj,
+ &sysfs_sfp_attr);
+ }
if (ha->beacon_blink_led == 1)
ha->isp_ops.beacon_off(ha);
#include <linux/delay.h>
-static int qla_uprintf(char **, char *, ...);
+static inline void
+qla2xxx_prep_dump(scsi_qla_host_t *ha, struct qla2xxx_fw_dump *fw_dump)
+{
+ fw_dump->fw_major_version = htonl(ha->fw_major_version);
+ fw_dump->fw_minor_version = htonl(ha->fw_minor_version);
+ fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version);
+ fw_dump->fw_attributes = htonl(ha->fw_attributes);
+
+ fw_dump->vendor = htonl(ha->pdev->vendor);
+ fw_dump->device = htonl(ha->pdev->device);
+ fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor);
+ fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device);
+}
+
+static inline void *
+qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
+{
+ /* Request queue. */
+ memcpy(ptr, ha->request_ring, ha->request_q_length *
+ sizeof(request_t));
+
+ /* Response queue. */
+ ptr += ha->request_q_length * sizeof(request_t);
+ memcpy(ptr, ha->response_ring, ha->response_q_length *
+ sizeof(response_t));
+
+ return ptr + (ha->response_q_length * sizeof(response_t));
+}
/**
* qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
"request...\n", ha->fw_dump);
goto qla2300_fw_dump_failed;
}
- fw = ha->fw_dump;
+ fw = &ha->fw_dump->isp.isp23;
+ qla2xxx_prep_dump(ha, ha->fw_dump);
rval = QLA_SUCCESS;
- fw->hccr = RD_REG_WORD(®->hccr);
+ fw->hccr = htons(RD_REG_WORD(®->hccr));
/* Pause RISC. */
WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
if (rval == QLA_SUCCESS) {
dmp_reg = (uint16_t __iomem *)(reg + 0);
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
- fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
- fw->risc_host_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40);
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
- fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x40);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++)
- fw->resp_dma_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->resp_dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x50);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
- fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x00);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0);
for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
- fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2000);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++)
- fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2200);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++)
- fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2400);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++)
- fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2600);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++)
- fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2800);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++)
- fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2A00);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++)
- fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2C00);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++)
- fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2E00);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++)
- fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x10);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++)
- fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->frame_buf_hdw_reg[cnt] =
+ htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x20);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++)
- fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x30);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++)
- fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
/* Reset RISC. */
WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
- fw->risc_ram[cnt] = mb2;
+ fw->risc_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
- fw->stack_ram[cnt] = mb2;
+ fw->stack_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
- fw->data_ram[cnt] = mb2;
+ fw->data_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
+ if (rval == QLA_SUCCESS)
+ qla2xxx_copy_queues(ha, &fw->data_ram[cnt]);
+
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Failed to dump firmware (%x)!!!\n", rval);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
-/**
- * qla2300_ascii_fw_dump() - Converts a binary firmware dump to ASCII.
- * @ha: HA context
- */
-void
-qla2300_ascii_fw_dump(scsi_qla_host_t *ha)
-{
- uint32_t cnt;
- char *uiter;
- char fw_info[30];
- struct qla2300_fw_dump *fw;
- uint32_t data_ram_cnt;
-
- uiter = ha->fw_dump_buffer;
- fw = ha->fw_dump;
-
- qla_uprintf(&uiter, "%s Firmware Version %s\n", ha->model_number,
- ha->isp_ops.fw_version_str(ha, fw_info));
-
- qla_uprintf(&uiter, "\n[==>BEG]\n");
-
- qla_uprintf(&uiter, "HCCR Register:\n%04x\n\n", fw->hccr);
-
- qla_uprintf(&uiter, "PBIU Registers:");
- for (cnt = 0; cnt < sizeof (fw->pbiu_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->pbiu_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nReqQ-RspQ-Risc2Host Status registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_host_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_host_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nMailbox Registers:");
- for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->mailbox_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nAuto Request Response DMA Registers:");
- for (cnt = 0; cnt < sizeof (fw->resp_dma_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->resp_dma_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nDMA Registers:");
- for (cnt = 0; cnt < sizeof (fw->dma_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->dma_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC Hardware Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_hdw_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_hdw_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP0 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp0_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp0_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP1 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp1_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp1_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP2 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp2_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp2_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP3 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp3_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp3_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP4 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp4_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp4_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP5 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp5_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp5_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP6 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp6_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp6_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP7 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp7_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp7_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nFrame Buffer Hardware Registers:");
- for (cnt = 0; cnt < sizeof (fw->frame_buf_hdw_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->frame_buf_hdw_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nFPM B0 Registers:");
- for (cnt = 0; cnt < sizeof (fw->fpm_b0_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->fpm_b0_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nFPM B1 Registers:");
- for (cnt = 0; cnt < sizeof (fw->fpm_b1_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->fpm_b1_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nCode RAM Dump:");
- for (cnt = 0; cnt < sizeof (fw->risc_ram) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n%04x: ", cnt + 0x0800);
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_ram[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nStack RAM Dump:");
- for (cnt = 0; cnt < sizeof (fw->stack_ram) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n%05x: ", cnt + 0x10000);
- }
- qla_uprintf(&uiter, "%04x ", fw->stack_ram[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nData RAM Dump:");
- data_ram_cnt = ha->fw_memory_size - 0x11000 + 1;
- for (cnt = 0; cnt < data_ram_cnt; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n%05x: ", cnt + 0x11000);
- }
- qla_uprintf(&uiter, "%04x ", fw->data_ram[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\n[<==END] ISP Debug Dump.");
-}
-
/**
* qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
* @ha: HA context
"request...\n", ha->fw_dump);
goto qla2100_fw_dump_failed;
}
- fw = ha->fw_dump;
+ fw = &ha->fw_dump->isp.isp21;
+ qla2xxx_prep_dump(ha, ha->fw_dump);
rval = QLA_SUCCESS;
- fw->hccr = RD_REG_WORD(®->hccr);
+ fw->hccr = htons(RD_REG_WORD(®->hccr));
/* Pause RISC. */
WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
if (rval == QLA_SUCCESS) {
dmp_reg = (uint16_t __iomem *)(reg + 0);
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
- fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
for (cnt = 0; cnt < ha->mbx_count; cnt++) {
if (cnt == 8) {
- dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xe0);
+ dmp_reg = (uint16_t __iomem *)
+ ((uint8_t __iomem *)reg + 0xe0);
}
- fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
}
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20);
for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
- fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x00);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0);
for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
- fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2000);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++)
- fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2100);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++)
- fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2200);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++)
- fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2300);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++)
- fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2400);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++)
- fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2500);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++)
- fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2600);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++)
- fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->pcr, 0x2700);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++)
- fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x10);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++)
- fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->frame_buf_hdw_reg[cnt] =
+ htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x20);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++)
- fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
WRT_REG_WORD(®->ctrl_status, 0x30);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++)
- fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+ fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
/* Reset the ISP. */
WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
- fw->risc_ram[cnt] = mb2;
+ fw->risc_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
+ if (rval == QLA_SUCCESS)
+ qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]);
+
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Failed to dump firmware (%x)!!!\n", rval);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
-/**
- * qla2100_ascii_fw_dump() - Converts a binary firmware dump to ASCII.
- * @ha: HA context
- */
-void
-qla2100_ascii_fw_dump(scsi_qla_host_t *ha)
-{
- uint32_t cnt;
- char *uiter;
- char fw_info[30];
- struct qla2100_fw_dump *fw;
-
- uiter = ha->fw_dump_buffer;
- fw = ha->fw_dump;
-
- qla_uprintf(&uiter, "%s Firmware Version %s\n", ha->model_number,
- ha->isp_ops.fw_version_str(ha, fw_info));
-
- qla_uprintf(&uiter, "\n[==>BEG]\n");
-
- qla_uprintf(&uiter, "HCCR Register:\n%04x\n\n", fw->hccr);
-
- qla_uprintf(&uiter, "PBIU Registers:");
- for (cnt = 0; cnt < sizeof (fw->pbiu_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->pbiu_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nMailbox Registers:");
- for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->mailbox_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nDMA Registers:");
- for (cnt = 0; cnt < sizeof (fw->dma_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->dma_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC Hardware Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_hdw_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_hdw_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP0 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp0_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp0_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP1 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp1_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp1_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP2 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp2_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp2_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP3 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp3_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp3_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP4 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp4_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp4_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP5 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp5_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp5_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP6 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp6_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp6_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC GP7 Registers:");
- for (cnt = 0; cnt < sizeof (fw->risc_gp7_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_gp7_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nFrame Buffer Hardware Registers:");
- for (cnt = 0; cnt < sizeof (fw->frame_buf_hdw_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->frame_buf_hdw_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nFPM B0 Registers:");
- for (cnt = 0; cnt < sizeof (fw->fpm_b0_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->fpm_b0_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nFPM B1 Registers:");
- for (cnt = 0; cnt < sizeof (fw->fpm_b1_reg) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n");
- }
- qla_uprintf(&uiter, "%04x ", fw->fpm_b1_reg[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\nRISC SRAM:");
- for (cnt = 0; cnt < sizeof (fw->risc_ram) / 2; cnt++) {
- if (cnt % 8 == 0) {
- qla_uprintf(&uiter, "\n%04x: ", cnt + 0x1000);
- }
- qla_uprintf(&uiter, "%04x ", fw->risc_ram[cnt]);
- }
-
- qla_uprintf(&uiter, "\n\n[<==END] ISP Debug Dump.");
-
- return;
-}
-
-static int
-qla_uprintf(char **uiter, char *fmt, ...)
-{
- int iter, len;
- char buf[128];
- va_list args;
-
- va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
- va_end(args);
-
- for (iter = 0; iter < len; iter++, *uiter += 1)
- *uiter[0] = buf[iter];
-
- return (len);
-}
-
-
void
qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
{
unsigned long flags;
struct qla24xx_fw_dump *fw;
uint32_t ext_mem_cnt;
+ void *eft;
risc_address = ext_mem_cnt = 0;
memset(mb, 0, sizeof(mb));
"request...\n", ha->fw_dump);
goto qla24xx_fw_dump_failed;
}
- fw = ha->fw_dump;
+ fw = &ha->fw_dump->isp.isp24;
+ qla2xxx_prep_dump(ha, ha->fw_dump);
rval = QLA_SUCCESS;
- fw->host_status = RD_REG_DWORD(®->host_status);
+ fw->host_status = htonl(RD_REG_DWORD(®->host_status));
/* Pause RISC. */
if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) {