Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (138 commits)
  [SCSI] libata: implement minimal transport template for ->eh_timed_out
  [SCSI] eliminate rphy allocation in favour of expander/end device allocation
  [SCSI] convert mptsas over to end_device/expander allocations
  [SCSI] allow displaying and setting of cache type via sysfs
  [SCSI] add scsi_mode_select to scsi_lib.c
  [SCSI] 3ware 9000 add big endian support
  [SCSI] qla2xxx: update MAINTAINERS
  [SCSI] scsi: move target_destroy call
  [SCSI] fusion - bump version
  [SCSI] fusion - expander hotplug suport in mptsas module
  [SCSI] fusion - exposing raid components in mptsas
  [SCSI] fusion - memory leak, and initializing fields
  [SCSI] fusion - exclosure misspelled
  [SCSI] fusion - cleanup mptsas event handling functions
  [SCSI] fusion - removing target_id/bus_id from the VirtDevice structure
  [SCSI] fusion - static fix's
  [SCSI] fusion - move some debug firmware event debug msgs to verbose level
  [SCSI] fusion - loginfo header update
  [SCSI] add scsi_reprobe_device
  [SCSI] megaraid_sas: fix extended timeout handling
  ...
This commit is contained in:
Linus Torvalds 2006-03-22 10:47:24 -08:00
Родитель 7cae7e26f2 30afc84cf7
Коммит 2152f85366
132 изменённых файлов: 35523 добавлений и 42706 удалений

Просмотреть файл

@ -2145,7 +2145,7 @@ S: Maintained
QLOGIC QLA2XXX FC-SCSI DRIVER QLOGIC QLA2XXX FC-SCSI DRIVER
P: Andrew Vasquez P: Andrew Vasquez
M: andrew.vasquez@qlogic.com M: linux-driver@qlogic.com
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
S: Supported S: Supported

Просмотреть файл

@ -536,6 +536,28 @@ void bus_rescan_devices(struct bus_type * bus)
bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
} }
/**
* device_reprobe - remove driver for a device and probe for a new driver
* @dev: the device to reprobe
*
* This function detaches the attached driver (if any) for the given
* device and restarts the driver probing process. It is intended
* to use if probing criteria changed during a devices lifetime and
* driver attachment should change accordingly.
*/
void device_reprobe(struct device *dev)
{
if (dev->driver) {
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
device_release_driver(dev);
if (dev->parent)
up(&dev->parent->sem);
}
bus_rescan_devices_helper(dev, NULL);
}
EXPORT_SYMBOL_GPL(device_reprobe);
struct bus_type * get_bus(struct bus_type * bus) struct bus_type * get_bus(struct bus_type * bus)
{ {

Просмотреть файл

@ -3251,8 +3251,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
clean4: clean4:
#ifdef CONFIG_CISS_SCSI_TAPE #ifdef CONFIG_CISS_SCSI_TAPE
if(hba[i]->scsi_rejects.complete) kfree(hba[i]->scsi_rejects.complete);
kfree(hba[i]->scsi_rejects.complete);
#endif #endif
kfree(hba[i]->cmd_pool_bits); kfree(hba[i]->cmd_pool_bits);
if(hba[i]->cmd_pool) if(hba[i]->cmd_pool)

Просмотреть файл

@ -9,6 +9,7 @@ config FUSION_SPI
tristate "Fusion MPT ScsiHost drivers for SPI" tristate "Fusion MPT ScsiHost drivers for SPI"
depends on PCI && SCSI depends on PCI && SCSI
select FUSION select FUSION
select SCSI_SPI_ATTRS
---help--- ---help---
SCSI HOST support for a parallel SCSI host adapters. SCSI HOST support for a parallel SCSI host adapters.

Просмотреть файл

@ -4,6 +4,7 @@
#EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
#EXTRA_CFLAGS += -DMPT_DEBUG_SG #EXTRA_CFLAGS += -DMPT_DEBUG_SG
#EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS
#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS
#EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_INIT
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL

Просмотреть файл

@ -3,38 +3,11 @@
* * * *
* Copyright 2003 LSI Logic Corporation. All rights reserved. * * Copyright 2003 LSI Logic Corporation. All rights reserved. *
* * * *
* This file is confidential and a trade secret of LSI Logic. The * * Description *
* receipt of or possession of this file does not convey any rights to * * ------------ *
* reproduce or disclose its contents or to manufacture, use, or sell * * This include file contains SAS firmware interface IOC Log Info codes *
* anything it may describe, in whole, or in part, without the specific *
* written consent of LSI Logic Corporation. *
* * * *
*************************************************************************** *-------------------------------------------------------------------------*
*
* Name: iopiIocLogInfo.h
* Title: SAS Firmware IOP Interface IOC Log Info Definitions
* Programmer: Guy Kendall
* Creation Date: September 24, 2003
*
* Version History
* ---------------
*
* Last Updated
* -------------
* Version %version: 22 %
* Date Updated %date_modified: %
* Programmer %created_by: nperucca %
*
* Date Who Description
* -------- --- -------------------------------------------------------
* 09/24/03 GWK Initial version
*
*
* Description
* ------------
* This include file contains SAS firmware interface IOC Log Info codes
*
*-------------------------------------------------------------------------
*/ */
#ifndef IOPI_IOCLOGINFO_H_INCLUDED #ifndef IOPI_IOCLOGINFO_H_INCLUDED
@ -57,6 +30,8 @@
#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000) #define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)
#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000) #define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)
#define IOC_LOGINFO_ORIGINATOR_MASK (0x0F000000)
/****************************************************************************/ /****************************************************************************/
/* LOGINFO_CODE defines */ /* LOGINFO_CODE defines */
/****************************************************************************/ /****************************************************************************/
@ -78,11 +53,27 @@
#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) #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 IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */
#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001)
#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002)
#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003)
#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004)
#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
/****************************************************************************/ /****************************************************************************/
/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
/****************************************************************************/ /****************************************************************************/
#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) #define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)
#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT (0x00010001)
#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION (0x00010011)
#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013)
#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY (0x00010018)
#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION (0x00010019)
#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT (0X0001001A)
#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0001001B)
#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED (0x0001001C)
#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) #define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)
#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) #define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) #define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
@ -97,6 +88,7 @@
#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) #define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) #define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)
#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */
#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */
#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */
@ -105,11 +97,23 @@
#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */
#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */
#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) #define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
#define PL_LOGINFO_CODE_RESET (0x00110000) #define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */
#define PL_LOGINFO_CODE_ABORT (0x00120000) #define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */
#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) #define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) #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_SUB_CODE_OPEN_FAILURE (0x00000100) #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 */
#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0000011B)
#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */
#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120)
#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */
#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */
#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) #define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) #define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)
@ -123,26 +127,39 @@
#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) #define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)
#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) #define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)
#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) #define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)
#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01)
#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00)
#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */ #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */ #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */
#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */ #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */
#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */ #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */
#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */ #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */
#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */ #define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */
#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */
#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */
#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */
#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */
#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */
#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */
#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ #define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */
#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ #define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */
#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ #define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */
#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */
#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */ #define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */ #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */ #define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */
#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */ #define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */
#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/ #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */
#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */
#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */
#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode */
/****************************************************************************/ /****************************************************************************/

Просмотреть файл

@ -180,6 +180,7 @@ static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
/* module entry point */ /* module entry point */
static int __init fusion_init (void); static int __init fusion_init (void);
@ -428,7 +429,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
results = ProcessEventNotification(ioc, pEvReply, &evHandlers); results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
if (results != evHandlers) { if (results != evHandlers) {
/* CHECKME! Any special handling needed here? */ /* CHECKME! Any special handling needed here? */
devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
ioc->name, evHandlers, results)); ioc->name, evHandlers, results));
} }
@ -438,10 +439,10 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
*/ */
if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
freereq = 0; freereq = 0;
devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
ioc->name, pEvReply)); ioc->name, pEvReply));
} else { } else {
devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
ioc->name, pEvReply)); ioc->name, pEvReply));
} }
@ -1120,65 +1121,6 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
return -1; return -1;
} }
int
mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
{
int loop_count = 30 * 4; /* Wait 30 seconds */
int status = -1; /* -1 means failed to get board READY */
do {
spin_lock(&ioc->initializing_hba_lock);
if (ioc->initializing_hba_lock_flag == 0) {
ioc->initializing_hba_lock_flag=1;
spin_unlock(&ioc->initializing_hba_lock);
status = 0;
break;
}
spin_unlock(&ioc->initializing_hba_lock);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/4);
} while (--loop_count);
return status;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
* @ioc: Pointer to MPT adapter structure
* @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
*
* This routine performs all the steps necessary to bring the IOC
* to a OPERATIONAL state.
*
* Special Note: This function was added with spin lock's so as to allow
* the dv(domain validation) work thread to succeed on the other channel
* that maybe occuring at the same time when this function is called.
* Without this lock, the dv would fail when message frames were
* requested during hba bringup on the alternate ioc.
*/
static int
mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
{
int r;
if(ioc->alt_ioc) {
if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
return r;
}
r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
CAN_SLEEP);
if(ioc->alt_ioc) {
spin_lock(&ioc->alt_ioc->initializing_hba_lock);
ioc->alt_ioc->initializing_hba_lock_flag=0;
spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
}
return r;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* /*
* mpt_attach - Install a PCI intelligent MPT adapter. * mpt_attach - Install a PCI intelligent MPT adapter.
@ -1482,7 +1424,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
*/ */
mpt_detect_bound_ports(ioc, pdev); mpt_detect_bound_ports(ioc, pdev);
if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
CAN_SLEEP)) != 0){
printk(KERN_WARNING MYNAM printk(KERN_WARNING MYNAM
": WARNING - %s did not initialize properly! (%d)\n", ": WARNING - %s did not initialize properly! (%d)\n",
ioc->name, r); ioc->name, r);
@ -1629,7 +1572,6 @@ mpt_resume(struct pci_dev *pdev)
MPT_ADAPTER *ioc = pci_get_drvdata(pdev); MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state; u32 device_state = pdev->current_state;
int recovery_state; int recovery_state;
int ii;
printk(MYIOC_s_INFO_FMT printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
@ -1643,14 +1585,6 @@ mpt_resume(struct pci_dev *pdev)
CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1; ioc->active = 1;
/* F/W not running */
if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
/* enable domain validation flags */
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
}
}
printk(MYIOC_s_INFO_FMT printk(MYIOC_s_INFO_FMT
"pci-resume: ioc-state=0x%x,doorbell=0x%x\n", "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
ioc->name, ioc->name,
@ -4938,7 +4872,7 @@ done_and_free:
return rc; return rc;
} }
int static int
mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
{ {
IOCPage3_t *pIoc3; IOCPage3_t *pIoc3;
@ -5146,13 +5080,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
if (evnp == NULL) { if (evnp == NULL) {
devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
ioc->name)); ioc->name));
return 0; return 0;
} }
memset(evnp, 0, sizeof(*evnp)); memset(evnp, 0, sizeof(*evnp));
devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
evnp->ChainOffset = 0; evnp->ChainOffset = 0;
@ -5907,24 +5841,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break; break;
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
{ {
char buf[50];
u8 id = (u8)(evData0);
u8 ReasonCode = (u8)(evData0 >> 16); u8 ReasonCode = (u8)(evData0 >> 16);
switch (ReasonCode) { switch (ReasonCode) {
case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
ds = "SAS Device Status Change: Added"; sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
break; break;
case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
ds = "SAS Device Status Change: Deleted"; sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
break; break;
case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
ds = "SAS Device Status Change: SMART Data"; sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
break; break;
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
ds = "SAS Device Status Change: No Persistancy Added"; sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
break; break;
default: default:
ds = "SAS Device Status Change: Unknown"; sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
break; break;
} }
ds = buf;
break; break;
} }
case MPI_EVENT_ON_BUS_TIMER_EXPIRED: case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@ -5940,11 +5877,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
ds = "Persistent Table Full"; ds = "Persistent Table Full";
break; break;
case MPI_EVENT_SAS_PHY_LINK_STATUS: case MPI_EVENT_SAS_PHY_LINK_STATUS:
ds = "SAS PHY Link Status"; {
char buf[50];
u8 LinkRates = (u8)(evData0 >> 8);
u8 PhyNumber = (u8)(evData0);
LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
switch (LinkRates) {
case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
sprintf(buf,"SAS PHY Link Status: Phy=%d:"
" Rate Unknown",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
sprintf(buf,"SAS PHY Link Status: Phy=%d:"
" Phy Disabled",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
sprintf(buf,"SAS PHY Link Status: Phy=%d:"
" Failed Speed Nego",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
sprintf(buf,"SAS PHY Link Status: Phy=%d:"
" Sata OOB Completed",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
sprintf(buf,"SAS PHY Link Status: Phy=%d:"
" Rate 1.5 Gbps",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
sprintf(buf,"SAS PHY Link Status: Phy=%d:"
" Rate 3.0 Gpbs",PhyNumber);
break;
default:
sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
break;
}
ds = buf;
break; break;
}
case MPI_EVENT_SAS_DISCOVERY_ERROR: case MPI_EVENT_SAS_DISCOVERY_ERROR:
ds = "SAS Discovery Error"; ds = "SAS Discovery Error";
break; break;
case MPI_EVENT_IR_RESYNC_UPDATE:
{
u8 resync_complete = (u8)(evData0 >> 16);
char buf[40];
sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
ds = buf;
break;
}
case MPI_EVENT_IR2:
{
u8 ReasonCode = (u8)(evData0 >> 16);
switch (ReasonCode) {
case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
ds = "IR2: LD State Changed";
break;
case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
ds = "IR2: PD State Changed";
break;
case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
ds = "IR2: Bad Block Table Full";
break;
case MPI_EVENT_IR2_RC_PD_INSERTED:
ds = "IR2: PD Inserted";
break;
case MPI_EVENT_IR2_RC_PD_REMOVED:
ds = "IR2: PD Removed";
break;
case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
ds = "IR2: Foreign CFG Detected";
break;
case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
ds = "IR2: Rebuild Medium Error";
break;
default:
ds = "IR2";
break;
}
break;
}
case MPI_EVENT_SAS_DISCOVERY:
{
if (evData0)
ds = "SAS Discovery: Start";
else
ds = "SAS Discovery: Stop";
break;
}
case MPI_EVENT_LOG_ENTRY_ADDED:
ds = "SAS Log Entry Added";
break;
/* /*
* MPT base "custom" events may be added here... * MPT base "custom" events may be added here...
@ -5989,12 +6012,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
} }
EventDescriptionStr(event, evData0, evStr); EventDescriptionStr(event, evData0, evStr);
devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n",
ioc->name, ioc->name,
evStr, event,
event)); evStr));
#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS)
printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
for (ii = 0; ii < evDataLen; ii++) for (ii = 0; ii < evDataLen; ii++)
printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
@ -6053,7 +6076,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
*/ */
for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
if (MptEvHandlers[ii]) { if (MptEvHandlers[ii]) {
devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
ioc->name, ii)); ioc->name, ii));
r += (*(MptEvHandlers[ii]))(ioc, pEventReply); r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
handlers++; handlers++;
@ -6065,10 +6088,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
* If needed, send (a single) EventAck. * If needed, send (a single) EventAck.
*/ */
if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
devtprintk((MYIOC_s_WARN_FMT devtverboseprintk((MYIOC_s_WARN_FMT
"EventAck required\n",ioc->name)); "EventAck required\n",ioc->name));
if ((ii = SendEventAck(ioc, pEventReply)) != 0) { if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
ioc->name, ii)); ioc->name, ii));
} }
} }
@ -6205,8 +6228,8 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
"Abort", /* 12h */ "Abort", /* 12h */
"IO Not Yet Executed", /* 13h */ "IO Not Yet Executed", /* 13h */
"IO Executed", /* 14h */ "IO Executed", /* 14h */
NULL, /* 15h */ "Persistant Reservation Out Not Affiliation Owner", /* 15h */
NULL, /* 16h */ "Open Transmit DMA Abort", /* 16h */
NULL, /* 17h */ NULL, /* 17h */
NULL, /* 18h */ NULL, /* 18h */
NULL, /* 19h */ NULL, /* 19h */
@ -6431,11 +6454,9 @@ EXPORT_SYMBOL(mpt_stm_index);
EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_HardResetHandler);
EXPORT_SYMBOL(mpt_config); EXPORT_SYMBOL(mpt_config);
EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation); EXPORT_SYMBOL(mptbase_sas_persist_operation);
EXPORT_SYMBOL(mpt_alt_ioc_wait);
EXPORT_SYMBOL(mptbase_GetFcPortPage0); EXPORT_SYMBOL(mptbase_GetFcPortPage0);

Просмотреть файл

@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif #endif
#define MPT_LINUX_VERSION_COMMON "3.03.07" #define MPT_LINUX_VERSION_COMMON "3.03.08"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07" #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.08"
#define WHAT_MAGIC_STRING "@" "(" "#" ")" #define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \ #define show_mptmod_ver(s,ver) \
@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS
* VirtDevice - FC LUN device or SCSI target device * VirtDevice - FC LUN device or SCSI target device
*/ */
typedef struct _VirtTarget { typedef struct _VirtTarget {
struct scsi_target *starget;
u8 tflags; u8 tflags;
u8 ioc_id; u8 ioc_id;
u8 target_id; u8 target_id;
@ -343,14 +344,10 @@ typedef struct _VirtTarget {
u8 type; /* byte 0 of Inquiry data */ u8 type; /* byte 0 of Inquiry data */
u32 num_luns; u32 num_luns;
u32 luns[8]; /* Max LUNs is 256 */ u32 luns[8]; /* Max LUNs is 256 */
u8 inq_data[8];
} VirtTarget; } VirtTarget;
typedef struct _VirtDevice { typedef struct _VirtDevice {
VirtTarget *vtarget; VirtTarget *vtarget;
u8 ioc_id;
u8 bus_id;
u8 target_id;
u8 configured_lun; u8 configured_lun;
u32 lun; u32 lun;
} VirtDevice; } VirtDevice;
@ -364,6 +361,7 @@ typedef struct _VirtDevice {
#define MPT_TARGET_FLAGS_Q_YES 0x08 #define MPT_TARGET_FLAGS_Q_YES 0x08
#define MPT_TARGET_FLAGS_VALID_56 0x10 #define MPT_TARGET_FLAGS_VALID_56 0x10
#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40
/* /*
* /proc/mpt interface * /proc/mpt interface
@ -447,13 +445,6 @@ typedef struct _mpt_ioctl_events {
* Substructure to store SCSI specific configuration page data * Substructure to store SCSI specific configuration page data
*/ */
/* dvStatus defines: */ /* dvStatus defines: */
#define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */
#define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */
#define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */
#define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */
#define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */
#define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */
/* Args passed to writeSDP1: */
#define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */
#define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */
/* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */
@ -464,7 +455,6 @@ typedef struct _SpiCfgData {
IOCPage4_t *pIocPg4; /* SEP devices addressing */ IOCPage4_t *pIocPg4; /* SEP devices addressing */
dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */
int IocPg4Sz; /* IOCPage4 size */ int IocPg4Sz; /* IOCPage4 size */
u8 dvStatus[MPT_MAX_SCSI_DEVICES];
u8 minSyncFactor; /* 0xFF if async */ u8 minSyncFactor; /* 0xFF if async */
u8 maxSyncOffset; /* 0 if async */ u8 maxSyncOffset; /* 0 if async */
u8 maxBusWidth; /* 0 if narrow, 1 if wide */ u8 maxBusWidth; /* 0 if narrow, 1 if wide */
@ -474,13 +464,11 @@ typedef struct _SpiCfgData {
u8 sdp0version; /* SDP0 version */ u8 sdp0version; /* SDP0 version */
u8 sdp0length; /* SDP0 length */ u8 sdp0length; /* SDP0 length */
u8 dvScheduled; /* 1 if scheduled */ u8 dvScheduled; /* 1 if scheduled */
u8 forceDv; /* 1 to force DV scheduling */
u8 noQas; /* Disable QAS for this adapter */ u8 noQas; /* Disable QAS for this adapter */
u8 Saf_Te; /* 1 to force all Processors as u8 Saf_Te; /* 1 to force all Processors as
* SAF-TE if Inquiry data length * SAF-TE if Inquiry data length
* is too short to check for SAF-TE * is too short to check for SAF-TE
*/ */
u8 mpt_dv; /* command line option: enhanced=1, basic=0 */
u8 bus_reset; /* 1 to allow bus reset */ u8 bus_reset; /* 1 to allow bus reset */
u8 rsvd[1]; u8 rsvd[1];
}SpiCfgData; }SpiCfgData;
@ -631,6 +619,10 @@ typedef struct _MPT_ADAPTER
struct net_device *netdev; struct net_device *netdev;
struct list_head sas_topology; struct list_head sas_topology;
struct mutex sas_topology_mutex; struct mutex sas_topology_mutex;
struct mutex sas_discovery_mutex;
u8 sas_discovery_runtime;
u8 sas_discovery_ignore_events;
int sas_index; /* index refrencing */
MPT_SAS_MGMT sas_mgmt; MPT_SAS_MGMT sas_mgmt;
int num_ports; int num_ports;
struct work_struct mptscsih_persistTask; struct work_struct mptscsih_persistTask;
@ -728,12 +720,18 @@ typedef struct _mpt_sge {
#define dhsprintk(x) #define dhsprintk(x)
#endif #endif
#ifdef MPT_DEBUG_EVENTS #if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS)
#define devtprintk(x) printk x #define devtprintk(x) printk x
#else #else
#define devtprintk(x) #define devtprintk(x)
#endif #endif
#ifdef MPT_DEBUG_VERBOSE_EVENTS
#define devtverboseprintk(x) printk x
#else
#define devtverboseprintk(x)
#endif
#ifdef MPT_DEBUG_RESET #ifdef MPT_DEBUG_RESET
#define drsprintk(x) printk x #define drsprintk(x) printk x
#else #else
@ -1030,10 +1028,8 @@ extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
/* /*
* Public data decl's... * Public data decl's...

Просмотреть файл

@ -140,7 +140,7 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
* Event Handler function * Event Handler function
*/ */
static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
struct fasync_struct *async_queue=NULL; static struct fasync_struct *async_queue=NULL;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* /*
@ -497,7 +497,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
if (event == 0x21 ) { if (event == 0x21 ) {
ioc->aen_event_read_flag=1; ioc->aen_event_read_flag=1;
dctlprintk(("Raised SIGIO to application\n")); dctlprintk(("Raised SIGIO to application\n"));
devtprintk(("Raised SIGIO to application\n")); devtverboseprintk(("Raised SIGIO to application\n"));
kill_fasync(&async_queue, SIGIO, POLL_IN); kill_fasync(&async_queue, SIGIO, POLL_IN);
return 1; return 1;
} }
@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
if (ioc->events && (ioc->eventTypes & ( 1 << event))) { if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
ioc->aen_event_read_flag=1; ioc->aen_event_read_flag=1;
dctlprintk(("Raised SIGIO to application\n")); dctlprintk(("Raised SIGIO to application\n"));
devtprintk(("Raised SIGIO to application\n")); devtverboseprintk(("Raised SIGIO to application\n"));
kill_fasync(&async_queue, SIGIO, POLL_IN); kill_fasync(&async_queue, SIGIO, POLL_IN);
} }
return 1; return 1;
@ -2968,7 +2968,7 @@ static int __init mptctl_init(void)
} }
if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
devtprintk((KERN_INFO MYNAM devtverboseprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n")); ": Registered for IOC event notifications\n"));
} }

Просмотреть файл

@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
static struct scsi_transport_template *mptfc_transport_template = NULL; static struct scsi_transport_template *mptfc_transport_template = NULL;
struct fc_function_template mptfc_transport_functions = { static struct fc_function_template mptfc_transport_functions = {
.dd_fcrport_size = 8, .dd_fcrport_size = 8,
.show_host_node_name = 1, .show_host_node_name = 1,
.show_host_port_name = 1, .show_host_port_name = 1,
@ -348,24 +348,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
return 0; return 0;
} }
static void
mptfc_remap_sdev(struct scsi_device *sdev, void *arg)
{
VirtDevice *vdev;
VirtTarget *vtarget;
struct scsi_target *starget;
starget = scsi_target(sdev);
if (starget->hostdata == arg) {
vtarget = arg;
vdev = sdev->hostdata;
if (vdev) {
vdev->bus_id = vtarget->bus_id;
vdev->target_id = vtarget->target_id;
}
}
}
static void static void
mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
{ {
@ -423,8 +405,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
if (vtarget) { if (vtarget) {
vtarget->target_id = pg0->CurrentTargetID; vtarget->target_id = pg0->CurrentTargetID;
vtarget->bus_id = pg0->CurrentBus; vtarget->bus_id = pg0->CurrentBus;
starget_for_each_device(ri->starget,
vtarget,mptfc_remap_sdev);
} }
ri->remap_needed = 0; ri->remap_needed = 0;
} }
@ -432,7 +412,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
"rport tid %d, tmo %d\n", "rport tid %d, tmo %d\n",
ioc->name, ioc->name,
oc->sh->host_no, ioc->sh->host_no,
pg0->PortIdentifier, pg0->PortIdentifier,
pg0->WWNN, pg0->WWNN,
pg0->WWPN, pg0->WWPN,
@ -514,7 +494,7 @@ mptfc_target_alloc(struct scsi_target *starget)
* Return non-zero if allocation fails. * Return non-zero if allocation fails.
* Init memory once per LUN. * Init memory once per LUN.
*/ */
int static int
mptfc_slave_alloc(struct scsi_device *sdev) mptfc_slave_alloc(struct scsi_device *sdev)
{ {
MPT_SCSI_HOST *hd; MPT_SCSI_HOST *hd;
@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev)
} }
vdev->vtarget = vtarget; vdev->vtarget = vtarget;
vdev->ioc_id = hd->ioc->id;
vdev->lun = sdev->lun; vdev->lun = sdev->lun;
vdev->target_id = vtarget->target_id;
vdev->bus_id = vtarget->bus_id;
spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
vtarget->num_luns++; vtarget->num_luns++;
#ifdef DMPT_DEBUG_FC
{
struct mptfc_rport_info *ri;
ri = *((struct mptfc_rport_info **)rport->dd_data);
dfcprintk ((MYIOC_s_INFO_FMT dfcprintk ((MYIOC_s_INFO_FMT
"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
"CurrentTargetID %d, %x %llx %llx\n", "CurrentTargetID %d, %x %llx %llx\n",
ioc->name, hd->ioc->name,
sdev->host->host_no, sdev->host->host_no,
vtarget->num_luns, vtarget->num_luns,
sdev->id, ri->pg0.CurrentTargetID, sdev->id, ri->pg0.CurrentTargetID,
ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
}
#endif
return 0; return 0;
} }
@ -941,7 +924,7 @@ mptfc_init(void)
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
devtprintk((KERN_INFO MYNAM devtverboseprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n")); ": Registered for IOC event notifications\n"));
} }

Просмотреть файл

@ -1152,10 +1152,7 @@ mpt_lan_receive_post_reply(struct net_device *dev,
priv->mpt_rxfidx_tail, priv->mpt_rxfidx_tail,
MPT_LAN_MAX_BUCKETS_OUT); MPT_LAN_MAX_BUCKETS_OUT);
panic("Damn it Jim! I'm a doctor, not a programmer! " return -1;
"Oh, wait a sec, I am a programmer. "
"And, who's Jim?!?!\n"
"Arrgghh! We've done it again!\n");
} }
if (remaining == 0) if (remaining == 0)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -60,16 +60,6 @@
#define MPT_SCSI_MAX_SECTORS 8192 #define MPT_SCSI_MAX_SECTORS 8192
/* To disable domain validation, uncomment the
* following line. No effect for FC devices.
* For SCSI devices, driver will negotiate to
* NVRAM settings (if available) or to maximum adapter
* capabilities.
*/
#define MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* SCSI driver setup structure. Settings can be overridden /* SCSI driver setup structure. Settings can be overridden
* by command line options. * by command line options.
*/ */
@ -109,3 +99,5 @@ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
extern void mptscsih_timer_expired(unsigned long data); extern void mptscsih_timer_expired(unsigned long data);
extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);

Просмотреть файл

@ -56,12 +56,15 @@
#include <linux/reboot.h> /* notifier code */ #include <linux/reboot.h> /* notifier code */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/raid_class.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "mptbase.h" #include "mptbase.h"
#include "mptscsih.h" #include "mptscsih.h"
@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* Command line args */ /* Command line args */
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
module_param(mpt_dv, int, 0);
MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
static int mpt_width = MPTSCSIH_MAX_WIDTH;
module_param(mpt_width, int, 0);
MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
module_param(mpt_factor, ushort, 0);
MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
#endif
static int mpt_saf_te = MPTSCSIH_SAF_TE; static int mpt_saf_te = MPTSCSIH_SAF_TE;
module_param(mpt_saf_te, int, 0); module_param(mpt_saf_te, int, 0);
MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
@ -98,10 +87,308 @@ static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0); module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
static void mptspi_write_offset(struct scsi_target *, int);
static void mptspi_write_width(struct scsi_target *, int);
static int mptspi_write_spi_device_pg1(struct scsi_target *,
struct _CONFIG_PAGE_SCSI_DEVICE_1 *);
static struct scsi_transport_template *mptspi_transport_template = NULL;
static int mptspiDoneCtx = -1; static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1; static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */ static int mptspiInternalCtx = -1; /* Used only for internal commands */
static int mptspi_target_alloc(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
int ret;
if (hd == NULL)
return -ENODEV;
ret = mptscsih_target_alloc(starget);
if (ret)
return ret;
/* if we're a device on virtual channel 1 and we're not part
* of an array, just return here (otherwise the setup below
* may actually affect a real physical device on channel 0 */
if (starget->channel == 1 &&
mptscsih_raid_id_to_num(hd, starget->id) < 0)
return 0;
if (hd->ioc->spi_data.nvram &&
hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
u32 nvram = hd->ioc->spi_data.nvram[starget->id];
spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
} else {
spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
}
spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
spi_offset(starget) = 0;
mptspi_write_width(starget, 0);
return 0;
}
static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
struct _MPT_ADAPTER *ioc = hd->ioc;
struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
dma_addr_t pg0_dma;
int size;
struct _x_config_parms cfg;
struct _CONFIG_PAGE_HEADER hdr;
int err = -EBUSY;
/* No SPI parameters for RAID devices */
if (starget->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << starget->id)))
return -1;
size = ioc->spi_data.sdp0length * 4;
/*
if (ioc->spi_data.sdp0length & 1)
size += size + 4;
size += 2048;
*/
pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
if (pg0 == NULL) {
starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
return -EINVAL;
}
memset(&hdr, 0, sizeof(hdr));
hdr.PageVersion = ioc->spi_data.sdp0version;
hdr.PageLength = ioc->spi_data.sdp0length;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
memset(&cfg, 0, sizeof(cfg));
cfg.cfghdr.hdr = &hdr;
cfg.physAddr = pg0_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.dir = 0;
cfg.pageAddr = starget->id;
if (mpt_config(ioc, &cfg)) {
starget_printk(KERN_ERR, starget, "mpt_config failed\n");
goto out_free;
}
err = 0;
memcpy(pass_pg0, pg0, size);
out_free:
dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
return err;
}
static u32 mptspi_getRP(struct scsi_target *starget)
{
u32 nego = 0;
nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
return nego;
}
static void mptspi_read_parameters(struct scsi_target *starget)
{
int nego;
struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
mptspi_read_spi_device_pg0(starget, &pg0);
nego = le32_to_cpu(pg0.NegotiatedParameters);
spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
}
static int
mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
{
MpiRaidActionRequest_t *pReq;
MPT_FRAME_HDR *mf;
/* Get and Populate a free Frame
*/
if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
hd->ioc->name));
return -EAGAIN;
}
pReq = (MpiRaidActionRequest_t *)mf;
if (quiesce)
pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
else
pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
pReq->Reserved1 = 0;
pReq->ChainOffset = 0;
pReq->Function = MPI_FUNCTION_RAID_ACTION;
pReq->VolumeID = disk;
pReq->VolumeBus = 0;
pReq->PhysDiskNum = 0;
pReq->MsgFlags = 0;
pReq->Reserved2 = 0;
pReq->ActionDataWord = 0; /* Reserved for this action */
mpt_add_sge((char *)&pReq->ActionDataSGE,
MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
hd->ioc->name, action, io->id));
hd->pLocal = NULL;
hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
hd->scandv_wait_done = 0;
/* Save cmd pointer, for resource free if timeout or
* FW reload occurs
*/
hd->cmdPtr = mf;
add_timer(&hd->timer);
mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
wait_event(hd->scandv_waitq, hd->scandv_wait_done);
if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
return -1;
return 0;
}
static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
struct scsi_device *sdev)
{
VirtTarget *vtarget = scsi_target(sdev)->hostdata;
/* no DV on RAID devices */
if (sdev->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << sdev->id)))
return;
/* If this is a piece of a RAID, then quiesce first */
if (sdev->channel == 1 &&
mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) {
starget_printk(KERN_ERR, scsi_target(sdev),
"Integrated RAID quiesce failed\n");
return;
}
spi_dv_device(sdev);
if (sdev->channel == 1 &&
mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0)
starget_printk(KERN_ERR, scsi_target(sdev),
"Integrated RAID resume failed\n");
mptspi_read_parameters(sdev->sdev_target);
spi_display_xfer_agreement(sdev->sdev_target);
mptspi_read_parameters(sdev->sdev_target);
}
static int mptspi_slave_alloc(struct scsi_device *sdev)
{
int ret;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
/* gcc doesn't see that all uses of this variable occur within
* the if() statements, so stop it from whining */
int physdisknum = 0;
if (sdev->channel == 1) {
physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
if (physdisknum < 0)
return physdisknum;
}
ret = mptscsih_slave_alloc(sdev);
if (ret)
return ret;
if (sdev->channel == 1) {
VirtDevice *vdev = sdev->hostdata;
sdev->no_uld_attach = 1;
vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
/* The real channel for this device is zero */
vdev->vtarget->bus_id = 0;
/* The actual physdisknum (for RAID passthrough) */
vdev->vtarget->target_id = physdisknum;
}
return 0;
}
static int mptspi_slave_configure(struct scsi_device *sdev)
{
int ret = mptscsih_slave_configure(sdev);
struct _MPT_SCSI_HOST *hd =
(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
if (ret)
return ret;
if ((sdev->channel == 1 ||
!(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
!spi_initial_dv(sdev->sdev_target))
mptspi_dv_device(hd, sdev);
return 0;
}
static void mptspi_slave_destroy(struct scsi_device *sdev)
{
struct scsi_target *starget = scsi_target(sdev);
VirtTarget *vtarget = starget->hostdata;
VirtDevice *vdevice = sdev->hostdata;
/* Will this be the last lun on a non-raid device? */
if (vtarget->num_luns == 1 && vdevice->configured_lun) {
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
/* Async Narrow */
pg1.RequestedParameters = 0;
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
mptscsih_slave_destroy(sdev);
}
static struct scsi_host_template mptspi_driver_template = { static struct scsi_host_template mptspi_driver_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.proc_name = "mptspi", .proc_name = "mptspi",
@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = {
.name = "MPT SPI Host", .name = "MPT SPI Host",
.info = mptscsih_info, .info = mptscsih_info,
.queuecommand = mptscsih_qcmd, .queuecommand = mptscsih_qcmd,
.target_alloc = mptscsih_target_alloc, .target_alloc = mptspi_target_alloc,
.slave_alloc = mptscsih_slave_alloc, .slave_alloc = mptspi_slave_alloc,
.slave_configure = mptscsih_slave_configure, .slave_configure = mptspi_slave_configure,
.target_destroy = mptscsih_target_destroy, .target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy, .slave_destroy = mptspi_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth, .change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort, .eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset, .eh_device_reset_handler = mptscsih_dev_reset,
@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = {
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
}; };
static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
struct _MPT_ADAPTER *ioc = hd->ioc;
struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
dma_addr_t pg1_dma;
int size;
struct _x_config_parms cfg;
struct _CONFIG_PAGE_HEADER hdr;
int err = -EBUSY;
/* don't allow updating nego parameters on RAID devices */
if (starget->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << starget->id)))
return -1;
size = ioc->spi_data.sdp1length * 4;
pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
if (pg1 == NULL) {
starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
return -EINVAL;
}
memset(&hdr, 0, sizeof(hdr));
hdr.PageVersion = ioc->spi_data.sdp1version;
hdr.PageLength = ioc->spi_data.sdp1length;
hdr.PageNumber = 1;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
memset(&cfg, 0, sizeof(cfg));
cfg.cfghdr.hdr = &hdr;
cfg.physAddr = pg1_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
cfg.pageAddr = starget->id;
memcpy(pg1, pass_pg1, size);
pg1->Header.PageVersion = hdr.PageVersion;
pg1->Header.PageLength = hdr.PageLength;
pg1->Header.PageNumber = hdr.PageNumber;
pg1->Header.PageType = hdr.PageType;
if (mpt_config(ioc, &cfg)) {
starget_printk(KERN_ERR, starget, "mpt_config failed\n");
goto out_free;
}
err = 0;
out_free:
dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
return err;
}
static void mptspi_write_offset(struct scsi_target *starget, int offset)
{
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
u32 nego;
if (offset < 0)
offset = 0;
if (offset > 255)
offset = 255;
if (spi_offset(starget) == -1)
mptspi_read_parameters(starget);
spi_offset(starget) = offset;
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
static void mptspi_write_period(struct scsi_target *starget, int period)
{
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
u32 nego;
if (period < 8)
period = 8;
if (period > 255)
period = 255;
if (spi_period(starget) == -1)
mptspi_read_parameters(starget);
if (period == 8) {
spi_iu(starget) = 1;
spi_dt(starget) = 1;
} else if (period == 9) {
spi_dt(starget) = 1;
}
spi_period(starget) = period;
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
static void mptspi_write_dt(struct scsi_target *starget, int dt)
{
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
u32 nego;
if (spi_period(starget) == -1)
mptspi_read_parameters(starget);
if (!dt && spi_period(starget) < 10)
spi_period(starget) = 10;
spi_dt(starget) = dt;
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
static void mptspi_write_iu(struct scsi_target *starget, int iu)
{
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
u32 nego;
if (spi_period(starget) == -1)
mptspi_read_parameters(starget);
if (!iu && spi_period(starget) < 9)
spi_period(starget) = 9;
spi_iu(starget) = iu;
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \
static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
{ \
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \
u32 nego; \
\
spi_##parm(starget) = parm; \
\
nego = mptspi_getRP(starget); \
\
pg1.RequestedParameters = cpu_to_le32(nego); \
pg1.Reserved = 0; \
pg1.Configuration = 0; \
\
mptspi_write_spi_device_pg1(starget, &pg1); \
}
MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
static void mptspi_write_qas(struct scsi_target *starget, int qas)
{
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
VirtTarget *vtarget = starget->hostdata;
u32 nego;
if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
hd->ioc->spi_data.noQas)
spi_qas(starget) = 0;
else
spi_qas(starget) = qas;
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
static void mptspi_write_width(struct scsi_target *starget, int width)
{
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
u32 nego;
if (!width) {
spi_dt(starget) = 0;
if (spi_period(starget) < 10)
spi_period(starget) = 10;
}
spi_width(starget) = width;
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
struct work_queue_wrapper {
struct work_struct work;
struct _MPT_SCSI_HOST *hd;
int disk;
};
static void mpt_work_wrapper(void *data)
{
struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
struct _MPT_SCSI_HOST *hd = wqw->hd;
struct Scsi_Host *shost = hd->ioc->sh;
struct scsi_device *sdev;
int disk = wqw->disk;
struct _CONFIG_PAGE_IOC_3 *pg3;
kfree(wqw);
mpt_findImVolumes(hd->ioc);
pg3 = hd->ioc->raid_data.pIocPg3;
if (!pg3)
return;
shost_for_each_device(sdev,shost) {
struct scsi_target *starget = scsi_target(sdev);
VirtTarget *vtarget = starget->hostdata;
/* only want to search RAID components */
if (sdev->channel != 1)
continue;
/* The target_id is the raid PhysDiskNum, even if
* starget->id is the actual target address */
if(vtarget->target_id != disk)
continue;
starget_printk(KERN_INFO, vtarget->starget,
"Integrated RAID requests DV of new device\n");
mptspi_dv_device(hd, sdev);
}
shost_printk(KERN_INFO, shost,
"Integrated RAID detects new device %d\n", disk);
scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
}
static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
{
struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
if (!wqw) {
shost_printk(KERN_ERR, hd->ioc->sh,
"Failed to act on RAID event for physical disk %d\n",
disk);
return;
}
INIT_WORK(&wqw->work, mpt_work_wrapper, wqw);
wqw->hd = hd;
wqw->disk = disk;
schedule_work(&wqw->work);
}
static int
mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
if (hd && event == MPI_EVENT_INTEGRATED_RAID) {
int reason
= (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
mpt_dv_raid(hd, disk);
}
}
return mptscsih_event_process(ioc, pEvReply);
}
static int
mptspi_deny_binding(struct scsi_target *starget)
{
struct _MPT_SCSI_HOST *hd =
(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
starget->channel == 0) ? 1 : 0;
}
static struct spi_function_template mptspi_transport_functions = {
.get_offset = mptspi_read_parameters,
.set_offset = mptspi_write_offset,
.show_offset = 1,
.get_period = mptspi_read_parameters,
.set_period = mptspi_write_period,
.show_period = 1,
.get_width = mptspi_read_parameters,
.set_width = mptspi_write_width,
.show_width = 1,
.get_iu = mptspi_read_parameters,
.set_iu = mptspi_write_iu,
.show_iu = 1,
.get_dt = mptspi_read_parameters,
.set_dt = mptspi_write_dt,
.show_dt = 1,
.get_qas = mptspi_read_parameters,
.set_qas = mptspi_write_qas,
.show_qas = 1,
.get_wr_flow = mptspi_read_parameters,
.set_wr_flow = mptspi_write_wr_flow,
.show_wr_flow = 1,
.get_rd_strm = mptspi_read_parameters,
.set_rd_strm = mptspi_write_rd_strm,
.show_rd_strm = 1,
.get_rti = mptspi_read_parameters,
.set_rti = mptspi_write_rti,
.show_rti = 1,
.get_pcomp_en = mptspi_read_parameters,
.set_pcomp_en = mptspi_write_pcomp_en,
.show_pcomp_en = 1,
.get_hold_mcs = mptspi_read_parameters,
.set_hold_mcs = mptspi_write_hold_mcs,
.show_hold_mcs = 1,
.deny_binding = mptspi_deny_binding,
};
/**************************************************************************** /****************************************************************************
* Supported hardware * Supported hardware
@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->max_id = MPT_MAX_SCSI_DEVICES; sh->max_id = MPT_MAX_SCSI_DEVICES;
sh->max_lun = MPT_LAST_LUN + 1; sh->max_lun = MPT_LAST_LUN + 1;
sh->max_channel = 0; /*
* If RAID Firmware Detected, setup virtual channel
*/
if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
> MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
sh->max_channel = 1;
else
sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID; sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry. /* Required entry.
@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* indicates a device exists. * indicates a device exists.
* max_id = 1 + maximum id (hosts.h) * max_id = 1 + maximum id (hosts.h)
*/ */
hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
sizeof(void *), GFP_ATOMIC);
if (!hd->Targets) { if (!hd->Targets) {
error = -ENOMEM; error = -ENOMEM;
goto out_mptspi_probe; goto out_mptspi_probe;
@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->spi_data.Saf_Te = mpt_saf_te; ioc->spi_data.Saf_Te = mpt_saf_te;
hd->mpt_pq_filter = mpt_pq_filter; hd->mpt_pq_filter = mpt_pq_filter;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
if (ioc->spi_data.maxBusWidth > mpt_width)
ioc->spi_data.maxBusWidth = mpt_width;
if (ioc->spi_data.minSyncFactor < mpt_factor)
ioc->spi_data.minSyncFactor = mpt_factor;
if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
ioc->spi_data.maxSyncOffset = 0;
}
ioc->spi_data.mpt_dv = mpt_dv;
hd->negoNvram = 0;
ddvprintk((MYIOC_s_INFO_FMT
"dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
ioc->name,
mpt_dv,
mpt_width,
mpt_factor,
mpt_saf_te,
mpt_pq_filter));
#else
hd->negoNvram = MPT_SCSICFG_USE_NVRAM; hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
ddvprintk((MYIOC_s_INFO_FMT ddvprintk((MYIOC_s_INFO_FMT
"saf_te %x mpt_pq_filter %x\n", "saf_te %x mpt_pq_filter %x\n",
ioc->name, ioc->name,
mpt_saf_te, mpt_saf_te,
mpt_pq_filter)); mpt_pq_filter));
#endif
ioc->spi_data.forceDv = 0;
ioc->spi_data.noQas = 0; ioc->spi_data.noQas = 0;
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
ioc->spi_data.dvStatus[ii] =
MPT_SCSICFG_NEGOTIATE;
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
ioc->spi_data.dvStatus[ii] |=
MPT_SCSICFG_DV_NOT_DONE;
init_waitqueue_head(&hd->scandv_waitq); init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0; hd->scandv_wait_done = 0;
hd->last_queue_full = 0; hd->last_queue_full = 0;
/* Some versions of the firmware don't support page 0; without
* that we can't get the parameters */
if (hd->ioc->spi_data.sdp0length != 0)
sh->transportt = mptspi_transport_template;
error = scsi_add_host (sh, &ioc->pcidev->dev); error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) { if(error) {
dprintk((KERN_ERR MYNAM dprintk((KERN_ERR MYNAM
@ -423,15 +1046,18 @@ static struct pci_driver mptspi_driver = {
static int __init static int __init
mptspi_init(void) mptspi_init(void)
{ {
show_mptmod_ver(my_NAME, my_VERSION); show_mptmod_ver(my_NAME, my_VERSION);
mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
if (!mptspi_transport_template)
return -ENODEV;
mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
devtprintk((KERN_INFO MYNAM devtverboseprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n")); ": Registered for IOC event notifications\n"));
} }
@ -465,6 +1091,7 @@ mptspi_exit(void)
mpt_deregister(mptspiInternalCtx); mpt_deregister(mptspiInternalCtx);
mpt_deregister(mptspiTaskCtx); mpt_deregister(mptspiTaskCtx);
mpt_deregister(mptspiDoneCtx); mpt_deregister(mptspiDoneCtx);
spi_release_transport(mptspi_transport_template);
} }
module_init(mptspi_init); module_init(mptspi_init);

Просмотреть файл

@ -57,6 +57,13 @@ struct i2o_exec_wait {
struct list_head list; /* node in global wait list */ struct list_head list; /* node in global wait list */
}; };
/* Work struct needed to handle LCT NOTIFY replies */
struct i2o_exec_lct_notify_work {
struct work_struct work; /* work struct */
struct i2o_controller *c; /* controller on which the LCT NOTIFY
was received */
};
/* Exec OSM class handling definition */ /* Exec OSM class handling definition */
static struct i2o_class_id i2o_exec_class_id[] = { static struct i2o_class_id i2o_exec_class_id[] = {
{I2O_CLASS_EXECUTIVE}, {I2O_CLASS_EXECUTIVE},
@ -355,9 +362,12 @@ static int i2o_exec_remove(struct device *dev)
* new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
* again, otherwise send LCT NOTIFY to get informed on next LCT change. * again, otherwise send LCT NOTIFY to get informed on next LCT change.
*/ */
static void i2o_exec_lct_modified(struct i2o_controller *c) static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work)
{ {
u32 change_ind = 0; u32 change_ind = 0;
struct i2o_controller *c = work->c;
kfree(work);
if (i2o_device_parse_lct(c) != -EAGAIN) if (i2o_device_parse_lct(c) != -EAGAIN)
change_ind = c->lct->change_ind + 1; change_ind = c->lct->change_ind + 1;
@ -410,7 +420,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
return i2o_msg_post_wait_complete(c, m, msg, context); return i2o_msg_post_wait_complete(c, m, msg, context);
if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
struct work_struct *work; struct i2o_exec_lct_notify_work *work;
pr_debug("%s: LCT notify received\n", c->name); pr_debug("%s: LCT notify received\n", c->name);
@ -418,8 +428,11 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
if (!work) if (!work)
return -ENOMEM; return -ENOMEM;
INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c); work->c = c;
queue_work(i2o_exec_driver.event_queue, work);
INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified,
work);
queue_work(i2o_exec_driver.event_queue, &work->work);
return 1; return 1;
} }

Просмотреть файл

@ -2,8 +2,9 @@
3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux. 3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
Written By: Adam Radford <linuxraid@amcc.com> Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com>
Copyright (C) 2004-2005 Applied Micro Circuits Corporation. Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -62,6 +63,8 @@
2.26.02.003 - Correctly handle single sgl's with use_sg=1. 2.26.02.003 - Correctly handle single sgl's with use_sg=1.
2.26.02.004 - Add support for 9550SX controllers. 2.26.02.004 - Add support for 9550SX controllers.
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher. 2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
2.26.02.006 - Fix 9550SX pchip reset timeout.
Add big endian support.
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -85,7 +88,7 @@
#include "3w-9xxx.h" #include "3w-9xxx.h"
/* Globals */ /* Globals */
#define TW_DRIVER_VERSION "2.26.02.005" #define TW_DRIVER_VERSION "2.26.02.006"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count; static unsigned int twa_device_extension_count;
static int twa_major = -1; static int twa_major = -1;
@ -208,7 +211,7 @@ static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
tw_dev->posted_request_count--; tw_dev->posted_request_count--;
aen = header->status_block.error; aen = le16_to_cpu(header->status_block.error);
full_command_packet = tw_dev->command_packet_virt[request_id]; full_command_packet = tw_dev->command_packet_virt[request_id];
command_packet = &full_command_packet->command.oldcommand; command_packet = &full_command_packet->command.oldcommand;
@ -305,7 +308,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
tw_dev->posted_request_count--; tw_dev->posted_request_count--;
header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
aen = header->status_block.error; aen = le16_to_cpu(header->status_block.error);
queue = 0; queue = 0;
count++; count++;
@ -365,7 +368,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
tw_dev->aen_clobber = 1; tw_dev->aen_clobber = 1;
} }
aen = header->status_block.error; aen = le16_to_cpu(header->status_block.error);
memset(event, 0, sizeof(TW_Event)); memset(event, 0, sizeof(TW_Event));
event->severity = TW_SEV_OUT(header->status_block.severity__reserved); event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
@ -382,7 +385,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0'; header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
event->parameter_len = strlen(header->err_specific_desc); event->parameter_len = strlen(header->err_specific_desc);
memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len); memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + (error_str[0] == '\0' ? 0 : (1 + strlen(error_str))));
if (event->severity != TW_AEN_SEVERITY_DEBUG) if (event->severity != TW_AEN_SEVERITY_DEBUG)
printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n", printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
host, host,
@ -462,24 +465,24 @@ static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
command_packet = &full_command_packet->command.oldcommand; command_packet = &full_command_packet->command.oldcommand;
command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM); command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
command_packet->request_id = request_id; command_packet->request_id = request_id;
command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id]; command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
command_packet->size = TW_COMMAND_SIZE; command_packet->size = TW_COMMAND_SIZE;
command_packet->byte6_offset.parameter_count = 1; command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
/* Setup the param */ /* Setup the param */
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
memset(param, 0, TW_SECTOR_SIZE); memset(param, 0, TW_SECTOR_SIZE);
param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */ param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
param->parameter_id = 0x3; /* SchedulerTime */ param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
param->parameter_size_bytes = 4; param->parameter_size_bytes = cpu_to_le16(4);
/* Convert system time in UTC to local time seconds since last /* Convert system time in UTC to local time seconds since last
Sunday 12:00AM */ Sunday 12:00AM */
do_gettimeofday(&utc); do_gettimeofday(&utc);
local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60)); local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
schedulertime = local_time - (3 * 86400); schedulertime = local_time - (3 * 86400);
schedulertime = schedulertime % 604800; schedulertime = cpu_to_le32(schedulertime % 604800);
memcpy(param->data, &schedulertime, sizeof(u32)); memcpy(param->data, &schedulertime, sizeof(u32));
@ -931,26 +934,19 @@ out:
/* This function will clear the pchip/response queue on 9550SX */ /* This function will clear the pchip/response queue on 9550SX */
static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
{ {
u32 status_reg_value, response_que_value; u32 response_que_value = 0;
int count = 0, retval = 1; unsigned long before;
int retval = 1;
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); before = jiffies;
while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) {
while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) { if (time_after(jiffies, before + HZ * 30))
/* P-chip settle time */
msleep(500);
retval = 0;
goto out; goto out;
}
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
count++;
} }
if (count == TW_MAX_RESPONSE_DRAIN) /* P-chip settle time */
goto out; msleep(500);
retval = 0; retval = 0;
} else } else
retval = 0; retval = 0;
@ -972,7 +968,7 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_
error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]); error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]);
/* Don't print error for Logical unit not supported during rollcall */ /* Don't print error for Logical unit not supported during rollcall */
error = full_command_packet->header.status_block.error; error = le16_to_cpu(full_command_packet->header.status_block.error);
if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) { if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
if (print_host) if (print_host)
printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n", printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
@ -1047,18 +1043,18 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl
command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
command_packet->size = TW_COMMAND_SIZE; command_packet->size = TW_COMMAND_SIZE;
command_packet->request_id = request_id; command_packet->request_id = request_id;
command_packet->byte6_offset.block_count = 1; command_packet->byte6_offset.block_count = cpu_to_le16(1);
/* Now setup the param */ /* Now setup the param */
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
memset(param, 0, TW_SECTOR_SIZE); memset(param, 0, TW_SECTOR_SIZE);
param->table_id = table_id | 0x8000; param->table_id = cpu_to_le16(table_id | 0x8000);
param->parameter_id = parameter_id; param->parameter_id = cpu_to_le16(parameter_id);
param->parameter_size_bytes = parameter_size_bytes; param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
param_value = tw_dev->generic_buffer_phys[request_id]; param_value = tw_dev->generic_buffer_phys[request_id];
command_packet->byte8_offset.param.sgl[0].address = param_value; command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value);
command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
/* Post the command packet to the board */ /* Post the command packet to the board */
twa_post_command_packet(tw_dev, request_id, 1); twa_post_command_packet(tw_dev, request_id, 1);
@ -1107,18 +1103,20 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand; tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION); tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
tw_initconnect->request_id = request_id; tw_initconnect->request_id = request_id;
tw_initconnect->message_credits = message_credits; tw_initconnect->message_credits = cpu_to_le16(message_credits);
tw_initconnect->features = set_features; tw_initconnect->features = set_features;
/* Turn on 64-bit sgl support if we need to */ /* Turn on 64-bit sgl support if we need to */
tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0; tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
tw_initconnect->features = cpu_to_le32(tw_initconnect->features);
if (set_features & TW_EXTENDED_INIT_CONNECT) { if (set_features & TW_EXTENDED_INIT_CONNECT) {
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED; tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
tw_initconnect->fw_srl = current_fw_srl; tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
tw_initconnect->fw_arch_id = current_fw_arch_id; tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
tw_initconnect->fw_branch = current_fw_branch; tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
tw_initconnect->fw_build = current_fw_build; tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
} else } else
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE; tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
@ -1130,11 +1128,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection");
} else { } else {
if (set_features & TW_EXTENDED_INIT_CONNECT) { if (set_features & TW_EXTENDED_INIT_CONNECT) {
*fw_on_ctlr_srl = tw_initconnect->fw_srl; *fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
*fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id; *fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id);
*fw_on_ctlr_branch = tw_initconnect->fw_branch; *fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch);
*fw_on_ctlr_build = tw_initconnect->fw_build; *fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build);
*init_connect_result = tw_initconnect->result; *init_connect_result = le32_to_cpu(tw_initconnect->result);
} }
retval = 0; retval = 0;
} }
@ -1358,10 +1356,10 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
newcommand = &full_command_packet->command.newcommand; newcommand = &full_command_packet->command.newcommand;
newcommand->request_id__lunl = newcommand->request_id__lunl =
TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id); TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id);
newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
newcommand->sg_list[0].length = length; newcommand->sg_list[0].length = cpu_to_le32(length);
newcommand->sgl_entries__lunh = newcommand->sgl_entries__lunh =
TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1); cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1));
} else { } else {
oldcommand = &full_command_packet->command.oldcommand; oldcommand = &full_command_packet->command.oldcommand;
oldcommand->request_id = request_id; oldcommand->request_id = request_id;
@ -1369,8 +1367,8 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
/* Load the sg list */ /* Load the sg list */
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
sgl->length = length; sgl->length = cpu_to_le32(length);
if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
oldcommand->size += 1; oldcommand->size += 1;
@ -1828,10 +1826,10 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (srb) { if (srb) {
command_packet->unit = srb->device->id; command_packet->unit = srb->device->id;
command_packet->request_id__lunl = command_packet->request_id__lunl =
TW_REQ_LUN_IN(srb->device->lun, request_id); cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id));
} else { } else {
command_packet->request_id__lunl = command_packet->request_id__lunl =
TW_REQ_LUN_IN(0, request_id); cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
command_packet->unit = 0; command_packet->unit = 0;
} }
@ -1841,8 +1839,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
/* Map sglist from scsi layer to cmd packet */ /* Map sglist from scsi layer to cmd packet */
if (tw_dev->srb[request_id]->use_sg == 0) { if (tw_dev->srb[request_id]->use_sg == 0) {
if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
} else { } else {
@ -1850,12 +1848,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (buffaddr == 0) if (buffaddr == 0)
goto out; goto out;
command_packet->sg_list[0].address = buffaddr; command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen; command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
} }
command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1); command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) { if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
goto out; goto out;
} }
@ -1869,35 +1867,35 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
kunmap_atomic(buf - sg->offset, KM_IRQ0); kunmap_atomic(buf - sg->offset, KM_IRQ0);
} }
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
} else { } else {
sg_count = twa_map_scsi_sg_data(tw_dev, request_id); sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
if (sg_count == 0) if (sg_count == 0)
goto out; goto out;
for (i = 0; i < sg_count; i++) { for (i = 0; i < sg_count; i++) {
command_packet->sg_list[i].address = sg_dma_address(&sglist[i]); command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
command_packet->sg_list[i].length = sg_dma_len(&sglist[i]); command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
goto out; goto out;
} }
} }
} }
command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg); command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
} }
} else { } else {
/* Internal cdb post */ /* Internal cdb post */
for (i = 0; i < use_sg; i++) { for (i = 0; i < use_sg; i++) {
command_packet->sg_list[i].address = sglistarg[i].address; command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
command_packet->sg_list[i].length = sglistarg[i].length; command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length);
if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post");
goto out; goto out;
} }
} }
command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg); command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
} }
if (srb) { if (srb) {
@ -2115,8 +2113,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH), TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
(char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE, (char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE,
TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH), TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE, le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)); TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
/* Now setup the interrupt handler */ /* Now setup the interrupt handler */
retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev); retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);

Просмотреть файл

@ -2,8 +2,9 @@
3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux. 3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
Written By: Adam Radford <linuxraid@amcc.com> Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com>
Copyright (C) 2004-2005 Applied Micro Circuits Corporation. Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -287,9 +288,6 @@ static twa_message_type twa_error_table[] = {
#define TW_STATUS_UNEXPECTED_BITS 0x00F00000 #define TW_STATUS_UNEXPECTED_BITS 0x00F00000
#define TW_STATUS_VALID_INTERRUPT 0x00DF0000 #define TW_STATUS_VALID_INTERRUPT 0x00DF0000
/* RESPONSE QUEUE BIT DEFINITIONS */
#define TW_RESPONSE_ID_MASK 0x00000FF0
/* PCI related defines */ /* PCI related defines */
#define TW_NUMDEVICES 1 #define TW_NUMDEVICES 1
#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100 #define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
@ -471,6 +469,7 @@ printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
#define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109) #define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109)
#define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62) #define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
#define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0) #define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0)
#define TW_CPU_TO_SGL(x) (sizeof(dma_addr_t) > 4 ? cpu_to_le64(x) : cpu_to_le32(x))
#pragma pack(1) #pragma pack(1)
@ -614,13 +613,6 @@ typedef union TAG_TW_Response_Queue {
u32 value; u32 value;
} TW_Response_Queue; } TW_Response_Queue;
typedef struct TAG_TW_Info {
char *buffer;
int length;
int offset;
int position;
} TW_Info;
/* Compatibility information structure */ /* Compatibility information structure */
typedef struct TAG_TW_Compatibility_Info typedef struct TAG_TW_Compatibility_Info
{ {
@ -636,6 +628,8 @@ typedef struct TAG_TW_Compatibility_Info
unsigned short driver_build_low; unsigned short driver_build_low;
} TW_Compatibility_Info; } TW_Compatibility_Info;
#pragma pack()
typedef struct TAG_TW_Device_Extension { typedef struct TAG_TW_Device_Extension {
u32 __iomem *base_addr; u32 __iomem *base_addr;
unsigned long *generic_buffer_virt[TW_Q_LENGTH]; unsigned long *generic_buffer_virt[TW_Q_LENGTH];
@ -679,7 +673,5 @@ typedef struct TAG_TW_Device_Extension {
unsigned short working_build; unsigned short working_build;
} TW_Device_Extension; } TW_Device_Extension;
#pragma pack()
#endif /* _3W_9XXX_H */ #endif /* _3W_9XXX_H */

Просмотреть файл

@ -238,14 +238,6 @@ static char *NCR_700_SBCL_to_phase[] = {
"MSG IN", "MSG IN",
}; };
static __u8 NCR_700_SDTR_msg[] = {
0x01, /* Extended message */
0x03, /* Extended message Length */
0x01, /* SDTR Extended message */
NCR_700_MIN_PERIOD,
NCR_700_MAX_OFFSET
};
/* This translates the SDTR message offset and period to a value /* This translates the SDTR message offset and period to a value
* which can be loaded into the SXFER_REG. * which can be loaded into the SXFER_REG.
* *
@ -266,7 +258,7 @@ NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata,
return 0; return 0;
if(period < hostdata->min_period) { if(period < hostdata->min_period) {
printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4); printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD*4);
period = hostdata->min_period; period = hostdata->min_period;
} }
XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; XFERP = (period*4 * hostdata->sync_clock)/1000 - 4;
@ -1434,11 +1426,9 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
if(hostdata->fast && if(hostdata->fast &&
NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) {
memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, count += spi_populate_sync_msg(&hostdata->msgout[count],
sizeof(NCR_700_SDTR_msg)); spi_period(SCp->device->sdev_target),
hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target); spi_offset(SCp->device->sdev_target));
hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target);
count += sizeof(NCR_700_SDTR_msg);
NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
} }

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -218,7 +218,7 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
return 0; return 0;
detect_failed: detect_failed:
release_region(host->base, 64); release_region(region, 64);
region_failed: region_failed:
kfree(hostdata); kfree(hostdata);

Просмотреть файл

@ -997,7 +997,7 @@ struct aac_dev
int maximum_num_physicals; int maximum_num_physicals;
int maximum_num_channels; int maximum_num_channels;
struct fsa_dev_info *fsa_dev; struct fsa_dev_info *fsa_dev;
pid_t thread_pid; struct task_struct *thread;
int cardtype; int cardtype;
/* /*
@ -1017,7 +1017,6 @@ struct aac_dev
* AIF thread states * AIF thread states
*/ */
u32 aif_thread; u32 aif_thread;
struct completion aif_completion;
struct aac_adapter_info adapter_info; struct aac_adapter_info adapter_info;
struct aac_supplement_adapter_info supplement_adapter_info; struct aac_supplement_adapter_info supplement_adapter_info;
/* These are in adapter info but they are in the io flow so /* These are in adapter info but they are in the io flow so
@ -1797,7 +1796,7 @@ int aac_sa_init(struct aac_dev *dev);
unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_response_normal(struct aac_queue * q);
unsigned int aac_command_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
int aac_command_thread(struct aac_dev * dev); int aac_command_thread(void *data);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype); struct aac_driver_ident* aac_get_driver_ident(int devtype);

Просмотреть файл

@ -433,7 +433,6 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
} }
INIT_LIST_HEAD(&dev->fib_list); INIT_LIST_HEAD(&dev->fib_list);
init_completion(&dev->aif_completion);
return dev; return dev;
} }

Просмотреть файл

@ -39,6 +39,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kthread.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
@ -1045,8 +1046,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
* more FIBs. * more FIBs.
*/ */
int aac_command_thread(struct aac_dev * dev) int aac_command_thread(void *data)
{ {
struct aac_dev *dev = data;
struct hw_fib *hw_fib, *hw_newfib; struct hw_fib *hw_fib, *hw_newfib;
struct fib *fib, *newfib; struct fib *fib, *newfib;
struct aac_fib_context *fibctx; struct aac_fib_context *fibctx;
@ -1058,12 +1060,7 @@ int aac_command_thread(struct aac_dev * dev)
*/ */
if (dev->aif_thread) if (dev->aif_thread)
return -EINVAL; return -EINVAL;
/*
* Set up the name that will appear in 'ps'
* stored in task_struct.comm[16].
*/
daemonize("aacraid");
allow_signal(SIGKILL);
/* /*
* Let the DPC know it has a place to send the AIF's to. * Let the DPC know it has a place to send the AIF's to.
*/ */
@ -1266,13 +1263,12 @@ int aac_command_thread(struct aac_dev * dev)
spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
schedule(); schedule();
if(signal_pending(current)) if (kthread_should_stop())
break; break;
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
} }
if (dev->queues) if (dev->queues)
remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
dev->aif_thread = 0; dev->aif_thread = 0;
complete_and_exit(&dev->aif_completion, 0);
return 0; return 0;
} }

Просмотреть файл

@ -48,6 +48,7 @@
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/kthread.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
@ -850,10 +851,10 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
/* /*
* Start any kernel threads needed * Start any kernel threads needed
*/ */
aac->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, aac->thread = kthread_run(aac_command_thread, aac, AAC_DRIVERNAME);
aac, 0); if (IS_ERR(aac->thread)) {
if (aac->thread_pid < 0) {
printk(KERN_ERR "aacraid: Unable to create command thread.\n"); printk(KERN_ERR "aacraid: Unable to create command thread.\n");
error = PTR_ERR(aac->thread);
goto out_deinit; goto out_deinit;
} }
@ -934,9 +935,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
return 0; return 0;
out_deinit: out_deinit:
kill_proc(aac->thread_pid, SIGKILL, 0); kthread_stop(aac->thread);
wait_for_completion(&aac->aif_completion);
aac_send_shutdown(aac); aac_send_shutdown(aac);
aac_adapter_disable_int(aac); aac_adapter_disable_int(aac);
free_irq(pdev->irq, aac); free_irq(pdev->irq, aac);
@ -970,8 +969,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
scsi_remove_host(shost); scsi_remove_host(shost);
kill_proc(aac->thread_pid, SIGKILL, 0); kthread_stop(aac->thread);
wait_for_completion(&aac->aif_completion);
aac_send_shutdown(aac); aac_send_shutdown(aac);
aac_adapter_disable_int(aac); aac_adapter_disable_int(aac);

Просмотреть файл

@ -1716,12 +1716,7 @@ static void seldo_run(struct Scsi_Host *shpnt)
ADDMSGO(BUS_DEVICE_RESET); ADDMSGO(BUS_DEVICE_RESET);
} else if (SYNCNEG==0 && SYNCHRONOUS) { } else if (SYNCNEG==0 && SYNCHRONOUS) {
CURRENT_SC->SCp.phase |= syncneg; CURRENT_SC->SCp.phase |= syncneg;
ADDMSGO(EXTENDED_MESSAGE); MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
ADDMSGO(3);
ADDMSGO(EXTENDED_SDTR);
ADDMSGO(50); /* 200ns */
ADDMSGO(8); /* 8 byte req/ack offset */
SYNCNEG=1; /* negotiation in progress */ SYNCNEG=1; /* negotiation in progress */
} }

Просмотреть файл

@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -978,9 +978,13 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
break; break;
} }
case INVALID_SEQINT: case INVALID_SEQINT:
printf("%s: Invalid Sequencer interrupt occurred.\n", printf("%s: Invalid Sequencer interrupt occurred, "
"resetting channel.\n",
ahd_name(ahd)); ahd_name(ahd));
ahd_dump_card_state(ahd); #ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
ahd_dump_card_state(ahd);
#endif
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
break; break;
case STATUS_OVERRUN: case STATUS_OVERRUN:
@ -3762,11 +3766,8 @@ ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
{ {
if (offset == 0) if (offset == 0)
period = AHD_ASYNC_XFER_PERIOD; period = AHD_ASYNC_XFER_PERIOD;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; ahd->msgout_index += spi_populate_sync_msg(
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN; ahd->msgout_buf + ahd->msgout_index, period, offset);
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR;
ahd->msgout_buf[ahd->msgout_index++] = period;
ahd->msgout_buf[ahd->msgout_index++] = offset;
ahd->msgout_len += 5; ahd->msgout_len += 5;
if (bootverbose) { if (bootverbose) {
printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
@ -3783,10 +3784,8 @@ static void
ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
u_int bus_width) u_int bus_width)
{ {
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; ahd->msgout_index += spi_populate_width_msg(
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN; ahd->msgout_buf + ahd->msgout_index, bus_width);
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR;
ahd->msgout_buf[ahd->msgout_index++] = bus_width;
ahd->msgout_len += 4; ahd->msgout_len += 4;
if (bootverbose) { if (bootverbose) {
printf("(%s:%c:%d:%d): Sending WDTR %x\n", printf("(%s:%c:%d:%d): Sending WDTR %x\n",
@ -3813,14 +3812,9 @@ ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ppr_options |= MSG_EXT_PPR_PCOMP_EN; ppr_options |= MSG_EXT_PPR_PCOMP_EN;
if (offset == 0) if (offset == 0)
period = AHD_ASYNC_XFER_PERIOD; period = AHD_ASYNC_XFER_PERIOD;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; ahd->msgout_index += spi_populate_ppr_msg(
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN; ahd->msgout_buf + ahd->msgout_index, period, offset,
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR; bus_width, ppr_options);
ahd->msgout_buf[ahd->msgout_index++] = period;
ahd->msgout_buf[ahd->msgout_index++] = 0;
ahd->msgout_buf[ahd->msgout_index++] = offset;
ahd->msgout_buf[ahd->msgout_index++] = bus_width;
ahd->msgout_buf[ahd->msgout_index++] = ppr_options;
ahd->msgout_len += 8; ahd->msgout_len += 8;
if (bootverbose) { if (bootverbose) {
printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "
@ -7094,7 +7088,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
ahd_flush_qoutfifo(ahd); ahd_flush_qoutfifo(ahd);
ahd_platform_flushwork(ahd);
ahd->flags &= ~AHD_ALL_INTERRUPTS; ahd->flags &= ~AHD_ALL_INTERRUPTS;
} }

Просмотреть файл

@ -373,8 +373,7 @@ static void ahd_linux_handle_scsi_status(struct ahd_softc *,
struct scb *); struct scb *);
static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
struct scsi_cmnd *cmd); struct scsi_cmnd *cmd);
static void ahd_linux_sem_timeout(u_long arg); static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd);
static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo); struct ahd_devinfo *devinfo);
@ -453,18 +452,13 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
struct ahd_softc *ahd; struct ahd_softc *ahd;
struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device); struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
int rtn = SCSI_MLQUEUE_HOST_BUSY; int rtn = SCSI_MLQUEUE_HOST_BUSY;
unsigned long flags;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata; ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
ahd_lock(ahd, &flags); cmd->scsi_done = scsi_done;
if (ahd->platform_data->qfrozen == 0) { cmd->result = CAM_REQ_INPROG << 16;
cmd->scsi_done = scsi_done; rtn = ahd_linux_run_command(ahd, dev, cmd);
cmd->result = CAM_REQ_INPROG << 16;
rtn = ahd_linux_run_command(ahd, dev, cmd);
}
ahd_unlock(ahd, &flags);
return rtn; return rtn;
} }
@ -487,6 +481,7 @@ ahd_linux_target_alloc(struct scsi_target *starget)
{ {
struct ahd_softc *ahd = struct ahd_softc *ahd =
*((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
struct seeprom_config *sc = ahd->seep_config;
unsigned long flags; unsigned long flags;
struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
struct ahd_linux_target *targ = scsi_transport_target_data(starget); struct ahd_linux_target *targ = scsi_transport_target_data(starget);
@ -502,18 +497,38 @@ ahd_linux_target_alloc(struct scsi_target *starget)
*ahd_targp = starget; *ahd_targp = starget;
memset(targ, 0, sizeof(*targ)); memset(targ, 0, sizeof(*targ));
if (sc) {
int flags = sc->device_flags[starget->id];
tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
starget->id, &tstate);
if ((flags & CFPACKETIZED) == 0) {
/* Do not negotiate packetized transfers */
spi_rd_strm(starget) = 0;
spi_pcomp_en(starget) = 0;
spi_rti(starget) = 0;
spi_wr_flow(starget) = 0;
spi_hold_mcs(starget) = 0;
} else {
if ((ahd->features & AHD_RTI) == 0)
spi_rti(starget) = 0;
}
if ((flags & CFQAS) == 0)
spi_qas(starget) = 0;
/* Transinfo values have been set to BIOS settings */
spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;
spi_min_period(starget) = tinfo->user.period;
spi_max_offset(starget) = tinfo->user.offset;
}
tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
starget->id, &tstate); starget->id, &tstate);
ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id, ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
CAM_LUN_WILDCARD, channel, CAM_LUN_WILDCARD, channel,
ROLE_INITIATOR); ROLE_INITIATOR);
spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */
if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
spi_max_offset(starget) = MAX_OFFSET_PACED_BUG;
else
spi_max_offset(starget) = MAX_OFFSET_PACED;
spi_max_width(starget) = ahd->features & AHD_WIDE;
ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
AHD_TRANS_GOAL, /*paused*/FALSE); AHD_TRANS_GOAL, /*paused*/FALSE);
ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
@ -654,10 +669,9 @@ static int
ahd_linux_abort(struct scsi_cmnd *cmd) ahd_linux_abort(struct scsi_cmnd *cmd)
{ {
int error; int error;
error = ahd_linux_queue_abort_cmd(cmd);
error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT);
if (error != 0)
printf("aic79xx_abort returns 0x%x\n", error);
return error; return error;
} }
@ -667,12 +681,97 @@ ahd_linux_abort(struct scsi_cmnd *cmd)
static int static int
ahd_linux_dev_reset(struct scsi_cmnd *cmd) ahd_linux_dev_reset(struct scsi_cmnd *cmd)
{ {
int error; struct ahd_softc *ahd;
struct ahd_linux_device *dev;
struct scb *reset_scb;
u_int cdb_byte;
int retval = SUCCESS;
int paused;
int wait;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
unsigned long flags;
DECLARE_COMPLETION(done);
error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); reset_scb = NULL;
if (error != 0) paused = FALSE;
printf("aic79xx_dev_reset returns 0x%x\n", error); wait = FALSE;
return error; ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
scmd_printk(KERN_INFO, cmd,
"Attempting to queue a TARGET RESET message:");
printf("CDB:");
for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
printf(" 0x%x", cmd->cmnd[cdb_byte]);
printf("\n");
/*
* Determine if we currently own this command.
*/
dev = scsi_transport_device_data(cmd->device);
if (dev == NULL) {
/*
* No target device for this command exists,
* so we must not still own the command.
*/
scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
return SUCCESS;
}
/*
* Generate us a new SCB
*/
reset_scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX);
if (!reset_scb) {
scmd_printk(KERN_INFO, cmd, "No SCB available\n");
return FAILED;
}
tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
cmd->device->id, &tstate);
reset_scb->io_ctx = cmd;
reset_scb->platform_data->dev = dev;
reset_scb->sg_count = 0;
ahd_set_residual(reset_scb, 0);
ahd_set_sense_residual(reset_scb, 0);
reset_scb->platform_data->xfer_len = 0;
reset_scb->hscb->control = 0;
reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd);
reset_scb->hscb->lun = cmd->device->lun;
reset_scb->hscb->cdb_len = 0;
reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET;
reset_scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
reset_scb->flags |= SCB_PACKETIZED;
} else {
reset_scb->hscb->control |= MK_MESSAGE;
}
dev->openings--;
dev->active++;
dev->commands_issued++;
ahd_lock(ahd, &flags);
LIST_INSERT_HEAD(&ahd->pending_scbs, reset_scb, pending_links);
ahd_queue_scb(ahd, reset_scb);
ahd->platform_data->eh_done = &done;
ahd_unlock(ahd, &flags);
printf("%s: Device reset code sleeping\n", ahd_name(ahd));
if (!wait_for_completion_timeout(&done, 5 * HZ)) {
ahd_lock(ahd, &flags);
ahd->platform_data->eh_done = NULL;
ahd_unlock(ahd, &flags);
printf("%s: Device reset timer expired (active %d)\n",
ahd_name(ahd), dev->active);
retval = FAILED;
}
printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
return (retval);
} }
/* /*
@ -682,7 +781,6 @@ static int
ahd_linux_bus_reset(struct scsi_cmnd *cmd) ahd_linux_bus_reset(struct scsi_cmnd *cmd)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd;
u_long s;
int found; int found;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata; ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
@ -691,10 +789,8 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
printf("%s: Bus reset called for cmd %p\n", printf("%s: Bus reset called for cmd %p\n",
ahd_name(ahd), cmd); ahd_name(ahd), cmd);
#endif #endif
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A', found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
/*initiate reset*/TRUE); /*initiate reset*/TRUE);
ahd_unlock(ahd, &s);
if (bootverbose) if (bootverbose)
printf("%s: SCSI bus reset delivered. " printf("%s: SCSI bus reset delivered. "
@ -811,59 +907,6 @@ ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
} }
/********************* Platform Dependent Functions ***************************/ /********************* Platform Dependent Functions ***************************/
/*
* Compare "left hand" softc with "right hand" softc, returning:
* < 0 - lahd has a lower priority than rahd
* 0 - Softcs are equal
* > 0 - lahd has a higher priority than rahd
*/
int
ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
{
int value;
/*
* Under Linux, cards are ordered as follows:
* 1) PCI devices that are marked as the boot controller.
* 2) PCI devices with BIOS enabled sorted by bus/slot/func.
* 3) All remaining PCI devices sorted by bus/slot/func.
*/
#if 0
value = (lahd->flags & AHD_BOOT_CHANNEL)
- (rahd->flags & AHD_BOOT_CHANNEL);
if (value != 0)
/* Controllers set for boot have a *higher* priority */
return (value);
#endif
value = (lahd->flags & AHD_BIOS_ENABLED)
- (rahd->flags & AHD_BIOS_ENABLED);
if (value != 0)
/* Controllers with BIOS enabled have a *higher* priority */
return (value);
/* Still equal. Sort by bus/slot/func. */
if (aic79xx_reverse_scan != 0)
value = ahd_get_pci_bus(lahd->dev_softc)
- ahd_get_pci_bus(rahd->dev_softc);
else
value = ahd_get_pci_bus(rahd->dev_softc)
- ahd_get_pci_bus(lahd->dev_softc);
if (value != 0)
return (value);
if (aic79xx_reverse_scan != 0)
value = ahd_get_pci_slot(lahd->dev_softc)
- ahd_get_pci_slot(rahd->dev_softc);
else
value = ahd_get_pci_slot(rahd->dev_softc)
- ahd_get_pci_slot(lahd->dev_softc);
if (value != 0)
return (value);
value = rahd->channel - lahd->channel;
return (value);
}
static void static void
ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
{ {
@ -1194,7 +1237,6 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
ahd->platform_data->irq = AHD_LINUX_NOIRQ; ahd->platform_data->irq = AHD_LINUX_NOIRQ;
ahd_lockinit(ahd); ahd_lockinit(ahd);
init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
ahd->seltime = (aic79xx_seltime & 0x3) << 4; ahd->seltime = (aic79xx_seltime & 0x3) << 4;
return (0); return (0);
} }
@ -1346,14 +1388,12 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
case AHD_DEV_Q_BASIC: case AHD_DEV_Q_BASIC:
scsi_adjust_queue_depth(sdev, scsi_set_tag_type(sdev, MSG_SIMPLE_TASK);
MSG_SIMPLE_TASK, scsi_activate_tcq(sdev, dev->openings + dev->active);
dev->openings + dev->active);
break; break;
case AHD_DEV_Q_TAGGED: case AHD_DEV_Q_TAGGED:
scsi_adjust_queue_depth(sdev, scsi_set_tag_type(sdev, MSG_ORDERED_TASK);
MSG_ORDERED_TASK, scsi_activate_tcq(sdev, dev->openings + dev->active);
dev->openings + dev->active);
break; break;
default: default:
/* /*
@ -1362,9 +1402,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
* serially on the controller/device. This should * serially on the controller/device. This should
* remove some latency. * remove some latency.
*/ */
scsi_adjust_queue_depth(sdev, scsi_deactivate_tcq(sdev, 1);
/*NON-TAGGED*/0,
/*queue depth*/2);
break; break;
} }
} }
@ -1443,6 +1481,9 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
struct ahd_tmode_tstate *tstate; struct ahd_tmode_tstate *tstate;
u_int col_idx; u_int col_idx;
uint16_t mask; uint16_t mask;
unsigned long flags;
ahd_lock(ahd, &flags);
/* /*
* Get an scb to use. * Get an scb to use.
@ -1458,6 +1499,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
} }
if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
ahd->flags |= AHD_RESOURCE_SHORTAGE; ahd->flags |= AHD_RESOURCE_SHORTAGE;
ahd_unlock(ahd, &flags);
return SCSI_MLQUEUE_HOST_BUSY; return SCSI_MLQUEUE_HOST_BUSY;
} }
@ -1484,30 +1526,6 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
if ((tstate->auto_negotiate & mask) != 0) { if ((tstate->auto_negotiate & mask) != 0) {
scb->flags |= SCB_AUTO_NEGOTIATE; scb->flags |= SCB_AUTO_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE; scb->hscb->control |= MK_MESSAGE;
} else if (cmd->cmnd[0] == INQUIRY
&& (tinfo->curr.offset != 0
|| tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT
|| tinfo->curr.ppr_options != 0)
&& (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {
/*
* The SCSI spec requires inquiry
* commands to complete without
* reporting unit attention conditions.
* Because of this, an inquiry command
* that occurs just after a device is
* reset will result in a data phase
* with mismatched negotiated rates.
* The core already forces a renegotiation
* for reset events that are visible to
* our controller or that we initiate,
* but a third party device reset or a
* hot-plug insertion can still cause this
* issue. Therefore, we force a re-negotiation
* for every inquiry command unless we
* are async.
*/
scb->flags |= SCB_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE;
} }
if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
@ -1583,6 +1601,8 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
scb->flags |= SCB_ACTIVE; scb->flags |= SCB_ACTIVE;
ahd_queue_scb(ahd, scb); ahd_queue_scb(ahd, scb);
ahd_unlock(ahd, &flags);
return 0; return 0;
} }
@ -1603,12 +1623,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
return IRQ_RETVAL(ours); return IRQ_RETVAL(ours);
} }
void
ahd_platform_flushwork(struct ahd_softc *ahd)
{
}
void void
ahd_send_async(struct ahd_softc *ahd, char channel, 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, void *arg)
@ -1618,7 +1632,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
{ {
char buf[80]; char buf[80];
struct scsi_target *starget; struct scsi_target *starget;
struct ahd_linux_target *targ;
struct info_str info; struct info_str info;
struct ahd_initiator_tinfo *tinfo; struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate; struct ahd_tmode_tstate *tstate;
@ -1651,7 +1664,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
starget = ahd->platform_data->starget[target]; starget = ahd->platform_data->starget[target];
if (starget == NULL) if (starget == NULL)
break; break;
targ = scsi_transport_target_data(starget);
target_ppr_options = target_ppr_options =
(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@ -1803,10 +1815,9 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
if (ahd_get_transaction_status(scb) == CAM_BDR_SENT if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
|| ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; if (ahd->platform_data->eh_done)
up(&ahd->platform_data->eh_sem); complete(ahd->platform_data->eh_done);
}
} }
ahd_free_scb(ahd, scb); ahd_free_scb(ahd, scb);
@ -1961,133 +1972,125 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
static void static void
ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
{ {
int status;
int new_status = DID_OK;
int do_fallback = 0;
int scsi_status;
/* /*
* Map CAM error codes into Linux Error codes. We * Map CAM error codes into Linux Error codes. We
* avoid the conversion so that the DV code has the * avoid the conversion so that the DV code has the
* full error information available when making * full error information available when making
* state change decisions. * state change decisions.
*/ */
{
uint32_t status;
u_int new_status;
status = ahd_cmd_get_transaction_status(cmd); status = ahd_cmd_get_transaction_status(cmd);
switch (status) { switch (status) {
case CAM_REQ_INPROG: case CAM_REQ_INPROG:
case CAM_REQ_CMP: case CAM_REQ_CMP:
case CAM_SCSI_STATUS_ERROR: new_status = DID_OK;
new_status = DID_OK; break;
break; case CAM_AUTOSENSE_FAIL:
case CAM_REQ_ABORTED: new_status = DID_ERROR;
new_status = DID_ABORT; /* Fallthrough */
break; case CAM_SCSI_STATUS_ERROR:
case CAM_BUSY: scsi_status = ahd_cmd_get_scsi_status(cmd);
new_status = DID_BUS_BUSY;
break; switch(scsi_status) {
case CAM_REQ_INVALID: case SCSI_STATUS_CMD_TERMINATED:
case CAM_PATH_INVALID: case SCSI_STATUS_CHECK_COND:
new_status = DID_BAD_TARGET; if ((cmd->result >> 24) != DRIVER_SENSE) {
break; do_fallback = 1;
case CAM_SEL_TIMEOUT: } else {
new_status = DID_NO_CONNECT; struct scsi_sense_data *sense;
break;
case CAM_SCSI_BUS_RESET: sense = (struct scsi_sense_data *)
case CAM_BDR_SENT: &cmd->sense_buffer;
new_status = DID_RESET; if (sense->extra_len >= 5 &&
break; (sense->add_sense_code == 0x47
case CAM_UNCOR_PARITY: || sense->add_sense_code == 0x48))
new_status = DID_PARITY; do_fallback = 1;
break; }
case CAM_CMD_TIMEOUT:
new_status = DID_TIME_OUT;
break;
case CAM_UA_ABORT:
case CAM_REQ_CMP_ERR:
case CAM_AUTOSENSE_FAIL:
case CAM_NO_HBA:
case CAM_DATA_RUN_ERR:
case CAM_UNEXP_BUSFREE:
case CAM_SEQUENCE_FAIL:
case CAM_CCB_LEN_ERR:
case CAM_PROVIDE_FAIL:
case CAM_REQ_TERMIO:
case CAM_UNREC_HBA_ERROR:
case CAM_REQ_TOO_BIG:
new_status = DID_ERROR;
break;
case CAM_REQUEUE_REQ:
new_status = DID_REQUEUE;
break; break;
default: default:
/* We should never get here */
new_status = DID_ERROR;
break; break;
} }
break;
ahd_cmd_set_transaction_status(cmd, new_status); case CAM_REQ_ABORTED:
new_status = DID_ABORT;
break;
case CAM_BUSY:
new_status = DID_BUS_BUSY;
break;
case CAM_REQ_INVALID:
case CAM_PATH_INVALID:
new_status = DID_BAD_TARGET;
break;
case CAM_SEL_TIMEOUT:
new_status = DID_NO_CONNECT;
break;
case CAM_SCSI_BUS_RESET:
case CAM_BDR_SENT:
new_status = DID_RESET;
break;
case CAM_UNCOR_PARITY:
new_status = DID_PARITY;
do_fallback = 1;
break;
case CAM_CMD_TIMEOUT:
new_status = DID_TIME_OUT;
do_fallback = 1;
break;
case CAM_REQ_CMP_ERR:
case CAM_UNEXP_BUSFREE:
case CAM_DATA_RUN_ERR:
new_status = DID_ERROR;
do_fallback = 1;
break;
case CAM_UA_ABORT:
case CAM_NO_HBA:
case CAM_SEQUENCE_FAIL:
case CAM_CCB_LEN_ERR:
case CAM_PROVIDE_FAIL:
case CAM_REQ_TERMIO:
case CAM_UNREC_HBA_ERROR:
case CAM_REQ_TOO_BIG:
new_status = DID_ERROR;
break;
case CAM_REQUEUE_REQ:
new_status = DID_REQUEUE;
break;
default:
/* We should never get here */
new_status = DID_ERROR;
break;
} }
if (do_fallback) {
printf("%s: device overrun (status %x) on %d:%d:%d\n",
ahd_name(ahd), status, cmd->device->channel,
cmd->device->id, cmd->device->lun);
}
ahd_cmd_set_transaction_status(cmd, new_status);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
} }
static void
ahd_linux_sem_timeout(u_long arg)
{
struct ahd_softc *ahd;
u_long s;
ahd = (struct ahd_softc *)arg;
ahd_lock(ahd, &s);
if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
up(&ahd->platform_data->eh_sem);
}
ahd_unlock(ahd, &s);
}
void void
ahd_freeze_simq(struct ahd_softc *ahd) ahd_freeze_simq(struct ahd_softc *ahd)
{ {
unsigned long s; scsi_block_requests(ahd->platform_data->host);
ahd_lock(ahd, &s);
ahd->platform_data->qfrozen++;
if (ahd->platform_data->qfrozen == 1) {
scsi_block_requests(ahd->platform_data->host);
ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
CAM_LUN_WILDCARD, SCB_LIST_NULL,
ROLE_INITIATOR, CAM_REQUEUE_REQ);
}
ahd_unlock(ahd, &s);
} }
void void
ahd_release_simq(struct ahd_softc *ahd) ahd_release_simq(struct ahd_softc *ahd)
{ {
u_long s; scsi_unblock_requests(ahd->platform_data->host);
int unblock_reqs;
unblock_reqs = 0;
ahd_lock(ahd, &s);
if (ahd->platform_data->qfrozen > 0)
ahd->platform_data->qfrozen--;
if (ahd->platform_data->qfrozen == 0) {
unblock_reqs = 1;
}
ahd_unlock(ahd, &s);
/*
* There is still a race here. The mid-layer
* should keep its own freeze count and use
* a bottom half handler to run the queues
* so we can unblock with our own lock held.
*/
if (unblock_reqs)
scsi_unblock_requests(ahd->platform_data->host);
} }
static int static int
ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd;
struct ahd_linux_device *dev; struct ahd_linux_device *dev;
@ -2102,7 +2105,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int paused; int paused;
int wait; int wait;
int disconnected; int disconnected;
int found;
ahd_mode_state saved_modes; ahd_mode_state saved_modes;
unsigned long flags; unsigned long flags;
@ -2112,8 +2114,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
ahd = *(struct ahd_softc **)cmd->device->host->hostdata; ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
scmd_printk(KERN_INFO, cmd, scmd_printk(KERN_INFO, cmd,
"Attempting to queue a%s message:", "Attempting to queue an ABORT message:");
flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
printf("CDB:"); printf("CDB:");
for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
@ -2149,19 +2150,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
break; break;
} }
if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
/* Any SCB for this device will do for a target reset */
LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
if (ahd_match_scb(ahd, pending_scb,
scmd_id(cmd),
scmd_channel(cmd) + 'A',
CAM_LUN_WILDCARD,
SCB_LIST_NULL, ROLE_INITIATOR))
break;
}
}
if (pending_scb == NULL) { if (pending_scb == NULL) {
scmd_printk(KERN_INFO, cmd, "Command not found\n"); scmd_printk(KERN_INFO, cmd, "Command not found\n");
goto no_cmd; goto no_cmd;
@ -2195,25 +2183,17 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
ahd_dump_card_state(ahd); ahd_dump_card_state(ahd);
disconnected = TRUE; disconnected = TRUE;
if (flag == SCB_ABORT) { if (ahd_search_qinfifo(ahd, cmd->device->id,
if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A',
cmd->device->channel + 'A', cmd->device->lun,
cmd->device->lun, pending_scb->hscb->tag,
pending_scb->hscb->tag, ROLE_INITIATOR, CAM_REQ_ABORTED,
ROLE_INITIATOR, CAM_REQ_ABORTED, SEARCH_COMPLETE) > 0) {
SEARCH_COMPLETE) > 0) { printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahd_name(ahd), cmd->device->channel,
ahd_name(ahd), cmd->device->channel, cmd->device->id, cmd->device->lun);
cmd->device->id, cmd->device->lun); retval = SUCCESS;
retval = SUCCESS; goto done;
goto done;
}
} else if (ahd_search_qinfifo(ahd, cmd->device->id,
cmd->device->channel + 'A',
cmd->device->lun, pending_scb->hscb->tag,
ROLE_INITIATOR, /*status*/0,
SEARCH_COUNT) > 0) {
disconnected = FALSE;
} }
saved_modes = ahd_save_modes(ahd); saved_modes = ahd_save_modes(ahd);
@ -2221,17 +2201,12 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
last_phase = ahd_inb(ahd, LASTPHASE); last_phase = ahd_inb(ahd, LASTPHASE);
saved_scbptr = ahd_get_scbptr(ahd); saved_scbptr = ahd_get_scbptr(ahd);
active_scbptr = saved_scbptr; active_scbptr = saved_scbptr;
if (disconnected && ((last_phase != P_BUSFREE) || if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
(ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
struct scb *bus_scb; struct scb *bus_scb;
bus_scb = ahd_lookup_scb(ahd, active_scbptr); bus_scb = ahd_lookup_scb(ahd, active_scbptr);
if (bus_scb == pending_scb) if (bus_scb == pending_scb)
disconnected = FALSE; disconnected = FALSE;
else if (flag != SCB_ABORT
&& ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid
&& ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb))
disconnected = FALSE;
} }
/* /*
@ -2240,41 +2215,26 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* bus or is in the disconnected state. * bus or is in the disconnected state.
*/ */
saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
if (SCB_GET_TAG(pending_scb) == active_scbptr if (last_phase != P_BUSFREE
|| (flag == SCB_DEVICE_RESET && SCB_GET_TAG(pending_scb) == active_scbptr) {
&& SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
/* /*
* We're active on the bus, so assert ATN * We're active on the bus, so assert ATN
* and hope that the target responds. * and hope that the target responds.
*/ */
pending_scb = ahd_lookup_scb(ahd, active_scbptr); pending_scb = ahd_lookup_scb(ahd, active_scbptr);
pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
ahd_outb(ahd, MSG_OUT, HOST_MSG); ahd_outb(ahd, MSG_OUT, HOST_MSG);
ahd_outb(ahd, SCSISIGO, last_phase|ATNO); ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n"); scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
wait = TRUE; wait = TRUE;
} else if (last_phase != P_BUSFREE
&& ahd_inb(ahd, SCSIPHASE) == 0) {
/*
* SCB is not identified, there
* is no pending REQ, and the sequencer
* has not seen a busfree. Looks like
* a stuck connection waiting to
* go busfree. Reset the bus.
*/
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*Initiate Reset*/TRUE);
printf("%s: Issued Channel %c Bus Reset. "
"%d SCBs aborted\n", ahd_name(ahd),
cmd->device->channel + 'A', found);
} else if (disconnected) { } else if (disconnected) {
/* /*
* Actually re-queue this SCB in an attempt * Actually re-queue this SCB in an attempt
* to select the device before it reconnects. * to select the device before it reconnects.
*/ */
pending_scb->flags |= SCB_RECOVERY_SCB|flag; pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
pending_scb->hscb->cdb_len = 0; pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0; pending_scb->hscb->task_attribute = 0;
@ -2344,30 +2304,29 @@ done:
if (paused) if (paused)
ahd_unpause(ahd); ahd_unpause(ahd);
if (wait) { if (wait) {
struct timer_list timer; DECLARE_COMPLETION(done);
int ret;
ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM; ahd->platform_data->eh_done = &done;
ahd_unlock(ahd, &flags); ahd_unlock(ahd, &flags);
init_timer(&timer);
timer.data = (u_long)ahd;
timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout;
add_timer(&timer);
printf("%s: Recovery code sleeping\n", ahd_name(ahd)); printf("%s: Recovery code sleeping\n", ahd_name(ahd));
down(&ahd->platform_data->eh_sem); if (!wait_for_completion_timeout(&done, 5 * HZ)) {
printf("%s: Recovery code awake\n", ahd_name(ahd)); ahd_lock(ahd, &flags);
ret = del_timer_sync(&timer); ahd->platform_data->eh_done = NULL;
if (ret == 0) { ahd_unlock(ahd, &flags);
printf("%s: Timer Expired (active %d)\n", printf("%s: Timer Expired (active %d)\n",
ahd_name(ahd), dev->active); ahd_name(ahd), dev->active);
retval = FAILED; retval = FAILED;
} }
printf("Recovery code awake\n");
} else } else
ahd_unlock(ahd, &flags); ahd_unlock(ahd, &flags);
return (retval); if (retval != SUCCESS)
printf("%s: Command abort returning 0x%x\n",
ahd_name(ahd), retval);
return retval;
} }
static void ahd_linux_set_width(struct scsi_target *starget, int width) static void ahd_linux_set_width(struct scsi_target *starget, int width)

Просмотреть файл

@ -381,15 +381,12 @@ struct ahd_platform_data {
struct scsi_target *starget[AHD_NUM_TARGETS]; struct scsi_target *starget[AHD_NUM_TARGETS];
spinlock_t spin_lock; spinlock_t spin_lock;
u_int qfrozen; struct completion *eh_done;
struct semaphore eh_sem;
struct Scsi_Host *host; /* pointer to scsi host */ struct Scsi_Host *host; /* pointer to scsi host */
#define AHD_LINUX_NOIRQ ((uint32_t)~0) #define AHD_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */ uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address; uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */ uint32_t mem_busaddr; /* Mem Base Addr */
#define AHD_SCB_UP_EH_SEM 0x1
uint32_t flags;
}; };
/************************** OS Utility Wrappers *******************************/ /************************** OS Utility Wrappers *******************************/
@ -875,8 +872,6 @@ int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
role_t role, uint32_t status); role_t role, uint32_t status);
irqreturn_t irqreturn_t
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs); ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahd_platform_flushwork(struct ahd_softc *ahd);
int ahd_softc_comp(struct ahd_softc *, struct ahd_softc *);
void ahd_done(struct ahd_softc*, struct scb*); void ahd_done(struct ahd_softc*, struct scb*);
void ahd_send_async(struct ahd_softc *, char channel, 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 *);

Просмотреть файл

@ -2461,11 +2461,8 @@ ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
{ {
if (offset == 0) if (offset == 0)
period = AHC_ASYNC_XFER_PERIOD; period = AHC_ASYNC_XFER_PERIOD;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; ahc->msgout_index += spi_populate_sync_msg(
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN; ahc->msgout_buf + ahc->msgout_index, period, offset);
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR;
ahc->msgout_buf[ahc->msgout_index++] = period;
ahc->msgout_buf[ahc->msgout_index++] = offset;
ahc->msgout_len += 5; ahc->msgout_len += 5;
if (bootverbose) { if (bootverbose) {
printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
@ -2482,10 +2479,8 @@ static void
ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
u_int bus_width) u_int bus_width)
{ {
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; ahc->msgout_index += spi_populate_width_msg(
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN; ahc->msgout_buf + ahc->msgout_index, bus_width);
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR;
ahc->msgout_buf[ahc->msgout_index++] = bus_width;
ahc->msgout_len += 4; ahc->msgout_len += 4;
if (bootverbose) { if (bootverbose) {
printf("(%s:%c:%d:%d): Sending WDTR %x\n", printf("(%s:%c:%d:%d): Sending WDTR %x\n",
@ -2505,14 +2500,9 @@ ahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
{ {
if (offset == 0) if (offset == 0)
period = AHC_ASYNC_XFER_PERIOD; period = AHC_ASYNC_XFER_PERIOD;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; ahc->msgout_index += spi_populate_ppr_msg(
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN; ahc->msgout_buf + ahc->msgout_index, period, offset,
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR; bus_width, ppr_options);
ahc->msgout_buf[ahc->msgout_index++] = period;
ahc->msgout_buf[ahc->msgout_index++] = 0;
ahc->msgout_buf[ahc->msgout_index++] = offset;
ahc->msgout_buf[ahc->msgout_index++] = bus_width;
ahc->msgout_buf[ahc->msgout_index++] = ppr_options;
ahc->msgout_len += 8; ahc->msgout_len += 8;
if (bootverbose) { if (bootverbose) {
printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "

Просмотреть файл

@ -373,7 +373,6 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *,
struct scb *); struct scb *);
static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
struct scsi_cmnd *cmd); struct scsi_cmnd *cmd);
static void ahc_linux_sem_timeout(u_long arg);
static void ahc_linux_freeze_simq(struct ahc_softc *ahc); static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
static void ahc_linux_release_simq(struct ahc_softc *ahc); static void ahc_linux_release_simq(struct ahc_softc *ahc);
static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
@ -1193,7 +1192,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc->platform_data->irq = AHC_LINUX_NOIRQ;
ahc_lockinit(ahc); ahc_lockinit(ahc);
init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
if (aic7xxx_pci_parity == 0) if (aic7xxx_pci_parity == 0)
@ -1830,10 +1828,9 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if (ahc_get_transaction_status(scb) == CAM_BDR_SENT if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
|| ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED)
ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; if (ahc->platform_data->eh_done)
up(&ahc->platform_data->eh_sem); complete(ahc->platform_data->eh_done);
}
} }
ahc_free_scb(ahc, scb); ahc_free_scb(ahc, scb);
@ -2039,22 +2036,6 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
} }
static void
ahc_linux_sem_timeout(u_long arg)
{
struct ahc_softc *ahc;
u_long s;
ahc = (struct ahc_softc *)arg;
ahc_lock(ahc, &s);
if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
up(&ahc->platform_data->eh_sem);
}
ahc_unlock(ahc, &s);
}
static void static void
ahc_linux_freeze_simq(struct ahc_softc *ahc) ahc_linux_freeze_simq(struct ahc_softc *ahc)
{ {
@ -2355,25 +2336,21 @@ done:
if (paused) if (paused)
ahc_unpause(ahc); ahc_unpause(ahc);
if (wait) { if (wait) {
struct timer_list timer; DECLARE_COMPLETION(done);
int ret;
ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE; ahc->platform_data->eh_done = &done;
ahc_unlock(ahc, &flags); ahc_unlock(ahc, &flags);
init_timer(&timer);
timer.data = (u_long)ahc;
timer.expires = jiffies + (5 * HZ);
timer.function = ahc_linux_sem_timeout;
add_timer(&timer);
printf("Recovery code sleeping\n"); printf("Recovery code sleeping\n");
down(&ahc->platform_data->eh_sem); if (!wait_for_completion_timeout(&done, 5 * HZ)) {
printf("Recovery code awake\n"); ahc_lock(ahc, &flags);
ret = del_timer_sync(&timer); ahc->platform_data->eh_done = NULL;
if (ret == 0) { ahc_unlock(ahc, &flags);
printf("Timer Expired\n"); printf("Timer Expired\n");
retval = FAILED; retval = FAILED;
} }
printf("Recovery code awake\n");
} else } else
ahc_unlock(ahc, &flags); ahc_unlock(ahc, &flags);
return (retval); return (retval);

Просмотреть файл

@ -369,15 +369,12 @@ struct ahc_platform_data {
spinlock_t spin_lock; spinlock_t spin_lock;
u_int qfrozen; u_int qfrozen;
struct semaphore eh_sem; struct completion *eh_done;
struct Scsi_Host *host; /* pointer to scsi host */ struct Scsi_Host *host; /* pointer to scsi host */
#define AHC_LINUX_NOIRQ ((uint32_t)~0) #define AHC_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */ uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address; uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */ uint32_t mem_busaddr; /* Mem Base Addr */
#define AHC_UP_EH_SEMAPHORE 0x1
uint32_t flags;
}; };
/************************** OS Utility Wrappers *******************************/ /************************** OS Utility Wrappers *******************************/

Просмотреть файл

@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -39,6 +39,7 @@
MODULE_DESCRIPTION("device driver for scsi media changer devices"); MODULE_DESCRIPTION("device driver for scsi media changer devices");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
static int init = 1; static int init = 1;
module_param(init, int, 0444); module_param(init, int, 0444);

Просмотреть файл

@ -116,7 +116,7 @@ static int __devinit dmx3191d_probe_one(struct pci_dev *pdev,
out_free_irq: out_free_irq:
free_irq(shost->irq, shost); free_irq(shost->irq, shost);
out_release_region: out_release_region:
release_region(shost->io_port, DMX3191D_REGION_LEN); release_region(io, DMX3191D_REGION_LEN);
out_disable_device: out_disable_device:
pci_disable_device(pdev); pci_disable_device(pdev);
out: out:

Просмотреть файл

@ -306,10 +306,9 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
dump_stack(); dump_stack();
} }
shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
if (!shost) if (!shost)
return NULL; return NULL;
memset(shost, 0, sizeof(struct Scsi_Host) + privsize);
spin_lock_init(&shost->default_lock); spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock); scsi_assign_lock(shost, &shost->default_lock);

Просмотреть файл

@ -2412,8 +2412,7 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
spin_lock_irqsave(hosts[i]->host_lock, flags); /* Check it */ spin_lock_irqsave(hosts[i]->host_lock, flags); /* Check it */
host_index = i; host_index = i;
if (!shpnt) { if (!shpnt) {
len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n", len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter");
shpnt->host_no);
return len; return len;
} }
max_pun = subsystem_maxid(host_index); max_pun = subsystem_maxid(host_index);

Просмотреть файл

@ -5830,6 +5830,109 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
shutdown_type); shutdown_type);
} }
/**
* ipr_reset_freeze - Hold off all I/O activity
* @ipr_cmd: ipr command struct
*
* Description: If the PCI slot is frozen, hold off all I/O
* activity; then, as soon as the slot is available again,
* initiate an adapter reset.
*/
static int ipr_reset_freeze(struct ipr_cmnd *ipr_cmd)
{
/* Disallow new interrupts, avoid loop */
ipr_cmd->ioa_cfg->allow_interrupts = 0;
list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q);
ipr_cmd->done = ipr_reset_ioa_job;
return IPR_RC_JOB_RETURN;
}
/**
* ipr_pci_frozen - Called when slot has experienced a PCI bus error.
* @pdev: PCI device struct
*
* Description: This routine is called to tell us that the PCI bus
* is down. Can't do anything here, except put the device driver
* into a holding pattern, waiting for the PCI bus to come back.
*/
static void ipr_pci_frozen(struct pci_dev *pdev)
{
unsigned long flags = 0;
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_freeze, IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
}
/**
* ipr_pci_slot_reset - Called when PCI slot has been reset.
* @pdev: PCI device struct
*
* Description: This routine is called by the pci error recovery
* code after the PCI slot has been reset, just before we
* should resume normal operations.
*/
static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev)
{
unsigned long flags = 0;
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space,
IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
return PCI_ERS_RESULT_RECOVERED;
}
/**
* ipr_pci_perm_failure - Called when PCI slot is dead for good.
* @pdev: PCI device struct
*
* Description: This routine is called when the PCI bus has
* permanently failed.
*/
static void ipr_pci_perm_failure(struct pci_dev *pdev)
{
unsigned long flags = 0;
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
if (ioa_cfg->sdt_state == WAIT_FOR_DUMP)
ioa_cfg->sdt_state = ABORT_DUMP;
ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES;
ioa_cfg->in_ioa_bringdown = 1;
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
}
/**
* ipr_pci_error_detected - Called when a PCI error is detected.
* @pdev: PCI device struct
* @state: PCI channel state
*
* Description: Called when a PCI error is detected.
*
* Return value:
* PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
*/
static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
switch (state) {
case pci_channel_io_frozen:
ipr_pci_frozen(pdev);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
ipr_pci_perm_failure(pdev);
return PCI_ERS_RESULT_DISCONNECT;
break;
default:
break;
}
return PCI_ERS_RESULT_NEED_RESET;
}
/** /**
* ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..) * ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..)
* @ioa_cfg: ioa cfg struct * @ioa_cfg: ioa cfg struct
@ -6601,12 +6704,18 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
}; };
MODULE_DEVICE_TABLE(pci, ipr_pci_table); MODULE_DEVICE_TABLE(pci, ipr_pci_table);
static struct pci_error_handlers ipr_err_handler = {
.error_detected = ipr_pci_error_detected,
.slot_reset = ipr_pci_slot_reset,
};
static struct pci_driver ipr_driver = { static struct pci_driver ipr_driver = {
.name = IPR_NAME, .name = IPR_NAME,
.id_table = ipr_pci_table, .id_table = ipr_pci_table,
.probe = ipr_probe, .probe = ipr_probe,
.remove = ipr_remove, .remove = ipr_remove,
.shutdown = ipr_shutdown, .shutdown = ipr_shutdown,
.err_handler = &ipr_err_handler,
}; };
/** /**

Просмотреть файл

@ -1146,7 +1146,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
return (0); return (0);
} }
ha->ioctl_reset = 1; /* This reset request is from an IOCTL */ ha->ioctl_reset = 1; /* This reset request is from an IOCTL */
ips_eh_reset(SC); __ips_eh_reset(SC);
SC->result = DID_OK << 16; SC->result = DID_OK << 16;
SC->scsi_done(SC); SC->scsi_done(SC);
return (0); return (0);

Просмотреть файл

@ -52,7 +52,6 @@ static volatile unsigned char cmd_buffer[16];
* via PIO. * via PIO.
*/ */
int jazz_esp_detect(struct scsi_host_template *tpnt);
static int jazz_esp_release(struct Scsi_Host *shost) static int jazz_esp_release(struct Scsi_Host *shost)
{ {
if (shost->irq) if (shost->irq)
@ -75,7 +74,7 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt)
* first assumption it is there:-) * first assumption it is there:-)
*/ */
if (1) { if (1) {
esp_dev = 0; esp_dev = NULL;
esp = esp_allocate(tpnt, (void *) esp_dev); esp = esp_allocate(tpnt, (void *) esp_dev);
/* Do command transfer with programmed I/O */ /* Do command transfer with programmed I/O */
@ -94,13 +93,13 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt)
esp->dma_setup = &dma_setup; esp->dma_setup = &dma_setup;
/* Optional functions */ /* Optional functions */
esp->dma_barrier = 0; esp->dma_barrier = NULL;
esp->dma_drain = 0; esp->dma_drain = NULL;
esp->dma_invalidate = 0; esp->dma_invalidate = NULL;
esp->dma_irq_entry = 0; esp->dma_irq_entry = NULL;
esp->dma_irq_exit = 0; esp->dma_irq_exit = NULL;
esp->dma_poll = 0; esp->dma_poll = NULL;
esp->dma_reset = 0; esp->dma_reset = NULL;
esp->dma_led_off = &dma_led_off; esp->dma_led_off = &dma_led_off;
esp->dma_led_on = &dma_led_on; esp->dma_led_on = &dma_led_on;
@ -120,7 +119,7 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt)
* of DMA channel, so we can use the jazz DMA functions * of DMA channel, so we can use the jazz DMA functions
* *
*/ */
esp->dregs = JAZZ_SCSI_DMA; esp->dregs = (void *) JAZZ_SCSI_DMA;
/* ESP register base */ /* ESP register base */
esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE); esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE);

Просмотреть файл

@ -4653,6 +4653,8 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
if (!host) if (!host)
return NULL; return NULL;
host->transportt = &ata_scsi_transport_template;
ap = (struct ata_port *) &host->hostdata[0]; ap = (struct ata_port *) &host->hostdata[0];
ata_host_init(ap, host, host_set, ent, port_no); ata_host_init(ap, host, host_set, ent, port_no);
@ -5084,7 +5086,6 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_timed_out);
EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_scsi_release);

Просмотреть файл

@ -41,6 +41,7 @@
#include <scsi/scsi_eh.h> #include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_request.h> #include <scsi/scsi_request.h>
#include <scsi/scsi_transport.h>
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -52,6 +53,7 @@
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
static struct ata_device * static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
#define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE 0x1
#define RW_RECOVERY_MPAGE_LEN 12 #define RW_RECOVERY_MPAGE_LEN 12
@ -92,6 +94,14 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
0, 30 /* extended self test time, see 05-359r1 */ 0, 30 /* extended self test time, see 05-359r1 */
}; };
/*
* libata transport template. libata doesn't do real transport stuff.
* It just needs the eh_timed_out hook.
*/
struct scsi_transport_template ata_scsi_transport_template = {
.eh_timed_out = ata_scsi_timed_out,
};
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *)) void (*done)(struct scsi_cmnd *))

Просмотреть файл

@ -57,6 +57,8 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
/* libata-scsi.c */ /* libata-scsi.c */
extern struct scsi_transport_template ata_scsi_transport_template;
extern void ata_scsi_scan_host(struct ata_port *ap); extern void ata_scsi_scan_host(struct ata_port *ap);
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -121,7 +121,9 @@ struct lpfc_stats {
uint32_t elsRcvLOGO; uint32_t elsRcvLOGO;
uint32_t elsRcvPRLO; uint32_t elsRcvPRLO;
uint32_t elsRcvPRLI; uint32_t elsRcvPRLI;
uint32_t elsRcvRRQ; uint32_t elsRcvLIRR;
uint32_t elsRcvRPS;
uint32_t elsRcvRPL;
uint32_t elsXmitFLOGI; uint32_t elsXmitFLOGI;
uint32_t elsXmitPLOGI; uint32_t elsXmitPLOGI;
uint32_t elsXmitPRLI; uint32_t elsXmitPRLI;
@ -167,33 +169,35 @@ struct lpfc_sysfs_mbox {
}; };
struct lpfc_hba { struct lpfc_hba {
struct list_head hba_list; /* List of hbas/ports */
struct lpfc_sli sli; struct lpfc_sli sli;
struct lpfc_sli2_slim *slim2p; struct lpfc_sli2_slim *slim2p;
dma_addr_t slim2p_mapping; dma_addr_t slim2p_mapping;
uint16_t pci_cfg_value; uint16_t pci_cfg_value;
struct semaphore hba_can_block; struct semaphore hba_can_block;
uint32_t hba_state; int32_t hba_state;
#define LPFC_INIT_START 1 /* Initial state after board reset */ #define LPFC_STATE_UNKNOWN 0 /* HBA state is unknown */
#define LPFC_INIT_MBX_CMDS 2 /* Initialize HBA with mbox commands */ #define LPFC_WARM_START 1 /* HBA state after selective reset */
#define LPFC_LINK_DOWN 3 /* HBA initialized, link is down */ #define LPFC_INIT_START 2 /* Initial state after board reset */
#define LPFC_LINK_UP 4 /* Link is up - issue READ_LA */ #define LPFC_INIT_MBX_CMDS 3 /* Initialize HBA with mbox commands */
#define LPFC_LOCAL_CFG_LINK 5 /* local NPORT Id configured */ #define LPFC_LINK_DOWN 4 /* HBA initialized, link is down */
#define LPFC_FLOGI 6 /* FLOGI sent to Fabric */ #define LPFC_LINK_UP 5 /* Link is up - issue READ_LA */
#define LPFC_FABRIC_CFG_LINK 7 /* Fabric assigned NPORT Id #define LPFC_LOCAL_CFG_LINK 6 /* local NPORT Id configured */
#define LPFC_FLOGI 7 /* FLOGI sent to Fabric */
#define LPFC_FABRIC_CFG_LINK 8 /* Fabric assigned NPORT Id
configured */ configured */
#define LPFC_NS_REG 8 /* Register with NameServer */ #define LPFC_NS_REG 9 /* Register with NameServer */
#define LPFC_NS_QRY 9 /* Query NameServer for NPort ID list */ #define LPFC_NS_QRY 10 /* Query NameServer for NPort ID list */
#define LPFC_BUILD_DISC_LIST 10 /* Build ADISC and PLOGI lists for #define LPFC_BUILD_DISC_LIST 11 /* Build ADISC and PLOGI lists for
* device authentication / discovery */ * device authentication / discovery */
#define LPFC_DISC_AUTH 11 /* Processing ADISC list */ #define LPFC_DISC_AUTH 12 /* Processing ADISC list */
#define LPFC_CLEAR_LA 12 /* authentication cmplt - issue #define LPFC_CLEAR_LA 13 /* authentication cmplt - issue
CLEAR_LA */ CLEAR_LA */
#define LPFC_HBA_READY 32 #define LPFC_HBA_READY 32
#define LPFC_HBA_ERROR 0xff #define LPFC_HBA_ERROR -1
int32_t stopped; /* HBA has not been restarted since last ERATT */
uint8_t fc_linkspeed; /* Link speed after last READ_LA */ uint8_t fc_linkspeed; /* Link speed after last READ_LA */
uint32_t fc_eventTag; /* event tag for link attention */ uint32_t fc_eventTag; /* event tag for link attention */
@ -245,6 +249,7 @@ struct lpfc_hba {
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */
uint32_t fc_topology; /* link topology, from LINK INIT */ uint32_t fc_topology; /* link topology, from LINK INIT */
@ -289,8 +294,8 @@ struct lpfc_hba {
uint32_t cfg_link_speed; uint32_t cfg_link_speed;
uint32_t cfg_cr_delay; uint32_t cfg_cr_delay;
uint32_t cfg_cr_count; uint32_t cfg_cr_count;
uint32_t cfg_multi_ring_support;
uint32_t cfg_fdmi_on; uint32_t cfg_fdmi_on;
uint32_t cfg_fcp_bind_method;
uint32_t cfg_discovery_threads; uint32_t cfg_discovery_threads;
uint32_t cfg_max_luns; uint32_t cfg_max_luns;
uint32_t cfg_poll; uint32_t cfg_poll;

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -79,7 +79,7 @@ static ssize_t
lpfc_serialnum_show(struct class_device *cdev, char *buf) lpfc_serialnum_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber); return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
} }
@ -87,7 +87,7 @@ static ssize_t
lpfc_modeldesc_show(struct class_device *cdev, char *buf) lpfc_modeldesc_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc); return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
} }
@ -95,7 +95,7 @@ static ssize_t
lpfc_modelname_show(struct class_device *cdev, char *buf) lpfc_modelname_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName); return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
} }
@ -103,7 +103,7 @@ static ssize_t
lpfc_programtype_show(struct class_device *cdev, char *buf) lpfc_programtype_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType); return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
} }
@ -111,7 +111,7 @@ static ssize_t
lpfc_portnum_show(struct class_device *cdev, char *buf) lpfc_portnum_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port); return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
} }
@ -119,7 +119,7 @@ static ssize_t
lpfc_fwrev_show(struct class_device *cdev, char *buf) lpfc_fwrev_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
char fwrev[32]; char fwrev[32];
lpfc_decode_firmware_rev(phba, fwrev, 1); lpfc_decode_firmware_rev(phba, fwrev, 1);
return snprintf(buf, PAGE_SIZE, "%s\n",fwrev); return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
@ -130,7 +130,7 @@ lpfc_hdw_show(struct class_device *cdev, char *buf)
{ {
char hdw[9]; char hdw[9];
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
lpfc_vpd_t *vp = &phba->vpd; lpfc_vpd_t *vp = &phba->vpd;
lpfc_jedec_to_ascii(vp->rev.biuRev, hdw); lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
return snprintf(buf, PAGE_SIZE, "%s\n", hdw); return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
@ -139,16 +139,18 @@ static ssize_t
lpfc_option_rom_version_show(struct class_device *cdev, char *buf) lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion); return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
} }
static ssize_t static ssize_t
lpfc_state_show(struct class_device *cdev, char *buf) lpfc_state_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
int len = 0; int len = 0;
switch (phba->hba_state) { switch (phba->hba_state) {
case LPFC_STATE_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START: case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS: case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN: case LPFC_LINK_DOWN:
@ -194,7 +196,7 @@ static ssize_t
lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf) lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt + return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
phba->fc_unmap_cnt); phba->fc_unmap_cnt);
} }
@ -203,7 +205,7 @@ lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
static int static int
lpfc_issue_lip(struct Scsi_Host *host) lpfc_issue_lip(struct Scsi_Host *host)
{ {
struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
LPFC_MBOXQ_t *pmboxq; LPFC_MBOXQ_t *pmboxq;
int mbxstatus = MBXERR_ERROR; int mbxstatus = MBXERR_ERROR;
@ -235,7 +237,7 @@ static ssize_t
lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf) lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt); return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
} }
@ -243,7 +245,7 @@ static ssize_t
lpfc_board_online_show(struct class_device *cdev, char *buf) lpfc_board_online_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
if (phba->fc_flag & FC_OFFLINE_MODE) if (phba->fc_flag & FC_OFFLINE_MODE)
return snprintf(buf, PAGE_SIZE, "0\n"); return snprintf(buf, PAGE_SIZE, "0\n");
@ -256,7 +258,7 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
size_t count) size_t count)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct completion online_compl; struct completion online_compl;
int val=0, status=0; int val=0, status=0;
@ -278,11 +280,63 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
return -EIO; return -EIO;
} }
static ssize_t
lpfc_board_mode_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
char * state;
if (phba->hba_state == LPFC_HBA_ERROR)
state = "error";
else if (phba->hba_state == LPFC_WARM_START)
state = "warm start";
else if (phba->hba_state == LPFC_INIT_START)
state = "offline";
else
state = "online";
return snprintf(buf, PAGE_SIZE, "%s\n", state);
}
static ssize_t
lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
struct completion online_compl;
int status=0;
init_completion(&online_compl);
if(strncmp(buf, "online", sizeof("online") - 1) == 0)
lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_ONLINE);
else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_OFFLINE);
else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_WARM_START);
else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_KILL);
else
return -EINVAL;
wait_for_completion(&online_compl);
if (!status)
return strlen(buf);
else
return -EIO;
}
static ssize_t static ssize_t
lpfc_poll_show(struct class_device *cdev, char *buf) lpfc_poll_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll); return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
} }
@ -292,7 +346,7 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
size_t count) size_t count)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
uint32_t creg_val; uint32_t creg_val;
uint32_t old_val; uint32_t old_val;
int val=0; int val=0;
@ -349,7 +403,7 @@ static ssize_t \
lpfc_##attr##_show(struct class_device *cdev, char *buf) \ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
{ \ { \
struct Scsi_Host *host = class_to_shost(cdev);\ struct Scsi_Host *host = class_to_shost(cdev);\
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\ struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
int val = 0;\ int val = 0;\
val = phba->cfg_##attr;\ val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n",\ return snprintf(buf, PAGE_SIZE, "%d\n",\
@ -361,7 +415,7 @@ static ssize_t \
lpfc_##attr##_show(struct class_device *cdev, char *buf) \ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
{ \ { \
struct Scsi_Host *host = class_to_shost(cdev);\ struct Scsi_Host *host = class_to_shost(cdev);\
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\ struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
int val = 0;\ int val = 0;\
val = phba->cfg_##attr;\ val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%#x\n",\ return snprintf(buf, PAGE_SIZE, "%#x\n",\
@ -404,7 +458,7 @@ static ssize_t \
lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \ lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
{ \ { \
struct Scsi_Host *host = class_to_shost(cdev);\ struct Scsi_Host *host = class_to_shost(cdev);\
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\ struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
int val=0;\ int val=0;\
if (!isdigit(buf[0]))\ if (!isdigit(buf[0]))\
return -EINVAL;\ return -EINVAL;\
@ -480,6 +534,8 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
NULL); NULL);
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR, static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
lpfc_board_online_show, lpfc_board_online_store); lpfc_board_online_show, lpfc_board_online_store);
static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
lpfc_board_mode_show, lpfc_board_mode_store);
static int lpfc_poll = 0; static int lpfc_poll = 0;
module_param(lpfc_poll, int, 0); module_param(lpfc_poll, int, 0);
@ -519,6 +575,16 @@ LPFC_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask");
LPFC_ATTR_R(lun_queue_depth, 30, 1, 128, LPFC_ATTR_R(lun_queue_depth, 30, 1, 128,
"Max number of FCP commands we can queue to a specific LUN"); "Max number of FCP commands we can queue to a specific LUN");
/*
# hba_queue_depth: This parameter is used to limit the number of outstanding
# commands per lpfc HBA. Value range is [32,8192]. If this parameter
# value is greater than the maximum number of exchanges supported by the HBA,
# then maximum number of exchanges supported by the HBA is used to determine
# the hba_queue_depth.
*/
LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,
"Max number of FCP commands we can queue to a lpfc HBA");
/* /*
# Some disk devices have a "select ID" or "select Target" capability. # Some disk devices have a "select ID" or "select Target" capability.
# From a protocol standpoint "select ID" usually means select the # From a protocol standpoint "select ID" usually means select the
@ -550,6 +616,7 @@ LPFC_ATTR_RW(nodev_tmo, 30, 0, 255,
/* /*
# lpfc_topology: link topology for init link # lpfc_topology: link topology for init link
# 0x0 = attempt loop mode then point-to-point # 0x0 = attempt loop mode then point-to-point
# 0x01 = internal loopback mode
# 0x02 = attempt point-to-point mode only # 0x02 = attempt point-to-point mode only
# 0x04 = attempt loop mode only # 0x04 = attempt loop mode only
# 0x06 = attempt point-to-point mode then loop # 0x06 = attempt point-to-point mode then loop
@ -557,7 +624,7 @@ LPFC_ATTR_RW(nodev_tmo, 30, 0, 255,
# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6]. # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
# Default value is 0. # Default value is 0.
*/ */
LPFC_ATTR_R(topology, 0, 0, 6, "Select Fibre Channel topology"); LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology");
/* /*
# lpfc_link_speed: Link speed selection for initializing the Fibre Channel # lpfc_link_speed: Link speed selection for initializing the Fibre Channel
@ -597,12 +664,20 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
# is 0. Default value of cr_count is 1. The cr_count feature is disabled if # is 0. Default value of cr_count is 1. The cr_count feature is disabled if
# cr_delay is set to 0. # cr_delay is set to 0.
*/ */
LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an" LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an "
"interrupt response is generated"); "interrupt response is generated");
LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an" LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an "
"interrupt response is generated"); "interrupt response is generated");
/*
# lpfc_multi_ring_support: Determines how many rings to spread available
# cmd/rsp IOCB entries across.
# Value range is [1,2]. Default value is 1.
*/
LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary "
"SLI rings to spread IOCB entries across");
/* /*
# lpfc_fdmi_on: controls FDMI support. # lpfc_fdmi_on: controls FDMI support.
# 0 = no FDMI support # 0 = no FDMI support
@ -616,7 +691,7 @@ LPFC_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support");
# Specifies the maximum number of ELS cmds we can have outstanding (for # Specifies the maximum number of ELS cmds we can have outstanding (for
# discovery). Value range is [1,64]. Default value = 32. # discovery). Value range is [1,64]. Default value = 32.
*/ */
LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands" LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
"during discovery"); "during discovery");
/* /*
@ -649,6 +724,7 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_drvr_version, &class_device_attr_lpfc_drvr_version,
&class_device_attr_lpfc_log_verbose, &class_device_attr_lpfc_log_verbose,
&class_device_attr_lpfc_lun_queue_depth, &class_device_attr_lpfc_lun_queue_depth,
&class_device_attr_lpfc_hba_queue_depth,
&class_device_attr_lpfc_nodev_tmo, &class_device_attr_lpfc_nodev_tmo,
&class_device_attr_lpfc_fcp_class, &class_device_attr_lpfc_fcp_class,
&class_device_attr_lpfc_use_adisc, &class_device_attr_lpfc_use_adisc,
@ -658,11 +734,13 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_link_speed, &class_device_attr_lpfc_link_speed,
&class_device_attr_lpfc_cr_delay, &class_device_attr_lpfc_cr_delay,
&class_device_attr_lpfc_cr_count, &class_device_attr_lpfc_cr_count,
&class_device_attr_lpfc_multi_ring_support,
&class_device_attr_lpfc_fdmi_on, &class_device_attr_lpfc_fdmi_on,
&class_device_attr_lpfc_max_luns, &class_device_attr_lpfc_max_luns,
&class_device_attr_nport_evt_cnt, &class_device_attr_nport_evt_cnt,
&class_device_attr_management_version, &class_device_attr_management_version,
&class_device_attr_board_online, &class_device_attr_board_online,
&class_device_attr_board_mode,
&class_device_attr_lpfc_poll, &class_device_attr_lpfc_poll,
&class_device_attr_lpfc_poll_tmo, &class_device_attr_lpfc_poll_tmo,
NULL, NULL,
@ -674,7 +752,7 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
size_t buf_off; size_t buf_off;
struct Scsi_Host *host = class_to_shost(container_of(kobj, struct Scsi_Host *host = class_to_shost(container_of(kobj,
struct class_device, kobj)); struct class_device, kobj));
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
if ((off + count) > FF_REG_AREA_SIZE) if ((off + count) > FF_REG_AREA_SIZE)
return -ERANGE; return -ERANGE;
@ -707,7 +785,7 @@ sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
uint32_t * tmp_ptr; uint32_t * tmp_ptr;
struct Scsi_Host *host = class_to_shost(container_of(kobj, struct Scsi_Host *host = class_to_shost(container_of(kobj,
struct class_device, kobj)); struct class_device, kobj));
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
if (off > FF_REG_AREA_SIZE) if (off > FF_REG_AREA_SIZE)
return -ERANGE; return -ERANGE;
@ -762,7 +840,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{ {
struct Scsi_Host * host = struct Scsi_Host * host =
class_to_shost(container_of(kobj, struct class_device, kobj)); class_to_shost(container_of(kobj, struct class_device, kobj));
struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata;
struct lpfcMboxq * mbox = NULL; struct lpfcMboxq * mbox = NULL;
if ((count + off) > MAILBOX_CMD_SIZE) if ((count + off) > MAILBOX_CMD_SIZE)
@ -778,7 +856,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) if (!mbox)
return -ENOMEM; return -ENOMEM;
memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
} }
spin_lock_irq(host->host_lock); spin_lock_irq(host->host_lock);
@ -815,7 +893,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
struct Scsi_Host *host = struct Scsi_Host *host =
class_to_shost(container_of(kobj, struct class_device, class_to_shost(container_of(kobj, struct class_device,
kobj)); kobj));
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
int rc; int rc;
if (off > sizeof(MAILBOX_t)) if (off > sizeof(MAILBOX_t))
@ -872,8 +950,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
case MBX_DUMP_MEMORY: case MBX_DUMP_MEMORY:
case MBX_DOWN_LOAD: case MBX_DOWN_LOAD:
case MBX_UPDATE_CFG: case MBX_UPDATE_CFG:
case MBX_KILL_BOARD:
case MBX_LOAD_AREA: case MBX_LOAD_AREA:
case MBX_LOAD_EXP_ROM: case MBX_LOAD_EXP_ROM:
case MBX_BEACON:
case MBX_DEL_LD_ENTRY:
break; break;
case MBX_READ_SPARM64: case MBX_READ_SPARM64:
case MBX_READ_LA: case MBX_READ_LA:
@ -990,7 +1071,7 @@ lpfc_free_sysfs_attr(struct lpfc_hba *phba)
static void static void
lpfc_get_host_port_id(struct Scsi_Host *shost) lpfc_get_host_port_id(struct Scsi_Host *shost)
{ {
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
/* note: fc_myDID already in cpu endianness */ /* note: fc_myDID already in cpu endianness */
fc_host_port_id(shost) = phba->fc_myDID; fc_host_port_id(shost) = phba->fc_myDID;
} }
@ -998,7 +1079,7 @@ lpfc_get_host_port_id(struct Scsi_Host *shost)
static void static void
lpfc_get_host_port_type(struct Scsi_Host *shost) lpfc_get_host_port_type(struct Scsi_Host *shost)
{ {
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
@ -1023,7 +1104,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
static void static void
lpfc_get_host_port_state(struct Scsi_Host *shost) lpfc_get_host_port_state(struct Scsi_Host *shost)
{ {
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
@ -1031,6 +1112,8 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
else { else {
switch (phba->hba_state) { switch (phba->hba_state) {
case LPFC_STATE_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START: case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS: case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN: case LPFC_LINK_DOWN:
@ -1064,7 +1147,7 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
static void static void
lpfc_get_host_speed(struct Scsi_Host *shost) lpfc_get_host_speed(struct Scsi_Host *shost)
{ {
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
@ -1091,7 +1174,7 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
static void static void
lpfc_get_host_fabric_name (struct Scsi_Host *shost) lpfc_get_host_fabric_name (struct Scsi_Host *shost)
{ {
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
u64 node_name; u64 node_name;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
@ -1113,7 +1196,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
static struct fc_host_statistics * static struct fc_host_statistics *
lpfc_get_stats(struct Scsi_Host *shost) lpfc_get_stats(struct Scsi_Host *shost)
{ {
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct fc_host_statistics *hs = &phba->link_stats; struct fc_host_statistics *hs = &phba->link_stats;
LPFC_MBOXQ_t *pmboxq; LPFC_MBOXQ_t *pmboxq;
@ -1203,7 +1286,7 @@ static void
lpfc_get_starget_port_id(struct scsi_target *starget) lpfc_get_starget_port_id(struct scsi_target *starget)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
uint32_t did = -1; uint32_t did = -1;
struct lpfc_nodelist *ndlp = NULL; struct lpfc_nodelist *ndlp = NULL;
@ -1224,7 +1307,7 @@ static void
lpfc_get_starget_node_name(struct scsi_target *starget) lpfc_get_starget_node_name(struct scsi_target *starget)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
u64 node_name = 0; u64 node_name = 0;
struct lpfc_nodelist *ndlp = NULL; struct lpfc_nodelist *ndlp = NULL;
@ -1245,7 +1328,7 @@ static void
lpfc_get_starget_port_name(struct scsi_target *starget) lpfc_get_starget_port_name(struct scsi_target *starget)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
u64 port_name = 0; u64 port_name = 0;
struct lpfc_nodelist *ndlp = NULL; struct lpfc_nodelist *ndlp = NULL;
@ -1366,6 +1449,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_log_verbose_init(phba, lpfc_log_verbose); lpfc_log_verbose_init(phba, lpfc_log_verbose);
lpfc_cr_delay_init(phba, lpfc_cr_delay); lpfc_cr_delay_init(phba, lpfc_cr_delay);
lpfc_cr_count_init(phba, lpfc_cr_count); lpfc_cr_count_init(phba, lpfc_cr_count);
lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support);
lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth); lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth);
lpfc_fcp_class_init(phba, lpfc_fcp_class); lpfc_fcp_class_init(phba, lpfc_fcp_class);
lpfc_use_adisc_init(phba, lpfc_use_adisc); lpfc_use_adisc_init(phba, lpfc_use_adisc);
@ -1411,5 +1495,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
default: default:
phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH; phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH;
} }
if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth)
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
return; return;
} }

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
@ -26,6 +26,7 @@ void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *, int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
uint32_t); uint32_t);
@ -42,9 +43,6 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_nlp_plogi(struct lpfc_hba *, struct lpfc_nodelist *);
int lpfc_nlp_adisc(struct lpfc_hba *, struct lpfc_nodelist *);
int lpfc_nlp_unmapped(struct lpfc_hba *, struct lpfc_nodelist *);
int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int); int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int);
void lpfc_set_disctmo(struct lpfc_hba *); void lpfc_set_disctmo(struct lpfc_hba *);
int lpfc_can_disctmo(struct lpfc_hba *); int lpfc_can_disctmo(struct lpfc_hba *);
@ -54,12 +52,10 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *); int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t); void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t); struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
struct lpfc_nodelist *lpfc_setup_rscn_node(struct lpfc_hba *, uint32_t);
void lpfc_disc_list_loopmap(struct lpfc_hba *); void lpfc_disc_list_loopmap(struct lpfc_hba *);
void lpfc_disc_start(struct lpfc_hba *); void lpfc_disc_start(struct lpfc_hba *);
void lpfc_disc_flush_list(struct lpfc_hba *); void lpfc_disc_flush_list(struct lpfc_hba *);
void lpfc_disc_timeout(unsigned long); void lpfc_disc_timeout(unsigned long);
void lpfc_scan_timeout(unsigned long);
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
@ -68,19 +64,13 @@ int lpfc_do_work(void *);
int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *, int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
uint32_t); uint32_t);
uint32_t lpfc_cmpl_prli_reglogin_issue(struct lpfc_hba *,
struct lpfc_nodelist *, void *,
uint32_t);
uint32_t lpfc_cmpl_plogi_prli_issue(struct lpfc_hba *, struct lpfc_nodelist *,
void *, uint32_t);
int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *, int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
struct serv_parm *, uint32_t); struct serv_parm *, uint32_t);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp, int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
int); int);
int lpfc_els_abort_flogi(struct lpfc_hba *); int lpfc_els_abort_flogi(struct lpfc_hba *);
int lpfc_initial_flogi(struct lpfc_hba *); int lpfc_initial_flogi(struct lpfc_hba *);
int lpfc_issue_els_plogi(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
@ -94,6 +84,7 @@ int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_nodelist *); struct lpfc_nodelist *);
int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *, int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_nodelist *); struct lpfc_nodelist *);
void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_els_retry_delay(unsigned long); void lpfc_els_retry_delay(unsigned long);
void lpfc_els_retry_delay_handler(struct lpfc_nodelist *); void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
@ -117,18 +108,15 @@ void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
int lpfc_config_port_prep(struct lpfc_hba *); int lpfc_config_port_prep(struct lpfc_hba *);
int lpfc_config_port_post(struct lpfc_hba *); int lpfc_config_port_post(struct lpfc_hba *);
int lpfc_hba_down_prep(struct lpfc_hba *); int lpfc_hba_down_prep(struct lpfc_hba *);
int lpfc_hba_down_post(struct lpfc_hba *);
void lpfc_hba_init(struct lpfc_hba *, uint32_t *); void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
uint8_t *lpfc_get_lpfchba_info(struct lpfc_hba *, uint8_t *);
int lpfc_fcp_abort(struct lpfc_hba *, int, int, int);
int lpfc_online(struct lpfc_hba *); int lpfc_online(struct lpfc_hba *);
int lpfc_offline(struct lpfc_hba *); int lpfc_offline(struct lpfc_hba *);
int lpfc_sli_setup(struct lpfc_hba *); int lpfc_sli_setup(struct lpfc_hba *);
int lpfc_sli_queue_setup(struct lpfc_hba *); int lpfc_sli_queue_setup(struct lpfc_hba *);
void lpfc_slim_access(struct lpfc_hba *);
void lpfc_handle_eratt(struct lpfc_hba *); void lpfc_handle_eratt(struct lpfc_hba *);
void lpfc_handle_latt(struct lpfc_hba *); void lpfc_handle_latt(struct lpfc_hba *);
@ -137,6 +125,7 @@ irqreturn_t lpfc_intr_handler(int, void *, struct pt_regs *);
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *); void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
@ -149,6 +138,12 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
void lpfc_reset_barrier(struct lpfc_hba * phba);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_brdreset(struct lpfc_hba *);
int lpfc_sli_brdrestart(struct lpfc_hba *);
int lpfc_sli_hba_setup(struct lpfc_hba *); int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_hba_down(struct lpfc_hba *); int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
@ -174,12 +169,10 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout(unsigned long);
void lpfc_mbox_timeout_handler(struct lpfc_hba *); void lpfc_mbox_timeout_handler(struct lpfc_hba *);
void lpfc_map_fcp_cmnd_to_bpl(struct lpfc_hba *, struct lpfc_scsi_buf *);
void lpfc_free_scsi_cmd(struct lpfc_scsi_buf *);
uint32_t lpfc_os_timeout_transform(struct lpfc_hba *, uint32_t);
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t);
uint32_t did); struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, uint32_t,
struct lpfc_name *);
int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
uint32_t timeout); uint32_t timeout);

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
@ -260,8 +260,10 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
icmd->un.genreq64.w5.hcsw.Rctl = FC_UNSOL_CTL; icmd->un.genreq64.w5.hcsw.Rctl = FC_UNSOL_CTL;
icmd->un.genreq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP; icmd->un.genreq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP;
if (!tmo) if (!tmo) {
tmo = (2 * phba->fc_ratov) + 1; /* FC spec states we need 3 * ratov for CT requests */
tmo = (3 * phba->fc_ratov);
}
icmd->ulpTimeout = tmo; icmd->ulpTimeout = tmo;
icmd->ulpBdeCount = 1; icmd->ulpBdeCount = 1;
icmd->ulpLe = 1; icmd->ulpLe = 1;
@ -321,6 +323,7 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
struct lpfc_sli_ct_request *Response = struct lpfc_sli_ct_request *Response =
(struct lpfc_sli_ct_request *) mp->virt; (struct lpfc_sli_ct_request *) mp->virt;
struct lpfc_nodelist *ndlp = NULL; struct lpfc_nodelist *ndlp = NULL;
struct lpfc_nodelist *next_ndlp;
struct lpfc_dmabuf *mlast, *next_mp; struct lpfc_dmabuf *mlast, *next_mp;
uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType; uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
uint32_t Did; uint32_t Did;
@ -389,8 +392,36 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
nsout1: nsout1:
list_del(&head); list_del(&head);
/* Here we are finished in the case RSCN */ /*
* The driver has cycled through all Nports in the RSCN payload.
* Complete the handling by cleaning up and marking the
* current driver state.
*/
if (phba->hba_state == LPFC_HBA_READY) { if (phba->hba_state == LPFC_HBA_READY) {
/*
* Switch ports that connect a loop of multiple targets need
* special consideration. The driver wants to unregister the
* rpi only on the target that was pulled from the loop. On
* RSCN, the driver wants to rediscover an NPort only if the
* driver flagged it as NLP_NPR_2B_DISC. Provided adisc is
* not enabled and the NPort is not capable of retransmissions
* (FC Tape) prevent timing races with the scsi error handler by
* unregistering the Nport's RPI. This action causes all
* outstanding IO to flush back to the midlayer.
*/
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
nlp_listp) {
if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
(lpfc_rscn_payload_check(phba, ndlp->nlp_DID))) {
if ((phba->cfg_use_adisc == 0) &&
!(ndlp->nlp_fcp_info &
NLP_FCP_2_DEVICE)) {
lpfc_unreg_rpi(phba, ndlp);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
}
}
}
lpfc_els_flush_rscn(phba); lpfc_els_flush_rscn(phba);
spin_lock_irq(phba->host->host_lock); spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */ phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
@ -449,6 +480,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
CTrsp = (struct lpfc_sli_ct_request *) outp->virt; CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
if (CTrsp->CommandResponse.bits.CmdRsp == if (CTrsp->CommandResponse.bits.CmdRsp ==
be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0239 NameServer Rsp "
"Data: x%x\n",
phba->brd_no,
phba->fc_flag);
lpfc_ns_rsp(phba, outp, lpfc_ns_rsp(phba, outp,
(uint32_t) (irsp->un.genreq64.bdl.bdeSize)); (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
} else if (CTrsp->CommandResponse.bits.CmdRsp == } else if (CTrsp->CommandResponse.bits.CmdRsp ==
@ -978,19 +1014,19 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size);
ae->ad.bits.AttrType = be16_to_cpu(SUPPORTED_SPEED); ae->ad.bits.AttrType = be16_to_cpu(SUPPORTED_SPEED);
ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
if (FC_JEDEC_ID(vp->rev.biuRev) == VIPER_JEDEC_ID)
ae->un.SupportSpeed = 0;
if (phba->lmt & LMT_10Gb)
ae->un.SupportSpeed = HBA_PORTSPEED_10GBIT; ae->un.SupportSpeed = HBA_PORTSPEED_10GBIT;
else if (FC_JEDEC_ID(vp->rev.biuRev) == HELIOS_JEDEC_ID) if (phba->lmt & LMT_8Gb)
ae->un.SupportSpeed = HBA_PORTSPEED_4GBIT; ae->un.SupportSpeed |= HBA_PORTSPEED_8GBIT;
else if ((FC_JEDEC_ID(vp->rev.biuRev) == if (phba->lmt & LMT_4Gb)
CENTAUR_2G_JEDEC_ID) ae->un.SupportSpeed |= HBA_PORTSPEED_4GBIT;
|| (FC_JEDEC_ID(vp->rev.biuRev) == if (phba->lmt & LMT_2Gb)
PEGASUS_JEDEC_ID) ae->un.SupportSpeed |= HBA_PORTSPEED_2GBIT;
|| (FC_JEDEC_ID(vp->rev.biuRev) == if (phba->lmt & LMT_1Gb)
THOR_JEDEC_ID)) ae->un.SupportSpeed |= HBA_PORTSPEED_1GBIT;
ae->un.SupportSpeed = HBA_PORTSPEED_2GBIT;
else
ae->un.SupportSpeed = HBA_PORTSPEED_1GBIT;
pab->ab.EntryCnt++; pab->ab.EntryCnt++;
size += FOURBYTES + 4; size += FOURBYTES + 4;
@ -1130,11 +1166,6 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
{ {
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
spin_lock_irq(phba->host->host_lock);
if (!(phba->work_hba_events & WORKER_FDMI_TMO)) {
spin_unlock_irq(phba->host->host_lock);
return;
}
ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID); ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID);
if (ndlp) { if (ndlp) {
if (system_utsname.nodename[0] != '\0') { if (system_utsname.nodename[0] != '\0') {
@ -1143,7 +1174,6 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
} }
} }
spin_unlock_irq(phba->host->host_lock);
return; return;
} }

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
@ -28,18 +28,24 @@
* This is used by Fibre Channel protocol to support FCP. * This is used by Fibre Channel protocol to support FCP.
*/ */
/* worker thread events */
enum lpfc_work_type {
LPFC_EVT_NODEV_TMO,
LPFC_EVT_ONLINE,
LPFC_EVT_OFFLINE,
LPFC_EVT_WARM_START,
LPFC_EVT_KILL,
LPFC_EVT_ELS_RETRY,
};
/* structure used to queue event to the discovery tasklet */ /* structure used to queue event to the discovery tasklet */
struct lpfc_work_evt { struct lpfc_work_evt {
struct list_head evt_listp; struct list_head evt_listp;
void * evt_arg1; void * evt_arg1;
void * evt_arg2; void * evt_arg2;
uint32_t evt; enum lpfc_work_type evt;
}; };
#define LPFC_EVT_NODEV_TMO 0x1
#define LPFC_EVT_ONLINE 0x2
#define LPFC_EVT_OFFLINE 0x3
#define LPFC_EVT_ELS_RETRY 0x4
struct lpfc_nodelist { struct lpfc_nodelist {
struct list_head nlp_listp; struct list_head nlp_listp;
@ -56,6 +62,7 @@ struct lpfc_nodelist {
uint16_t nlp_rpi; uint16_t nlp_rpi;
uint16_t nlp_state; /* state transition indicator */ uint16_t nlp_state; /* state transition indicator */
uint16_t nlp_prev_state; /* state transition indicator */
uint16_t nlp_xri; /* output exchange id for RPI */ uint16_t nlp_xri; /* output exchange id for RPI */
uint16_t nlp_sid; /* scsi id */ uint16_t nlp_sid; /* scsi id */
#define NLP_NO_SID 0xffff #define NLP_NO_SID 0xffff

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
@ -454,10 +454,13 @@ struct serv_parm { /* Structure is in Big Endian format */
#define ELS_CMD_ADISC 0x52000000 #define ELS_CMD_ADISC 0x52000000
#define ELS_CMD_FARP 0x54000000 #define ELS_CMD_FARP 0x54000000
#define ELS_CMD_FARPR 0x55000000 #define ELS_CMD_FARPR 0x55000000
#define ELS_CMD_RPS 0x56000000
#define ELS_CMD_RPL 0x57000000
#define ELS_CMD_FAN 0x60000000 #define ELS_CMD_FAN 0x60000000
#define ELS_CMD_RSCN 0x61040000 #define ELS_CMD_RSCN 0x61040000
#define ELS_CMD_SCR 0x62000000 #define ELS_CMD_SCR 0x62000000
#define ELS_CMD_RNID 0x78000000 #define ELS_CMD_RNID 0x78000000
#define ELS_CMD_LIRR 0x7A000000
#else /* __LITTLE_ENDIAN_BITFIELD */ #else /* __LITTLE_ENDIAN_BITFIELD */
#define ELS_CMD_MASK 0xffff #define ELS_CMD_MASK 0xffff
#define ELS_RSP_MASK 0xff #define ELS_RSP_MASK 0xff
@ -486,10 +489,13 @@ struct serv_parm { /* Structure is in Big Endian format */
#define ELS_CMD_ADISC 0x52 #define ELS_CMD_ADISC 0x52
#define ELS_CMD_FARP 0x54 #define ELS_CMD_FARP 0x54
#define ELS_CMD_FARPR 0x55 #define ELS_CMD_FARPR 0x55
#define ELS_CMD_RPS 0x56
#define ELS_CMD_RPL 0x57
#define ELS_CMD_FAN 0x60 #define ELS_CMD_FAN 0x60
#define ELS_CMD_RSCN 0x0461 #define ELS_CMD_RSCN 0x0461
#define ELS_CMD_SCR 0x62 #define ELS_CMD_SCR 0x62
#define ELS_CMD_RNID 0x78 #define ELS_CMD_RNID 0x78
#define ELS_CMD_LIRR 0x7A
#endif #endif
/* /*
@ -758,12 +764,40 @@ typedef struct _RNID { /* Structure is in Big Endian format */
} un; } un;
} RNID; } RNID;
typedef struct _RRQ { /* Structure is in Big Endian format */ typedef struct _RPS { /* Structure is in Big Endian format */
uint32_t SID; union {
uint16_t Oxid; uint32_t portNum;
uint16_t Rxid; struct lpfc_name portName;
uint8_t resv[32]; /* optional association hdr */ } un;
} RRQ; } RPS;
typedef struct _RPS_RSP { /* Structure is in Big Endian format */
uint16_t rsvd1;
uint16_t portStatus;
uint32_t linkFailureCnt;
uint32_t lossSyncCnt;
uint32_t lossSignalCnt;
uint32_t primSeqErrCnt;
uint32_t invalidXmitWord;
uint32_t crcCnt;
} RPS_RSP;
typedef struct _RPL { /* Structure is in Big Endian format */
uint32_t maxsize;
uint32_t index;
} RPL;
typedef struct _PORT_NUM_BLK {
uint32_t portNum;
uint32_t portID;
struct lpfc_name portName;
} PORT_NUM_BLK;
typedef struct _RPL_RSP { /* Structure is in Big Endian format */
uint32_t listLen;
uint32_t index;
PORT_NUM_BLK port_num_blk;
} RPL_RSP;
/* This is used for RSCN command */ /* This is used for RSCN command */
typedef struct _D_ID { /* Structure is in Big Endian format */ typedef struct _D_ID { /* Structure is in Big Endian format */
@ -804,7 +838,6 @@ typedef struct _ELS_PKT { /* Structure is in Big Endian format */
FARP farp; /* Payload for FARP/ACC */ FARP farp; /* Payload for FARP/ACC */
FAN fan; /* Payload for FAN */ FAN fan; /* Payload for FAN */
SCR scr; /* Payload for SCR/ACC */ SCR scr; /* Payload for SCR/ACC */
RRQ rrq; /* Payload for RRQ */
RNID rnid; /* Payload for RNID */ RNID rnid; /* Payload for RNID */
uint8_t pad[128 - 4]; /* Pad out to payload of 128 bytes */ uint8_t pad[128 - 4]; /* Pad out to payload of 128 bytes */
} un; } un;
@ -1200,7 +1233,9 @@ typedef struct { /* FireFly BIU registers */
#define MBX_SET_MASK 0x20 #define MBX_SET_MASK 0x20
#define MBX_SET_SLIM 0x21 #define MBX_SET_SLIM 0x21
#define MBX_UNREG_D_ID 0x23 #define MBX_UNREG_D_ID 0x23
#define MBX_KILL_BOARD 0x24
#define MBX_CONFIG_FARP 0x25 #define MBX_CONFIG_FARP 0x25
#define MBX_BEACON 0x2A
#define MBX_LOAD_AREA 0x81 #define MBX_LOAD_AREA 0x81
#define MBX_RUN_BIU_DIAG64 0x84 #define MBX_RUN_BIU_DIAG64 0x84
@ -1676,13 +1711,13 @@ typedef struct {
uint32_t rttov; uint32_t rttov;
uint32_t altov; uint32_t altov;
uint32_t lmt; uint32_t lmt;
#define LMT_RESERVED 0x0 /* Not used */ #define LMT_RESERVED 0x000 /* Not used */
#define LMT_266_10bit 0x1 /* 265.625 Mbaud 10 bit iface */ #define LMT_1Gb 0x004
#define LMT_532_10bit 0x2 /* 531.25 Mbaud 10 bit iface */ #define LMT_2Gb 0x008
#define LMT_1063_20bit 0x3 /* 1062.5 Mbaud 20 bit iface */ #define LMT_4Gb 0x040
#define LMT_1063_10bit 0x4 /* 1062.5 Mbaud 10 bit iface */ #define LMT_8Gb 0x080
#define LMT_2125_10bit 0x8 /* 2125 Mbaud 10 bit iface */ #define LMT_10Gb 0x100
#define LMT_4250_10bit 0x40 /* 4250 Mbaud 10 bit iface */
uint32_t rsvd2; uint32_t rsvd2;
uint32_t rsvd3; uint32_t rsvd3;

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -42,7 +42,7 @@
#include "lpfc_crtn.h" #include "lpfc_crtn.h"
#include "lpfc_version.h" #include "lpfc_version.h"
static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *); static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
static int lpfc_post_rcv_buf(struct lpfc_hba *); static int lpfc_post_rcv_buf(struct lpfc_hba *);
@ -161,9 +161,6 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
memcpy(phba->RandomData, (char *)&mb->un.varWords[24], memcpy(phba->RandomData, (char *)&mb->un.varWords[24],
sizeof (phba->RandomData)); sizeof (phba->RandomData));
/* Get the default values for Model Name and Description */
lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
/* Get adapter VPD information */ /* Get adapter VPD information */
pmb->context2 = kmalloc(DMP_RSP_SIZE, GFP_KERNEL); pmb->context2 = kmalloc(DMP_RSP_SIZE, GFP_KERNEL);
if (!pmb->context2) if (!pmb->context2)
@ -182,16 +179,15 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
"mbxCmd x%x DUMP VPD, mbxStatus x%x\n", "mbxCmd x%x DUMP VPD, mbxStatus x%x\n",
phba->brd_no, phba->brd_no,
mb->mbxCommand, mb->mbxStatus); mb->mbxCommand, mb->mbxStatus);
kfree(lpfc_vpd_data); mb->un.varDmp.word_cnt = 0;
lpfc_vpd_data = NULL;
break;
} }
if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset, lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset,
mb->un.varDmp.word_cnt); mb->un.varDmp.word_cnt);
offset += mb->un.varDmp.word_cnt; offset += mb->un.varDmp.word_cnt;
} while (mb->un.varDmp.word_cnt); } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
lpfc_parse_vpd(phba, lpfc_vpd_data); lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
kfree(lpfc_vpd_data); kfree(lpfc_vpd_data);
out_free_context2: out_free_context2:
@ -327,13 +323,22 @@ lpfc_config_port_post(struct lpfc_hba * phba)
mb->un.varRdConfig.max_xri + 1; mb->un.varRdConfig.max_xri + 1;
phba->lmt = mb->un.varRdConfig.lmt; phba->lmt = mb->un.varRdConfig.lmt;
/* HBA is not 4GB capable, or HBA is not 2GB capable,
don't let link speed ask for it */ /* Get the default values for Model Name and Description */
if ((((phba->lmt & LMT_4250_10bit) != LMT_4250_10bit) && lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
(phba->cfg_link_speed > LINK_SPEED_2G)) ||
(((phba->lmt & LMT_2125_10bit) != LMT_2125_10bit) && if ((phba->cfg_link_speed > LINK_SPEED_10G)
(phba->cfg_link_speed > LINK_SPEED_1G))) { || ((phba->cfg_link_speed == LINK_SPEED_1G)
/* Reset link speed to auto. 1G/2GB HBA cfg'd for 4G */ && !(phba->lmt & LMT_1Gb))
|| ((phba->cfg_link_speed == LINK_SPEED_2G)
&& !(phba->lmt & LMT_2Gb))
|| ((phba->cfg_link_speed == LINK_SPEED_4G)
&& !(phba->lmt & LMT_4Gb))
|| ((phba->cfg_link_speed == LINK_SPEED_8G)
&& !(phba->lmt & LMT_8Gb))
|| ((phba->cfg_link_speed == LINK_SPEED_10G)
&& !(phba->lmt & LMT_10Gb))) {
/* Reset link speed to auto */
lpfc_printf_log(phba, lpfc_printf_log(phba,
KERN_WARNING, KERN_WARNING,
LOG_LINK_EVENT, LOG_LINK_EVENT,
@ -462,6 +467,40 @@ lpfc_hba_down_prep(struct lpfc_hba * phba)
return (0); return (0);
} }
/************************************************************************/
/* */
/* lpfc_hba_down_post */
/* This routine will do uninitialization after the HBA is reset */
/* when bringing down the SLI Layer. */
/* This routine returns 0 on success. Any other return value */
/* indicates an error. */
/* */
/************************************************************************/
int
lpfc_hba_down_post(struct lpfc_hba * phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp;
int i;
/* Cleanup preposted buffers on the ELS ring */
pring = &psli->ring[LPFC_ELS_RING];
list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
list_del(&mp->list);
pring->postbufq_cnt--;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
}
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
lpfc_sli_abort_iocb_ring(phba, pring);
}
return 0;
}
/************************************************************************/ /************************************************************************/
/* */ /* */
/* lpfc_handle_eratt */ /* lpfc_handle_eratt */
@ -476,20 +515,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
/*
* If a reset is sent to the HBA restore PCI configuration registers.
*/
if ( phba->hba_state == LPFC_INIT_START ) {
mdelay(1);
readl(phba->HCregaddr); /* flush */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
/* Restore PCI cmd register */
pci_write_config_word(phba->pcidev,
PCI_COMMAND, phba->pci_cfg_value);
}
if (phba->work_hs & HS_FFER6) { if (phba->work_hs & HS_FFER6) {
/* Re-establishing Link */ /* Re-establishing Link */
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
@ -499,6 +524,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
phba->work_status[0], phba->work_status[1]); phba->work_status[0], phba->work_status[1]);
spin_lock_irq(phba->host->host_lock); spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_ESTABLISH_LINK; phba->fc_flag |= FC_ESTABLISH_LINK;
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(phba->host->host_lock); spin_unlock_irq(phba->host->host_lock);
/* /*
@ -516,6 +542,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
* attempt to restart it. * attempt to restart it.
*/ */
lpfc_offline(phba); lpfc_offline(phba);
lpfc_sli_brdrestart(phba);
if (lpfc_online(phba) == 0) { /* Initialize the HBA */ if (lpfc_online(phba) == 0) { /* Initialize the HBA */
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
return; return;
@ -531,8 +558,10 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
phba->brd_no, phba->work_hs, phba->brd_no, phba->work_hs,
phba->work_status[0], phba->work_status[1]); phba->work_status[0], phba->work_status[1]);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
lpfc_offline(phba); lpfc_offline(phba);
phba->hba_state = LPFC_HBA_ERROR;
lpfc_hba_down_post(phba);
} }
} }
@ -623,7 +652,7 @@ lpfc_handle_latt_err_exit:
/* */ /* */
/************************************************************************/ /************************************************************************/
static int static int
lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd) lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
{ {
uint8_t lenlo, lenhi; uint8_t lenlo, lenhi;
uint32_t Length; uint32_t Length;
@ -642,9 +671,10 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd)
phba->brd_no, phba->brd_no,
(uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2], (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
(uint32_t) vpd[3]); (uint32_t) vpd[3]);
do { while (!finished && (index < (len - 4))) {
switch (vpd[index]) { switch (vpd[index]) {
case 0x82: case 0x82:
case 0x91:
index += 1; index += 1;
lenlo = vpd[index]; lenlo = vpd[index];
index += 1; index += 1;
@ -660,7 +690,8 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd)
lenhi = vpd[index]; lenhi = vpd[index];
index += 1; index += 1;
Length = ((((unsigned short)lenhi) << 8) + lenlo); Length = ((((unsigned short)lenhi) << 8) + lenlo);
if (Length > len - index)
Length = len - index;
while (Length > 0) { while (Length > 0) {
/* Look for Serial Number */ /* Look for Serial Number */
if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) { if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) {
@ -754,7 +785,7 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd)
index ++; index ++;
break; break;
} }
} while (!finished && (index < 108)); }
return(1); return(1);
} }
@ -765,137 +796,173 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
lpfc_vpd_t *vp; lpfc_vpd_t *vp;
uint16_t dev_id = phba->pcidev->device; uint16_t dev_id = phba->pcidev->device;
uint16_t dev_subid = phba->pcidev->subsystem_device; uint16_t dev_subid = phba->pcidev->subsystem_device;
uint8_t hdrtype = phba->pcidev->hdr_type; uint8_t hdrtype;
char *model_str = ""; int max_speed;
char * ports;
struct {
char * name;
int max_speed;
char * ports;
char * bus;
} m;
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
ports = (hdrtype == 0x80) ? "2-port " : "";
if (mdp && mdp[0] != '\0'
&& descp && descp[0] != '\0')
return;
if (phba->lmt & LMT_10Gb)
max_speed = 10;
else if (phba->lmt & LMT_8Gb)
max_speed = 8;
else if (phba->lmt & LMT_4Gb)
max_speed = 4;
else if (phba->lmt & LMT_2Gb)
max_speed = 2;
else
max_speed = 1;
vp = &phba->vpd; vp = &phba->vpd;
switch (dev_id) { switch (dev_id) {
case PCI_DEVICE_ID_FIREFLY: case PCI_DEVICE_ID_FIREFLY:
model_str = "LP6000 1Gb PCI"; m = (typeof(m)){"LP6000", max_speed, "", "PCI"};
break; break;
case PCI_DEVICE_ID_SUPERFLY: case PCI_DEVICE_ID_SUPERFLY:
if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
model_str = "LP7000 1Gb PCI"; m = (typeof(m)){"LP7000", max_speed, "", "PCI"};
else else
model_str = "LP7000E 1Gb PCI"; m = (typeof(m)){"LP7000E", max_speed, "", "PCI"};
break; break;
case PCI_DEVICE_ID_DRAGONFLY: case PCI_DEVICE_ID_DRAGONFLY:
model_str = "LP8000 1Gb PCI"; m = (typeof(m)){"LP8000", max_speed, "", "PCI"};
break; break;
case PCI_DEVICE_ID_CENTAUR: case PCI_DEVICE_ID_CENTAUR:
if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
model_str = "LP9002 2Gb PCI"; m = (typeof(m)){"LP9002", max_speed, "", "PCI"};
else else
model_str = "LP9000 1Gb PCI"; m = (typeof(m)){"LP9000", max_speed, "", "PCI"};
break; break;
case PCI_DEVICE_ID_RFLY: case PCI_DEVICE_ID_RFLY:
model_str = "LP952 2Gb PCI"; m = (typeof(m)){"LP952", max_speed, "", "PCI"};
break; break;
case PCI_DEVICE_ID_PEGASUS: case PCI_DEVICE_ID_PEGASUS:
model_str = "LP9802 2Gb PCI-X"; m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"};
break; break;
case PCI_DEVICE_ID_THOR: case PCI_DEVICE_ID_THOR:
if (hdrtype == 0x80) if (hdrtype == 0x80)
model_str = "LP10000DC 2Gb 2-port PCI-X"; m = (typeof(m)){"LP10000DC",
max_speed, ports, "PCI-X"};
else else
model_str = "LP10000 2Gb PCI-X"; m = (typeof(m)){"LP10000",
max_speed, ports, "PCI-X"};
break; break;
case PCI_DEVICE_ID_VIPER: case PCI_DEVICE_ID_VIPER:
model_str = "LPX1000 10Gb PCI-X"; m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"};
break; break;
case PCI_DEVICE_ID_PFLY: case PCI_DEVICE_ID_PFLY:
model_str = "LP982 2Gb PCI-X"; m = (typeof(m)){"LP982", max_speed, "", "PCI-X"};
break; break;
case PCI_DEVICE_ID_TFLY: case PCI_DEVICE_ID_TFLY:
if (hdrtype == 0x80) if (hdrtype == 0x80)
model_str = "LP1050DC 2Gb 2-port PCI-X"; m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"};
else else
model_str = "LP1050 2Gb PCI-X"; m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"};
break; break;
case PCI_DEVICE_ID_HELIOS: case PCI_DEVICE_ID_HELIOS:
if (hdrtype == 0x80) if (hdrtype == 0x80)
model_str = "LP11002 4Gb 2-port PCI-X2"; m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"};
else else
model_str = "LP11000 4Gb PCI-X2"; m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"};
break; break;
case PCI_DEVICE_ID_HELIOS_SCSP: case PCI_DEVICE_ID_HELIOS_SCSP:
model_str = "LP11000-SP 4Gb PCI-X2"; m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"};
break; break;
case PCI_DEVICE_ID_HELIOS_DCSP: case PCI_DEVICE_ID_HELIOS_DCSP:
model_str = "LP11002-SP 4Gb 2-port PCI-X2"; m = (typeof(m)){"LP11002-SP", max_speed, ports, "PCI-X2"};
break; break;
case PCI_DEVICE_ID_NEPTUNE: case PCI_DEVICE_ID_NEPTUNE:
if (hdrtype == 0x80) if (hdrtype == 0x80)
model_str = "LPe1002 4Gb 2-port"; m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"};
else else
model_str = "LPe1000 4Gb PCIe"; m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_NEPTUNE_SCSP: case PCI_DEVICE_ID_NEPTUNE_SCSP:
model_str = "LPe1000-SP 4Gb PCIe"; m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_NEPTUNE_DCSP: case PCI_DEVICE_ID_NEPTUNE_DCSP:
model_str = "LPe1002-SP 4Gb 2-port PCIe"; m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_BMID: case PCI_DEVICE_ID_BMID:
model_str = "LP1150 4Gb PCI-X2"; m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"};
break; break;
case PCI_DEVICE_ID_BSMB: case PCI_DEVICE_ID_BSMB:
model_str = "LP111 4Gb PCI-X2"; m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"};
break; break;
case PCI_DEVICE_ID_ZEPHYR: case PCI_DEVICE_ID_ZEPHYR:
if (hdrtype == 0x80) if (hdrtype == 0x80)
model_str = "LPe11002 4Gb 2-port PCIe"; m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"};
else else
model_str = "LPe11000 4Gb PCIe"; m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_ZEPHYR_SCSP: case PCI_DEVICE_ID_ZEPHYR_SCSP:
model_str = "LPe11000-SP 4Gb PCIe"; m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_ZEPHYR_DCSP: case PCI_DEVICE_ID_ZEPHYR_DCSP:
model_str = "LPe11002-SP 4Gb 2-port PCIe"; m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_ZMID: case PCI_DEVICE_ID_ZMID:
model_str = "LPe1150 4Gb PCIe"; m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_ZSMB: case PCI_DEVICE_ID_ZSMB:
model_str = "LPe111 4Gb PCIe"; m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"};
break; break;
case PCI_DEVICE_ID_LP101: case PCI_DEVICE_ID_LP101:
model_str = "LP101 2Gb PCI-X"; m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"};
break; break;
case PCI_DEVICE_ID_LP10000S: case PCI_DEVICE_ID_LP10000S:
model_str = "LP10000-S 2Gb PCI"; m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"};
break; break;
case PCI_DEVICE_ID_LP11000S: case PCI_DEVICE_ID_LP11000S:
case PCI_DEVICE_ID_LPE11000S: case PCI_DEVICE_ID_LPE11000S:
switch (dev_subid) { switch (dev_subid) {
case PCI_SUBSYSTEM_ID_LP11000S: case PCI_SUBSYSTEM_ID_LP11000S:
model_str = "LP11002-S 4Gb PCI-X2"; m = (typeof(m)){"LP11000-S", max_speed,
ports, "PCI-X2"};
break; break;
case PCI_SUBSYSTEM_ID_LP11002S: case PCI_SUBSYSTEM_ID_LP11002S:
model_str = "LP11000-S 4Gb 2-port PCI-X2"; m = (typeof(m)){"LP11002-S", max_speed,
ports, "PCI-X2"};
break; break;
case PCI_SUBSYSTEM_ID_LPE11000S: case PCI_SUBSYSTEM_ID_LPE11000S:
model_str = "LPe11002-S 4Gb PCIe"; m = (typeof(m)){"LPe11000-S", max_speed,
ports, "PCIe"};
break; break;
case PCI_SUBSYSTEM_ID_LPE11002S: case PCI_SUBSYSTEM_ID_LPE11002S:
model_str = "LPe11002-S 4Gb 2-port PCIe"; m = (typeof(m)){"LPe11002-S", max_speed,
ports, "PCIe"};
break; break;
case PCI_SUBSYSTEM_ID_LPE11010S: case PCI_SUBSYSTEM_ID_LPE11010S:
model_str = "LPe11010-S 4Gb 10-port PCIe"; m = (typeof(m)){"LPe11010-S", max_speed,
"10-port ", "PCIe"};
break; break;
default: default:
m = (typeof(m)){ 0 };
break; break;
} }
break; break;
default: default:
m = (typeof(m)){ 0 };
break; break;
} }
if (mdp)
sscanf(model_str, "%s", mdp); if (mdp && mdp[0] == '\0')
if (descp) snprintf(mdp, 79,"%s", m.name);
sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str); if (descp && descp[0] == '\0')
snprintf(descp, 255,
"Emulex %s %dGb %s%s Fibre Channel Adapter",
m.name, m.max_speed, m.ports, m.bus);
} }
/**************************************************/ /**************************************************/
@ -1462,9 +1529,23 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
phba->pci_bar2_map = pci_resource_start(phba->pcidev, 2); phba->pci_bar2_map = pci_resource_start(phba->pcidev, 2);
bar2map_len = pci_resource_len(phba->pcidev, 2); bar2map_len = pci_resource_len(phba->pcidev, 2);
/* Map HBA SLIM and Control Registers to a kernel virtual address. */ /* Map HBA SLIM to a kernel virtual address. */
phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len); phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len);
if (!phba->slim_memmap_p) {
error = -ENODEV;
dev_printk(KERN_ERR, &pdev->dev,
"ioremap failed for SLIM memory.\n");
goto out_idr_remove;
}
/* Map HBA Control Registers to a kernel virtual address. */
phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len); phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len);
if (!phba->ctrl_regs_memmap_p) {
error = -ENODEV;
dev_printk(KERN_ERR, &pdev->dev,
"ioremap failed for HBA control registers.\n");
goto out_iounmap_slim;
}
/* Allocate memory for SLI-2 structures */ /* Allocate memory for SLI-2 structures */
phba->slim2p = dma_alloc_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE, phba->slim2p = dma_alloc_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
@ -1539,7 +1620,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list); INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
host->transportt = lpfc_transport_template; host->transportt = lpfc_transport_template;
host->hostdata[0] = (unsigned long)phba;
pci_set_drvdata(pdev, host); pci_set_drvdata(pdev, host);
error = scsi_add_host(host, &pdev->dev); error = scsi_add_host(host, &pdev->dev);
if (error) if (error)
@ -1590,21 +1670,14 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host)); lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host));
fc_host_supported_speeds(host) = 0; fc_host_supported_speeds(host) = 0;
switch (FC_JEDEC_ID(phba->vpd.rev.biuRev)) { if (phba->lmt & LMT_10Gb)
case VIPER_JEDEC_ID:
fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT; fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT;
break; if (phba->lmt & LMT_4Gb)
case HELIOS_JEDEC_ID:
fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT; fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT;
/* Fall through */ if (phba->lmt & LMT_2Gb)
case CENTAUR_2G_JEDEC_ID:
case PEGASUS_JEDEC_ID:
case THOR_JEDEC_ID:
fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT; fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT;
/* Fall through */ if (phba->lmt & LMT_1Gb)
default: fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT;
fc_host_supported_speeds(host) = FC_PORTSPEED_1GBIT;
}
fc_host_maxframe_size(host) = fc_host_maxframe_size(host) =
((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) | ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
@ -1643,6 +1716,7 @@ out_free_slim:
phba->slim2p_mapping); phba->slim2p_mapping);
out_iounmap: out_iounmap:
iounmap(phba->ctrl_regs_memmap_p); iounmap(phba->ctrl_regs_memmap_p);
out_iounmap_slim:
iounmap(phba->slim_memmap_p); iounmap(phba->slim_memmap_p);
out_idr_remove: out_idr_remove:
idr_remove(&lpfc_hba_index, phba->brd_no); idr_remove(&lpfc_hba_index, phba->brd_no);
@ -1660,7 +1734,7 @@ static void __devexit
lpfc_pci_remove_one(struct pci_dev *pdev) lpfc_pci_remove_one(struct pci_dev *pdev)
{ {
struct Scsi_Host *host = pci_get_drvdata(pdev); struct Scsi_Host *host = pci_get_drvdata(pdev);
struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
unsigned long iflag; unsigned long iflag;
lpfc_free_sysfs_attr(phba); lpfc_free_sysfs_attr(phba);
@ -1681,6 +1755,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
* the HBA. * the HBA.
*/ */
lpfc_sli_hba_down(phba); lpfc_sli_hba_down(phba);
lpfc_sli_brdrestart(phba);
/* Release the irq reservation */ /* Release the irq reservation */
free_irq(phba->pcidev->irq, phba); free_irq(phba->pcidev->irq, phba);

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -195,6 +195,9 @@ lpfc_init_link(struct lpfc_hba * phba,
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
break; break;
case FLAGS_LOCAL_LB:
mb->un.varInitLnk.link_flags = FLAGS_LOCAL_LB;
break;
} }
/* NEW_FEATURE /* NEW_FEATURE
@ -336,6 +339,23 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/*************************************************/
/* lpfc_read_lnk_stat Issue a READ LINK STATUS */
/* mailbox command */
/*************************************************/
void
lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
MAILBOX_t *mb;
mb = &pmb->mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
mb->mbxCommand = MBX_READ_LNK_STAT;
mb->mbxOwner = OWN_HOST;
return;
}
/********************************************/ /********************************************/
/* lpfc_reg_login Issue a REG_LOGIN */ /* lpfc_reg_login Issue a REG_LOGIN */
/* mailbox command */ /* mailbox command */
@ -619,6 +639,17 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
phba->brd_no); phba->brd_no);
} }
void
lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{
MAILBOX_t *mb = &pmb->mb;
memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
mb->mbxCommand = MBX_KILL_BOARD;
mb->mbxOwner = OWN_HOST;
return;
}
void void
lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
{ {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -467,7 +467,12 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
sdev = cmd->device; sdev = cmd->device;
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
if (!result && if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_release_scsi_buf(phba, lpfc_cmd);
return;
}
if (!result && pnode != NULL &&
((jiffies - pnode->last_ramp_up_time) > ((jiffies - pnode->last_ramp_up_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) && LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((jiffies - pnode->last_q_full_time) > ((jiffies - pnode->last_q_full_time) >
@ -495,7 +500,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* Check for queue full. If the lun is reporting queue full, then * Check for queue full. If the lun is reporting queue full, then
* back off the lun queue depth to prevent target overloads. * back off the lun queue depth to prevent target overloads.
*/ */
if (result == SAM_STAT_TASK_SET_FULL) { if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) {
pnode->last_q_full_time = jiffies; pnode->last_q_full_time = jiffies;
shost_for_each_device(tmp_sdev, sdev->host) { shost_for_each_device(tmp_sdev, sdev->host) {
@ -743,7 +748,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
const char * const char *
lpfc_info(struct Scsi_Host *host) lpfc_info(struct Scsi_Host *host)
{ {
struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
int len; int len;
static char lpfcinfobuf[384]; static char lpfcinfobuf[384];
@ -803,7 +808,7 @@ static int
lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
{ {
struct lpfc_hba *phba = struct lpfc_hba *phba =
(struct lpfc_hba *) cmnd->device->host->hostdata[0]; (struct lpfc_hba *) cmnd->device->host->hostdata;
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_rport_data *rdata = cmnd->device->hostdata; struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode; struct lpfc_nodelist *ndlp = rdata->pnode;
@ -877,7 +882,7 @@ static int
lpfc_abort_handler(struct scsi_cmnd *cmnd) lpfc_abort_handler(struct scsi_cmnd *cmnd)
{ {
struct Scsi_Host *shost = cmnd->device->host; struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring]; struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
struct lpfc_iocbq *iocb; struct lpfc_iocbq *iocb;
struct lpfc_iocbq *abtsiocb; struct lpfc_iocbq *abtsiocb;
@ -981,7 +986,7 @@ static int
lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{ {
struct Scsi_Host *shost = cmnd->device->host; struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_scsi_buf *lpfc_cmd; struct lpfc_scsi_buf *lpfc_cmd;
struct lpfc_iocbq *iocbq, *iocbqrsp; struct lpfc_iocbq *iocbq, *iocbqrsp;
struct lpfc_rport_data *rdata = cmnd->device->hostdata; struct lpfc_rport_data *rdata = cmnd->device->hostdata;
@ -1094,7 +1099,7 @@ static int
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{ {
struct Scsi_Host *shost = cmnd->device->host; struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
struct lpfc_nodelist *ndlp = NULL; struct lpfc_nodelist *ndlp = NULL;
int match; int match;
int ret = FAILED, i, err_count = 0; int ret = FAILED, i, err_count = 0;
@ -1195,7 +1200,7 @@ out:
static int static int
lpfc_slave_alloc(struct scsi_device *sdev) lpfc_slave_alloc(struct scsi_device *sdev)
{ {
struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata;
struct lpfc_scsi_buf *scsi_buf = NULL; struct lpfc_scsi_buf *scsi_buf = NULL;
struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
uint32_t total = 0, i; uint32_t total = 0, i;
@ -1251,7 +1256,7 @@ lpfc_slave_alloc(struct scsi_device *sdev)
static int static int
lpfc_slave_configure(struct scsi_device *sdev) lpfc_slave_configure(struct scsi_device *sdev)
{ {
struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata[0]; struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata;
struct fc_rport *rport = starget_to_rport(sdev->sdev_target); struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
if (sdev->tagged_supported) if (sdev->tagged_supported)

Просмотреть файл

@ -23,10 +23,13 @@
struct lpfc_hba; struct lpfc_hba;
#define list_remove_head(list, entry, type, member) \ #define list_remove_head(list, entry, type, member) \
do { \
entry = NULL; \
if (!list_empty(list)) { \ if (!list_empty(list)) { \
entry = list_entry((list)->next, type, member); \ entry = list_entry((list)->next, type, member); \
list_del_init(&entry->member); \ list_del_init(&entry->member); \
} } \
} while(0)
#define list_get_first(list, type, member) \ #define list_get_first(list, type, member) \
(list_empty(list)) ? NULL : \ (list_empty(list)) ? NULL : \

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -513,7 +513,9 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_SET_MASK: case MBX_SET_MASK:
case MBX_SET_SLIM: case MBX_SET_SLIM:
case MBX_UNREG_D_ID: case MBX_UNREG_D_ID:
case MBX_KILL_BOARD:
case MBX_CONFIG_FARP: case MBX_CONFIG_FARP:
case MBX_BEACON:
case MBX_LOAD_AREA: case MBX_LOAD_AREA:
case MBX_RUN_BIU_DIAG64: case MBX_RUN_BIU_DIAG64:
case MBX_CONFIG_PORT: case MBX_CONFIG_PORT:
@ -764,7 +766,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
} }
/* unSolicited Responses */ /* unSolicited Responses */
if (pring->prt[0].profile) { if (pring->prt[0].profile) {
(pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring, saveq); if (pring->prt[0].lpfc_sli_rcv_unsol_event)
(pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring,
saveq);
match = 1; match = 1;
} else { } else {
/* We must search, based on rctl / type /* We must search, based on rctl / type
@ -775,8 +779,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
Rctl) Rctl)
&& (pring->prt[i]. && (pring->prt[i].
type == Type)) { type == Type)) {
(pring->prt[i].lpfc_sli_rcv_unsol_event) if (pring->prt[i].lpfc_sli_rcv_unsol_event)
(phba, pring, saveq); (pring->prt[i].lpfc_sli_rcv_unsol_event)
(phba, pring, saveq);
match = 1; match = 1;
break; break;
} }
@ -1149,12 +1154,17 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq); &rspiocbq);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) { if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
spin_unlock_irqrestore( if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
phba->host->host_lock, iflag); (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &rspiocbq);
&rspiocbq); } else {
spin_lock_irqsave(phba->host->host_lock, spin_unlock_irqrestore(
iflag); phba->host->host_lock, iflag);
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
spin_lock_irqsave(phba->host->host_lock,
iflag);
}
} }
break; break;
default: default:
@ -1512,98 +1522,240 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return errcnt; return errcnt;
} }
/****************************************************************************** int
* lpfc_sli_send_reset lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
*
* Note: After returning from this function, the HBA cannot be accessed for
* 1 ms. Since we do not wish to delay in interrupt context, it is the
* responsibility of the caller to perform the mdelay(1) and flush via readl().
******************************************************************************/
static int
lpfc_sli_send_reset(struct lpfc_hba * phba, uint16_t skip_post)
{ {
MAILBOX_t *swpmb; uint32_t status;
volatile uint32_t word0; int i = 0;
void __iomem *to_slim; int retval = 0;
unsigned long flags = 0;
spin_lock_irqsave(phba->host->host_lock, flags); /* Read the HBA Host Status Register */
status = readl(phba->HSregaddr);
/* A board reset must use REAL SLIM. */ /*
phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; * Check status register every 100ms for 5 retries, then every
* 500ms for 5, then every 2.5 sec for 5, then reset board and
* every 2.5 sec for 4.
* Break our of the loop if errors occurred during init.
*/
while (((status & mask) != mask) &&
!(status & HS_FFERM) &&
i++ < 20) {
word0 = 0; if (i <= 5)
swpmb = (MAILBOX_t *) & word0; msleep(10);
swpmb->mbxCommand = MBX_RESTART; else if (i <= 10)
swpmb->mbxHc = 1; msleep(500);
else
msleep(2500);
to_slim = phba->MBslimaddr; if (i == 15) {
writel(*(uint32_t *) swpmb, to_slim); phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
readl(to_slim); /* flush */ lpfc_sli_brdrestart(phba);
}
/* Only skip post after fc_ffinit is completed */ /* Read the HBA Host Status Register */
if (skip_post) { status = readl(phba->HSregaddr);
word0 = 1; /* This is really setting up word1 */
} else {
word0 = 0; /* This is really setting up word1 */
} }
to_slim = phba->MBslimaddr + sizeof (uint32_t);
writel(*(uint32_t *) swpmb, to_slim);
readl(to_slim); /* flush */
/* Turn off parity checking and serr during the physical reset */ /* Check to see if any errors occurred during init */
pci_read_config_word(phba->pcidev, PCI_COMMAND, &phba->pci_cfg_value); if ((status & HS_FFERM) || (i >= 20)) {
pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->hba_state = LPFC_HBA_ERROR;
(phba->pci_cfg_value & retval = 1;
~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); }
writel(HC_INITFF, phba->HCregaddr); return retval;
phba->hba_state = LPFC_INIT_START;
spin_unlock_irqrestore(phba->host->host_lock, flags);
return 0;
} }
static int #define BARRIER_TEST_PATTERN (0xdeadbeef)
lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
void lpfc_reset_barrier(struct lpfc_hba * phba)
{ {
uint32_t * resp_buf;
uint32_t * mbox_buf;
volatile uint32_t mbox;
uint32_t hc_copy;
int i;
uint8_t hdrtype;
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
if (hdrtype != 0x80 ||
(FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID &&
FC_JEDEC_ID(phba->vpd.rev.biuRev) != THOR_JEDEC_ID))
return;
/*
* Tell the other part of the chip to suspend temporarily all
* its DMA activity.
*/
resp_buf = (uint32_t *)phba->MBslimaddr;
/* Disable the error attention */
hc_copy = readl(phba->HCregaddr);
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
if (readl(phba->HAregaddr) & HA_ERATT) {
/* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr);
phba->stopped = 1;
}
mbox = 0;
((MAILBOX_t *)&mbox)->mbxCommand = MBX_KILL_BOARD;
((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP;
writel(BARRIER_TEST_PATTERN, (resp_buf + 1));
mbox_buf = (uint32_t *)phba->MBslimaddr;
writel(mbox, mbox_buf);
for (i = 0;
readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++)
mdelay(1);
if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
phba->stopped)
goto restore_hc;
else
goto clear_errat;
}
((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
for (i = 0; readl(resp_buf) != mbox && i < 500; i++)
mdelay(1);
clear_errat:
while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500)
mdelay(1);
if (readl(phba->HAregaddr) & HA_ERATT) {
writel(HA_ERATT, phba->HAregaddr);
phba->stopped = 1;
}
restore_hc:
writel(hc_copy, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
int
lpfc_sli_brdkill(struct lpfc_hba * phba)
{
struct lpfc_sli *psli;
LPFC_MBOXQ_t *pmb;
uint32_t status;
uint32_t ha_copy;
int retval;
int i = 0;
psli = &phba->sli;
/* Kill HBA */
lpfc_printf_log(phba,
KERN_INFO,
LOG_SLI,
"%d:0329 Kill HBA Data: x%x x%x\n",
phba->brd_no,
phba->hba_state,
psli->sli_flag);
if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL)) == 0)
return 1;
/* Disable the error attention */
spin_lock_irq(phba->host->host_lock);
status = readl(phba->HCregaddr);
status &= ~HC_ERINT_ENA;
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
lpfc_kill_board(phba, pmb);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
retval = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if (retval != MBX_SUCCESS) {
if (retval != MBX_BUSY)
mempool_free(pmb, phba->mbox_mem_pool);
return 1;
}
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
mempool_free(pmb, phba->mbox_mem_pool);
/* There is no completion for a KILL_BOARD mbox cmd. Check for an error
* attention every 100ms for 3 seconds. If we don't get ERATT after
* 3 seconds we still set HBA_ERROR state because the status of the
* board is now undefined.
*/
ha_copy = readl(phba->HAregaddr);
while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
mdelay(100);
ha_copy = readl(phba->HAregaddr);
}
del_timer_sync(&psli->mbox_tmo);
if (ha_copy & HA_ERATT) {
writel(HA_ERATT, phba->HAregaddr);
phba->stopped = 1;
}
spin_lock_irq(phba->host->host_lock);
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
psli->mbox_active = NULL;
lpfc_hba_down_post(phba);
phba->hba_state = LPFC_HBA_ERROR;
return (ha_copy & HA_ERATT ? 0 : 1);
}
int
lpfc_sli_brdreset(struct lpfc_hba * phba)
{
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
uint16_t cfg_value;
int i; int i;
struct lpfc_dmabuf *mp, *next_mp;
unsigned long flags = 0;
lpfc_sli_send_reset(phba, skip_post); psli = &phba->sli;
mdelay(1);
spin_lock_irqsave(phba->host->host_lock, flags); /* Reset HBA */
/* Risk the write on flush case ie no delay after the readl */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
readl(phba->HCregaddr); /* flush */ "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
/* Now toggle INITFF bit set by lpfc_sli_send_reset */ phba->hba_state, psli->sli_flag);
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
/* Restore PCI cmd register */
pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->pci_cfg_value);
/* perform board reset */ /* perform board reset */
phba->fc_eventTag = 0; phba->fc_eventTag = 0;
phba->fc_myDID = 0; phba->fc_myDID = 0;
phba->fc_prevDID = Mask_DID; phba->fc_prevDID = 0;
/* Reset HBA */ psli->sli_flag = 0;
lpfc_printf_log(phba,
KERN_INFO, /* Turn off parity checking and serr during the physical reset */
LOG_SLI, pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
"%d:0325 Reset HBA Data: x%x x%x x%x\n", pci_write_config_word(phba->pcidev, PCI_COMMAND,
phba->brd_no, (cfg_value &
phba->hba_state, ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
phba->sli.sli_flag,
skip_post); psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
/* Now toggle INITFF bit in the Host Control Register */
writel(HC_INITFF, phba->HCregaddr);
mdelay(1);
readl(phba->HCregaddr); /* flush */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
/* Restore PCI cmd register */
pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
/* Initialize relevant SLI info */ /* Initialize relevant SLI info */
for (i = 0; i < phba->sli.num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
pring = &phba->sli.ring[i]; pring = &psli->ring[i];
pring->flag = 0; pring->flag = 0;
pring->rspidx = 0; pring->rspidx = 0;
pring->next_cmdidx = 0; pring->next_cmdidx = 0;
@ -1611,27 +1763,64 @@ lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
pring->cmdidx = 0; pring->cmdidx = 0;
pring->missbufcnt = 0; pring->missbufcnt = 0;
} }
spin_unlock_irqrestore(phba->host->host_lock, flags);
if (skip_post) { phba->hba_state = LPFC_WARM_START;
mdelay(100); return 0;
}
int
lpfc_sli_brdrestart(struct lpfc_hba * phba)
{
MAILBOX_t *mb;
struct lpfc_sli *psli;
uint16_t skip_post;
volatile uint32_t word0;
void __iomem *to_slim;
spin_lock_irq(phba->host->host_lock);
psli = &phba->sli;
/* Restart HBA */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no,
phba->hba_state, psli->sli_flag);
word0 = 0;
mb = (MAILBOX_t *) &word0;
mb->mbxCommand = MBX_RESTART;
mb->mbxHc = 1;
lpfc_reset_barrier(phba);
to_slim = phba->MBslimaddr;
writel(*(uint32_t *) mb, to_slim);
readl(to_slim); /* flush */
/* Only skip post after fc_ffinit is completed */
if (phba->hba_state) {
skip_post = 1;
word0 = 1; /* This is really setting up word1 */
} else { } else {
skip_post = 0;
word0 = 0; /* This is really setting up word1 */
}
to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t);
writel(*(uint32_t *) mb, to_slim);
readl(to_slim); /* flush */
lpfc_sli_brdreset(phba);
phba->stopped = 0;
phba->hba_state = LPFC_INIT_START;
spin_unlock_irq(phba->host->host_lock);
if (skip_post)
mdelay(100);
else
mdelay(2000); mdelay(2000);
}
spin_lock_irqsave(phba->host->host_lock, flags); lpfc_hba_down_post(phba);
/* Cleanup preposted buffers on the ELS ring */
pring = &phba->sli.ring[LPFC_ELS_RING];
list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
list_del(&mp->list);
pring->postbufq_cnt--;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
for (i = 0; i < phba->sli.num_rings; i++)
lpfc_sli_abort_iocb_ring(phba, &phba->sli.ring[i]);
return 0; return 0;
} }
@ -1691,7 +1880,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
} }
if (i == 15) { if (i == 15) {
lpfc_sli_brdreset(phba, 0); phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
lpfc_sli_brdrestart(phba);
} }
/* Read the HBA Host Status Register */ /* Read the HBA Host Status Register */
status = readl(phba->HSregaddr); status = readl(phba->HSregaddr);
@ -1735,8 +1925,8 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
} }
while (resetcount < 2 && !done) { while (resetcount < 2 && !done) {
phba->hba_state = 0; phba->hba_state = LPFC_STATE_UNKNOWN;
lpfc_sli_brdreset(phba, 0); lpfc_sli_brdrestart(phba);
msleep(2500); msleep(2500);
rc = lpfc_sli_chipset_init(phba); rc = lpfc_sli_chipset_init(phba);
if (rc) if (rc)
@ -1920,6 +2110,21 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
mb = &pmbox->mb; mb = &pmbox->mb;
status = MBX_SUCCESS; status = MBX_SUCCESS;
if (phba->hba_state == LPFC_HBA_ERROR) {
spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
return (MBX_NOT_FINISHED);
}
if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
!(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
return (MBX_NOT_FINISHED);
}
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
/* Polling for a mbox command when another one is already active /* Polling for a mbox command when another one is already active
* is not allowed in SLI. Also, the driver must have established * is not allowed in SLI. Also, the driver must have established
@ -2002,7 +2207,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
/* If we are not polling, we MUST be in SLI2 mode */ /* If we are not polling, we MUST be in SLI2 mode */
if (flag != MBX_POLL) { if (flag != MBX_POLL) {
if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) { if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
(mb->mbxCommand != MBX_KILL_BOARD)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock, spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag); drvr_flag);
@ -2086,8 +2292,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
ha_copy = readl(phba->HAregaddr); ha_copy = readl(phba->HAregaddr);
/* Wait for command to complete */ /* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP) while (((word0 & OWN_CHIP) == OWN_CHIP) ||
|| !(ha_copy & HA_MBATT)) { (!(ha_copy & HA_MBATT) &&
(phba->hba_state > LPFC_WARM_START))) {
if (i++ >= 100) { if (i++ >= 100) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock, spin_unlock_irqrestore(phba->host->host_lock,
@ -2237,16 +2444,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
!(phba->sli.sli_flag & LPFC_PROCESS_LA))) !(phba->sli.sli_flag & LPFC_PROCESS_LA)))
goto iocb_busy; goto iocb_busy;
/*
* Check to see if this is a high priority command.
* If so bypass tx queue processing.
*/
if (unlikely((flag & SLI_IOCB_HIGH_PRIORITY) &&
(iocb = lpfc_sli_next_iocb_slot(phba, pring)))) {
lpfc_sli_submit_iocb(phba, pring, iocb, piocb);
piocb = NULL;
}
while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) && while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) &&
(nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb))) (nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
lpfc_sli_submit_iocb(phba, pring, iocb, nextiocb); lpfc_sli_submit_iocb(phba, pring, iocb, nextiocb);
@ -2274,6 +2471,37 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return IOCB_BUSY; return IOCB_BUSY;
} }
static int
lpfc_extra_ring_setup( struct lpfc_hba *phba)
{
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
psli = &phba->sli;
/* Adjust cmd/rsp ring iocb entries more evenly */
pring = &psli->ring[psli->fcp_ring];
pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES;
pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES;
pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES;
pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES;
pring = &psli->ring[1];
pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES;
pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
/* Setup default profile for this ring */
pring->iotag_max = 4096;
pring->num_mask = 1;
pring->prt[0].profile = 0; /* Mask 0 */
pring->prt[0].rctl = FC_UNSOL_DATA;
pring->prt[0].type = 5;
pring->prt[0].lpfc_sli_rcv_unsol_event = NULL;
return 0;
}
int int
lpfc_sli_setup(struct lpfc_hba *phba) lpfc_sli_setup(struct lpfc_hba *phba)
{ {
@ -2357,6 +2585,8 @@ lpfc_sli_setup(struct lpfc_hba *phba)
"SLI2 SLIM Data: x%x x%x\n", "SLI2 SLIM Data: x%x x%x\n",
phba->brd_no, totiocb, MAX_SLI2_IOCB); phba->brd_no, totiocb, MAX_SLI2_IOCB);
} }
if (phba->cfg_multi_ring_support == 2)
lpfc_extra_ring_setup(phba);
return 0; return 0;
} }
@ -2465,15 +2695,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
spin_unlock_irqrestore(phba->host->host_lock, flags); spin_unlock_irqrestore(phba->host->host_lock, flags);
/*
* Provided the hba is not in an error state, reset it. It is not
* capable of IO anymore.
*/
if (phba->hba_state != LPFC_HBA_ERROR) {
phba->hba_state = LPFC_INIT_START;
lpfc_sli_brdreset(phba, 1);
}
return 1; return 1;
} }
@ -2877,11 +3098,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
pmboxq->context1 = NULL; pmboxq->context1 = NULL;
/* if schedule_timeout returns 0, we timed out and were not /* if schedule_timeout returns 0, we timed out and were not
woken up */ woken up */
if (timeleft == 0) { if ((timeleft == 0) || signal_pending(current))
retval = MBX_TIMEOUT; retval = MBX_TIMEOUT;
} else { else
retval = MBX_SUCCESS; retval = MBX_SUCCESS;
}
} }
@ -2987,13 +3207,7 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
/* Clear Chip error bit */ /* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr); writel(HA_ERATT, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */ readl(phba->HAregaddr); /* flush */
phba->stopped = 1;
/*
* Reseting the HBA is the only reliable way
* to shutdown interrupt when there is a
* ERROR.
*/
lpfc_sli_send_reset(phba, phba->hba_state);
} }
spin_lock(phba->host->host_lock); spin_lock(phba->host->host_lock);

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
@ -61,7 +61,6 @@ struct lpfc_iocbq {
}; };
#define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */ #define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
#define SLI_IOCB_HIGH_PRIORITY 2 /* High priority command */
#define IOCB_SUCCESS 0 #define IOCB_SUCCESS 0
#define IOCB_BUSY 1 #define IOCB_BUSY 1
@ -200,8 +199,6 @@ struct lpfc_sli {
struct timer_list mbox_tmo; /* Hold clk to timeout active mbox struct timer_list mbox_tmo; /* Hold clk to timeout active mbox
cmd */ cmd */
uint32_t *MBhostaddr; /* virtual address for mbox cmds */
#define LPFC_IOCBQ_LOOKUP_INCREMENT 1024 #define LPFC_IOCBQ_LOOKUP_INCREMENT 1024
struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */ struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */
size_t iocbq_lookup_len; /* current lengs of the array */ size_t iocbq_lookup_len; /* current lengs of the array */

Просмотреть файл

@ -1,7 +1,7 @@
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. * * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
@ -18,12 +18,12 @@
* included with this package. * * included with this package. *
*******************************************************************/ *******************************************************************/
#define LPFC_DRIVER_VERSION "8.1.1" #define LPFC_DRIVER_VERSION "8.1.4"
#define LPFC_DRIVER_NAME "lpfc" #define LPFC_DRIVER_NAME "lpfc"
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION LPFC_DRIVER_VERSION
#define LPFC_COPYRIGHT "Copyright(c) 2004-2005 Emulex. All rights reserved." #define LPFC_COPYRIGHT "Copyright(c) 2004-2006 Emulex. All rights reserved."
#define DFC_API_VERSION "0.0.0" #define DFC_API_VERSION "0.0.0"

Просмотреть файл

@ -772,8 +772,6 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
goto out_return_cmd; goto out_return_cmd;
cmd->scmd = scmd; cmd->scmd = scmd;
scmd->SCp.ptr = (char *)cmd;
scmd->SCp.sent_command = jiffies;
/* /*
* Issue the command to the FW * Issue the command to the FW
@ -804,6 +802,12 @@ static int megasas_slave_configure(struct scsi_device *sdev)
*/ */
if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK) if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
return -ENXIO; return -ENXIO;
/*
* The RAID firmware may require extended timeouts.
*/
if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
sdev->timeout = 90 * HZ;
return 0; return 0;
} }
@ -875,23 +879,6 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
return ret_val; return ret_val;
} }
static enum scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
{
unsigned long seconds;
if (scmd->SCp.ptr) {
seconds = (jiffies - scmd->SCp.sent_command) / HZ;
if (seconds < 90) {
return EH_RESET_TIMER;
} else {
return EH_NOT_HANDLED;
}
}
return EH_HANDLED;
}
/** /**
* megasas_reset_device - Device reset handler entry point * megasas_reset_device - Device reset handler entry point
*/ */
@ -962,7 +949,6 @@ static struct scsi_host_template megasas_template = {
.eh_device_reset_handler = megasas_reset_device, .eh_device_reset_handler = megasas_reset_device,
.eh_bus_reset_handler = megasas_reset_bus_host, .eh_bus_reset_handler = megasas_reset_bus_host,
.eh_host_reset_handler = megasas_reset_bus_host, .eh_host_reset_handler = megasas_reset_bus_host,
.eh_timed_out = megasas_reset_timer,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
}; };

Просмотреть файл

@ -69,6 +69,10 @@
** Low PCI traffic for command handling when on-chip RAM is present. ** Low PCI traffic for command handling when on-chip RAM is present.
** Aggressive SCSI SCRIPTS optimizations. ** Aggressive SCSI SCRIPTS optimizations.
** **
** 2005 by Matthew Wilcox and James Bottomley
** PCI-ectomy. This driver now supports only the 720 chip (see the
** NCR_Q720 and zalon drivers for the bus probe logic).
**
******************************************************************************* *******************************************************************************
*/ */
@ -90,13 +94,6 @@
#define SCSI_NCR_DEBUG_FLAGS (0) #define SCSI_NCR_DEBUG_FLAGS (0)
/*==========================================================
**
** Include files
**
**==========================================================
*/
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
@ -121,6 +118,7 @@
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
@ -128,10 +126,8 @@
#include "ncr53c8xx.h" #include "ncr53c8xx.h"
#define NAME53C "ncr53c"
#define NAME53C8XX "ncr53c8xx" #define NAME53C8XX "ncr53c8xx"
/*========================================================== /*==========================================================
** **
** Debugging tags ** Debugging tags
@ -2111,7 +2107,7 @@ static struct script script0 __initdata = {
*/ */
/* /*
** The M_REJECT problem seems to be due to a selection ** The MESSAGE_REJECT problem seems to be due to a selection
** timing problem. ** timing problem.
** Wait immediately for the selection to complete. ** Wait immediately for the selection to complete.
** (2.5x behaves so) ** (2.5x behaves so)
@ -2162,7 +2158,7 @@ static struct script script0 __initdata = {
/* /*
** Selection complete. ** Selection complete.
** Send the IDENTIFY and SIMPLE_TAG messages ** Send the IDENTIFY and SIMPLE_TAG messages
** (and the M_X_SYNC_REQ message) ** (and the EXTENDED_SDTR message)
*/ */
SCR_MOVE_TBL ^ SCR_MSG_OUT, SCR_MOVE_TBL ^ SCR_MSG_OUT,
offsetof (struct dsb, smsg), offsetof (struct dsb, smsg),
@ -2191,7 +2187,7 @@ static struct script script0 __initdata = {
/* /*
** Initialize the msgout buffer with a NOOP message. ** Initialize the msgout buffer with a NOOP message.
*/ */
SCR_LOAD_REG (scratcha, M_NOOP), SCR_LOAD_REG (scratcha, NOP),
0, 0,
SCR_COPY (1), SCR_COPY (1),
RADDR (scratcha), RADDR (scratcha),
@ -2343,21 +2339,21 @@ static struct script script0 __initdata = {
/* /*
** Handle this message. ** Handle this message.
*/ */
SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), SCR_JUMP ^ IFTRUE (DATA (COMMAND_COMPLETE)),
PADDR (complete), PADDR (complete),
SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), SCR_JUMP ^ IFTRUE (DATA (DISCONNECT)),
PADDR (disconnect), PADDR (disconnect),
SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), SCR_JUMP ^ IFTRUE (DATA (SAVE_POINTERS)),
PADDR (save_dp), PADDR (save_dp),
SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), SCR_JUMP ^ IFTRUE (DATA (RESTORE_POINTERS)),
PADDR (restore_dp), PADDR (restore_dp),
SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), SCR_JUMP ^ IFTRUE (DATA (EXTENDED_MESSAGE)),
PADDRH (msg_extended), PADDRH (msg_extended),
SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), SCR_JUMP ^ IFTRUE (DATA (NOP)),
PADDR (clrack), PADDR (clrack),
SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), SCR_JUMP ^ IFTRUE (DATA (MESSAGE_REJECT)),
PADDRH (msg_reject), PADDRH (msg_reject),
SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)), SCR_JUMP ^ IFTRUE (DATA (IGNORE_WIDE_RESIDUE)),
PADDRH (msg_ign_residue), PADDRH (msg_ign_residue),
/* /*
** Rest of the messages left as ** Rest of the messages left as
@ -2372,7 +2368,7 @@ static struct script script0 __initdata = {
*/ */
SCR_INT, SCR_INT,
SIR_REJECT_SENT, SIR_REJECT_SENT,
SCR_LOAD_REG (scratcha, M_REJECT), SCR_LOAD_REG (scratcha, MESSAGE_REJECT),
0, 0,
}/*-------------------------< SETMSG >----------------------*/,{ }/*-------------------------< SETMSG >----------------------*/,{
SCR_COPY (1), SCR_COPY (1),
@ -2564,7 +2560,7 @@ static struct script script0 __initdata = {
/* /*
** If it was no ABORT message ... ** If it was no ABORT message ...
*/ */
SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), SCR_JUMP ^ IFTRUE (DATA (ABORT_TASK_SET)),
PADDRH (msg_out_abort), PADDRH (msg_out_abort),
/* /*
** ... wait for the next phase ** ... wait for the next phase
@ -2576,7 +2572,7 @@ static struct script script0 __initdata = {
/* /*
** ... else clear the message ... ** ... else clear the message ...
*/ */
SCR_LOAD_REG (scratcha, M_NOOP), SCR_LOAD_REG (scratcha, NOP),
0, 0,
SCR_COPY (4), SCR_COPY (4),
RADDR (scratcha), RADDR (scratcha),
@ -3035,7 +3031,7 @@ static struct scripth scripth0 __initdata = {
*/ */
SCR_MOVE_ABS (1) ^ SCR_MSG_IN, SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[2]), NADDR (msgin[2]),
SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)), SCR_JUMP ^ IFTRUE (DATA (EXTENDED_WDTR)),
PADDRH (msg_wdtr), PADDRH (msg_wdtr),
/* /*
** unknown extended message ** unknown extended message
@ -3069,7 +3065,7 @@ static struct scripth scripth0 __initdata = {
}/*-------------------------< SEND_WDTR >----------------*/,{ }/*-------------------------< SEND_WDTR >----------------*/,{
/* /*
** Send the M_X_WIDE_REQ ** Send the EXTENDED_WDTR
*/ */
SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
NADDR (msgout), NADDR (msgout),
@ -3089,7 +3085,7 @@ static struct scripth scripth0 __initdata = {
*/ */
SCR_MOVE_ABS (1) ^ SCR_MSG_IN, SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[2]), NADDR (msgin[2]),
SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), SCR_JUMP ^ IFTRUE (DATA (EXTENDED_SDTR)),
PADDRH (msg_sdtr), PADDRH (msg_sdtr),
/* /*
** unknown extended message ** unknown extended message
@ -3124,7 +3120,7 @@ static struct scripth scripth0 __initdata = {
}/*-------------------------< SEND_SDTR >-------------*/,{ }/*-------------------------< SEND_SDTR >-------------*/,{
/* /*
** Send the M_X_SYNC_REQ ** Send the EXTENDED_SDTR
*/ */
SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
NADDR (msgout), NADDR (msgout),
@ -3202,10 +3198,10 @@ static struct scripth scripth0 __initdata = {
}/*-------------------------< RESET >----------------------*/,{ }/*-------------------------< RESET >----------------------*/,{
/* /*
** Send a M_RESET message if bad IDENTIFY ** Send a TARGET_RESET message if bad IDENTIFY
** received on reselection. ** received on reselection.
*/ */
SCR_LOAD_REG (scratcha, M_ABORT_TAG), SCR_LOAD_REG (scratcha, ABORT_TASK),
0, 0,
SCR_JUMP, SCR_JUMP,
PADDRH (abort_resel), PADDRH (abort_resel),
@ -3213,7 +3209,7 @@ static struct scripth scripth0 __initdata = {
/* /*
** Abort a wrong tag received on reselection. ** Abort a wrong tag received on reselection.
*/ */
SCR_LOAD_REG (scratcha, M_ABORT_TAG), SCR_LOAD_REG (scratcha, ABORT_TASK),
0, 0,
SCR_JUMP, SCR_JUMP,
PADDRH (abort_resel), PADDRH (abort_resel),
@ -3221,7 +3217,7 @@ static struct scripth scripth0 __initdata = {
/* /*
** Abort a reselection when no active CCB. ** Abort a reselection when no active CCB.
*/ */
SCR_LOAD_REG (scratcha, M_ABORT), SCR_LOAD_REG (scratcha, ABORT_TASK_SET),
0, 0,
}/*-------------------------< ABORT_RESEL >----------------*/,{ }/*-------------------------< ABORT_RESEL >----------------*/,{
SCR_COPY (1), SCR_COPY (1),
@ -3333,7 +3329,7 @@ static struct scripth scripth0 __initdata = {
** Read the message, since we got it directly ** Read the message, since we got it directly
** from the SCSI BUS data lines. ** from the SCSI BUS data lines.
** Signal problem to C code for logging the event. ** Signal problem to C code for logging the event.
** Send a M_ABORT to clear all pending tasks. ** Send an ABORT_TASK_SET to clear all pending tasks.
*/ */
SCR_INT, SCR_INT,
SIR_RESEL_BAD_LUN, SIR_RESEL_BAD_LUN,
@ -3345,7 +3341,7 @@ static struct scripth scripth0 __initdata = {
/* /*
** We donnot have a task for that I_T_L. ** We donnot have a task for that I_T_L.
** Signal problem to C code for logging the event. ** Signal problem to C code for logging the event.
** Send a M_ABORT message. ** Send an ABORT_TASK_SET message.
*/ */
SCR_INT, SCR_INT,
SIR_RESEL_BAD_I_T_L, SIR_RESEL_BAD_I_T_L,
@ -3355,7 +3351,7 @@ static struct scripth scripth0 __initdata = {
/* /*
** We donnot have a task that matches the tag. ** We donnot have a task that matches the tag.
** Signal problem to C code for logging the event. ** Signal problem to C code for logging the event.
** Send a M_ABORTTAG message. ** Send an ABORT_TASK message.
*/ */
SCR_INT, SCR_INT,
SIR_RESEL_BAD_I_T_L_Q, SIR_RESEL_BAD_I_T_L_Q,
@ -3366,7 +3362,7 @@ static struct scripth scripth0 __initdata = {
** We donnot know the target that reselected us. ** We donnot know the target that reselected us.
** Grab the first message if any (IDENTIFY). ** Grab the first message if any (IDENTIFY).
** Signal problem to C code for logging the event. ** Signal problem to C code for logging the event.
** M_RESET message. ** TARGET_RESET message.
*/ */
SCR_INT, SCR_INT,
SIR_RESEL_BAD_TARGET, SIR_RESEL_BAD_TARGET,
@ -4109,17 +4105,11 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
switch (nego) { switch (nego) {
case NS_SYNC: case NS_SYNC:
msgptr[msglen++] = M_EXTENDED; msglen += spi_populate_sync_msg(msgptr + msglen,
msgptr[msglen++] = 3; tp->maxoffs ? tp->minsync : 0, tp->maxoffs);
msgptr[msglen++] = M_X_SYNC_REQ;
msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0;
msgptr[msglen++] = tp->maxoffs;
break; break;
case NS_WIDE: case NS_WIDE:
msgptr[msglen++] = M_EXTENDED; msglen += spi_populate_width_msg(msgptr + msglen, tp->usrwide);
msgptr[msglen++] = 2;
msgptr[msglen++] = M_X_WIDE_REQ;
msgptr[msglen++] = tp->usrwide;
break; break;
} }
@ -4220,7 +4210,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**---------------------------------------------------- **----------------------------------------------------
*/ */
idmsg = M_IDENTIFY | sdev->lun; idmsg = IDENTIFY(0, sdev->lun);
if (cp ->tag != NO_TAG || if (cp ->tag != NO_TAG ||
(cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC))) (cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC)))
@ -4239,7 +4229,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
*/ */
if (lp && time_after(jiffies, lp->tags_stime)) { if (lp && time_after(jiffies, lp->tags_stime)) {
if (lp->tags_smap) { if (lp->tags_smap) {
order = M_ORDERED_TAG; order = ORDERED_QUEUE_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){ if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
PRINT_ADDR(cmd, PRINT_ADDR(cmd,
"ordered tag forced.\n"); "ordered tag forced.\n");
@ -4257,10 +4247,10 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
case 0x08: /* READ_SMALL (6) */ case 0x08: /* READ_SMALL (6) */
case 0x28: /* READ_BIG (10) */ case 0x28: /* READ_BIG (10) */
case 0xa8: /* READ_HUGE (12) */ case 0xa8: /* READ_HUGE (12) */
order = M_SIMPLE_TAG; order = SIMPLE_QUEUE_TAG;
break; break;
default: default:
order = M_ORDERED_TAG; order = ORDERED_QUEUE_TAG;
} }
} }
msgptr[msglen++] = order; msgptr[msglen++] = order;
@ -6229,9 +6219,9 @@ static int ncr_int_par (struct ncb *np)
if (!(dbc & 0xc0000000)) if (!(dbc & 0xc0000000))
phase = (dbc >> 24) & 7; phase = (dbc >> 24) & 7;
if (phase == 7) if (phase == 7)
msg = M_PARITY; msg = MSG_PARITY_ERROR;
else else
msg = M_ID_ERROR; msg = INITIATOR_ERROR;
/* /*
@ -6795,6 +6785,8 @@ void ncr_int_sir (struct ncb *np)
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
** **
** Was Sie schon immer ueber transfermode negotiation wissen wollten ... ** Was Sie schon immer ueber transfermode negotiation wissen wollten ...
** ("Everything you've always wanted to know about transfer mode
** negotiation")
** **
** We try to negotiate sync and wide transfer only after ** We try to negotiate sync and wide transfer only after
** a successful inquire command. We look at byte 7 of the ** a successful inquire command. We look at byte 7 of the
@ -6896,8 +6888,8 @@ void ncr_int_sir (struct ncb *np)
break; break;
} }
np->msgin [0] = M_NOOP; np->msgin [0] = NOP;
np->msgout[0] = M_NOOP; np->msgout[0] = NOP;
cp->nego_status = 0; cp->nego_status = 0;
break; break;
@ -6991,12 +6983,7 @@ void ncr_int_sir (struct ncb *np)
spi_offset(starget) = ofs; spi_offset(starget) = ofs;
ncr_setsync(np, cp, scntl3, (fak<<5)|ofs); ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
np->msgout[0] = M_EXTENDED; spi_populate_sync_msg(np->msgout, per, ofs);
np->msgout[1] = 3;
np->msgout[2] = M_X_SYNC_REQ;
np->msgout[3] = per;
np->msgout[4] = ofs;
cp->nego_status = NS_SYNC; cp->nego_status = NS_SYNC;
if (DEBUG_FLAGS & DEBUG_NEGO) { if (DEBUG_FLAGS & DEBUG_NEGO) {
@ -7007,7 +6994,7 @@ void ncr_int_sir (struct ncb *np)
OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
return; return;
} }
np->msgin [0] = M_NOOP; np->msgin [0] = NOP;
break; break;
@ -7082,13 +7069,9 @@ void ncr_int_sir (struct ncb *np)
spi_width(starget) = wide; spi_width(starget) = wide;
ncr_setwide(np, cp, wide, 1); ncr_setwide(np, cp, wide, 1);
spi_populate_width_msg(np->msgout, wide);
np->msgout[0] = M_EXTENDED; np->msgin [0] = NOP;
np->msgout[1] = 2;
np->msgout[2] = M_X_WIDE_REQ;
np->msgout[3] = wide;
np->msgin [0] = M_NOOP;
cp->nego_status = NS_WIDE; cp->nego_status = NS_WIDE;
@ -7107,12 +7090,12 @@ void ncr_int_sir (struct ncb *np)
case SIR_REJECT_RECEIVED: case SIR_REJECT_RECEIVED:
/*----------------------------------------------- /*-----------------------------------------------
** **
** We received a M_REJECT message. ** We received a MESSAGE_REJECT.
** **
**----------------------------------------------- **-----------------------------------------------
*/ */
PRINT_ADDR(cp->cmd, "M_REJECT received (%x:%x).\n", PRINT_ADDR(cp->cmd, "MESSAGE_REJECT received (%x:%x).\n",
(unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]); (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
break; break;
@ -7124,7 +7107,7 @@ void ncr_int_sir (struct ncb *np)
**----------------------------------------------- **-----------------------------------------------
*/ */
ncr_print_msg(cp, "M_REJECT sent for", np->msgin); ncr_print_msg(cp, "MESSAGE_REJECT sent for", np->msgin);
break; break;
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
@ -7143,7 +7126,7 @@ void ncr_int_sir (struct ncb *np)
**----------------------------------------------- **-----------------------------------------------
*/ */
PRINT_ADDR(cp->cmd, "M_IGN_RESIDUE received, but not yet " PRINT_ADDR(cp->cmd, "IGNORE_WIDE_RESIDUE received, but not yet "
"implemented.\n"); "implemented.\n");
break; break;
#if 0 #if 0
@ -7156,7 +7139,7 @@ void ncr_int_sir (struct ncb *np)
**----------------------------------------------- **-----------------------------------------------
*/ */
PRINT_ADDR(cp->cmd, "M_DISCONNECT received, but datapointer " PRINT_ADDR(cp->cmd, "DISCONNECT received, but datapointer "
"not saved: data=%x save=%x goal=%x.\n", "not saved: data=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp), (unsigned) INL (nc_temp),
(unsigned) scr_to_cpu(np->header.savep), (unsigned) scr_to_cpu(np->header.savep),
@ -7862,7 +7845,7 @@ static int __init ncr_snooptest (struct ncb* np)
**========================================================== **==========================================================
** **
** Note: we have to return the correct value. ** Note: we have to return the correct value.
** THERE IS NO SAVE DEFAULT VALUE. ** THERE IS NO SAFE DEFAULT VALUE.
** **
** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. ** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock.
** 53C860 and 53C875 rev. 1 support fast20 transfers but ** 53C860 and 53C875 rev. 1 support fast20 transfers but
@ -8562,7 +8545,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
/* use SIMPLE TAG messages by default */ /* use SIMPLE TAG messages by default */
#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG #ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG
np->order = M_SIMPLE_TAG; np->order = SIMPLE_QUEUE_TAG;
#endif #endif
spin_unlock_irqrestore(&np->smp_lock, flags); spin_unlock_irqrestore(&np->smp_lock, flags);

Просмотреть файл

@ -56,8 +56,10 @@
#include <linux/config.h> #include <linux/config.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <linux/config.h>
/* /*
** If you want a driver as small as possible, do not define the ** If you want a driver as small as possible, donnot define the
** following options. ** following options.
*/ */
#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT #define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
@ -1254,39 +1256,6 @@ struct scr_tblsel {
**----------------------------------------------------------- **-----------------------------------------------------------
*/ */
/*
** Messages
*/
#define M_COMPLETE COMMAND_COMPLETE
#define M_EXTENDED EXTENDED_MESSAGE
#define M_SAVE_DP SAVE_POINTERS
#define M_RESTORE_DP RESTORE_POINTERS
#define M_DISCONNECT DISCONNECT
#define M_ID_ERROR INITIATOR_ERROR
#define M_ABORT ABORT_TASK_SET
#define M_REJECT MESSAGE_REJECT
#define M_NOOP NOP
#define M_PARITY MSG_PARITY_ERROR
#define M_LCOMPLETE LINKED_CMD_COMPLETE
#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
#define M_RESET TARGET_RESET
#define M_ABORT_TAG ABORT_TASK
#define M_CLEAR_QUEUE CLEAR_TASK_SET
#define M_INIT_REC INITIATE_RECOVERY
#define M_REL_REC RELEASE_RECOVERY
#define M_TERMINATE (0x11)
#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
#define M_ORDERED_TAG ORDERED_QUEUE_TAG
#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
#define M_IDENTIFY (0x80)
#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
#define M_X_SYNC_REQ EXTENDED_SDTR
#define M_X_WIDE_REQ EXTENDED_WDTR
#define M_X_PPR_REQ EXTENDED_PPR
/* /*
** Status ** Status
*/ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -518,7 +518,8 @@ struct osst_buffer {
int writing; int writing;
int midlevel_result; int midlevel_result;
int syscall_result; int syscall_result;
struct scsi_request *last_SRpnt; struct osst_request *last_SRpnt;
struct st_cmdstatus cmdstat;
unsigned char *b_data; unsigned char *b_data;
os_aux_t *aux; /* onstream AUX structure at end of each block */ os_aux_t *aux; /* onstream AUX structure at end of each block */
unsigned short use_sg; /* zero or number of s/g segments for this adapter */ unsigned short use_sg; /* zero or number of s/g segments for this adapter */
@ -626,6 +627,15 @@ struct osst_tape {
struct gendisk *drive; struct gendisk *drive;
} ; } ;
/* scsi tape command */
struct osst_request {
unsigned char cmd[MAX_COMMAND_SIZE];
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
int result;
struct osst_tape *stp;
struct completion *waiting;
};
/* Values of write_type */ /* Values of write_type */
#define OS_WRITE_DATA 0 #define OS_WRITE_DATA 0
#define OS_WRITE_EOD 1 #define OS_WRITE_EOD 1

Просмотреть файл

@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -10,14 +10,13 @@ config SCSI_QLA_FC
By default, firmware for the ISP parts will be loaded By default, firmware for the ISP parts will be loaded
via the Firmware Loader interface. via the Firmware Loader interface.
ISP Firmware Filename ISP Firmware Filename
---------- ----------------- ---------- -----------------
21xx ql2100_fw.bin 21xx ql2100_fw.bin
22xx ql2200_fw.bin 22xx ql2200_fw.bin
2300, 2312 ql2300_fw.bin 2300, 2312, 6312 ql2300_fw.bin
2322 ql2322_fw.bin 2322, 6322 ql2322_fw.bin
6312, 6322 ql6312_fw.bin 24xx ql2400_fw.bin
24xx ql2400_fw.bin
Upon request, the driver caches the firmware image until Upon request, the driver caches the firmware image until
the driver is unloaded. the driver is unloaded.
@ -51,23 +50,17 @@ config SCSI_QLA22XX
This driver supports the QLogic 22xx (ISP2200) host adapter family. This driver supports the QLogic 22xx (ISP2200) host adapter family.
config SCSI_QLA2300 config SCSI_QLA2300
tristate " Build QLogic ISP2300 firmware-module" tristate " Build QLogic ISP2300/ISP6312 firmware-module"
depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help--- ---help---
This driver supports the QLogic 2300 (ISP2300 and ISP2312) host This driver supports the QLogic 2300 (ISP2300, ISP2312 and
adapter family. ISP6312) host adapter family.
config SCSI_QLA2322 config SCSI_QLA2322
tristate " Build QLogic ISP2322 firmware-module" tristate " Build QLogic ISP2322/ISP6322 firmware-module"
depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help--- ---help---
This driver supports the QLogic 2322 (ISP2322) host adapter family. This driver supports the QLogic 2322 (ISP2322 and ISP6322) host
config SCSI_QLA6312
tristate " Build QLogic ISP63xx firmware-module"
depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
adapter family. adapter family.
config SCSI_QLA24XX config SCSI_QLA24XX

Просмотреть файл

@ -9,12 +9,10 @@ qla2100-y := ql2100.o ql2100_fw.o
qla2200-y := ql2200.o ql2200_fw.o qla2200-y := ql2200.o ql2200_fw.o
qla2300-y := ql2300.o ql2300_fw.o qla2300-y := ql2300.o ql2300_fw.o
qla2322-y := ql2322.o ql2322_fw.o qla2322-y := ql2322.o ql2322_fw.o
qla6312-y := ql6312.o ql6312_fw.o
qla2400-y := ql2400.o ql2400_fw.o qla2400-y := ql2400.o ql2400_fw.o
obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o
obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o
obj-$(CONFIG_SCSI_QLA6312) += qla2xxx.o qla6312.o
obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o

Просмотреть файл

@ -40,6 +40,11 @@ static struct qla_board_info qla_board_tbl[] = {
.isp_name = "ISP2312", .isp_name = "ISP2312",
.fw_info = qla_fw_tbl, .fw_info = qla_fw_tbl,
}, },
{
.drv_name = qla_driver_name,
.isp_name = "ISP6312",
.fw_info = qla_fw_tbl,
},
}; };
static struct pci_device_id qla2300_pci_tbl[] = { static struct pci_device_id qla2300_pci_tbl[] = {
@ -57,6 +62,13 @@ static struct pci_device_id qla2300_pci_tbl[] = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[1], .driver_data = (unsigned long)&qla_board_tbl[1],
}, },
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP6312,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[2],
},
{0, 0}, {0, 0},
}; };
MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl); MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -52,6 +52,11 @@ static struct qla_board_info qla_board_tbl[] = {
.isp_name = "ISP2322", .isp_name = "ISP2322",
.fw_info = qla_fw_tbl, .fw_info = qla_fw_tbl,
}, },
{
.drv_name = qla_driver_name,
.isp_name = "ISP6322",
.fw_info = qla_fw_tbl,
},
}; };
static struct pci_device_id qla2322_pci_tbl[] = { static struct pci_device_id qla2322_pci_tbl[] = {
@ -62,6 +67,13 @@ static struct pci_device_id qla2322_pci_tbl[] = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[0], .driver_data = (unsigned long)&qla_board_tbl[0],
}, },
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP6322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[1],
},
{0, 0}, {0, 0},
}; };
MODULE_DEVICE_TABLE(pci, qla2322_pci_tbl); MODULE_DEVICE_TABLE(pci, qla2322_pci_tbl);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -49,6 +49,18 @@ static struct qla_board_info qla_board_tbl[] = {
.fw_info = qla_fw_tbl, .fw_info = qla_fw_tbl,
.fw_fname = "ql2400_fw.bin", .fw_fname = "ql2400_fw.bin",
}, },
{
.drv_name = qla_driver_name,
.isp_name = "ISP5422",
.fw_info = qla_fw_tbl,
.fw_fname = "ql2400_fw.bin",
},
{
.drv_name = qla_driver_name,
.isp_name = "ISP5432",
.fw_info = qla_fw_tbl,
.fw_fname = "ql2400_fw.bin",
},
}; };
static struct pci_device_id qla24xx_pci_tbl[] = { static struct pci_device_id qla24xx_pci_tbl[] = {
@ -66,6 +78,21 @@ static struct pci_device_id qla24xx_pci_tbl[] = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[1], .driver_data = (unsigned long)&qla_board_tbl[1],
}, },
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP5422,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[2],
},
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP5432,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[3],
},
{0, 0}, {0, 0},
}; };
MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl); MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,101 +0,0 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "qla_def.h"
static char qla_driver_name[] = "qla6312";
extern unsigned char fw2300flx_version[];
extern unsigned char fw2300flx_version_str[];
extern unsigned short fw2300flx_addr01;
extern unsigned short fw2300flx_code01[];
extern unsigned short fw2300flx_length01;
static struct qla_fw_info qla_fw_tbl[] = {
{
.addressing = FW_INFO_ADDR_NORMAL,
.fwcode = &fw2300flx_code01[0],
.fwlen = &fw2300flx_length01,
.fwstart = &fw2300flx_addr01,
},
{ FW_INFO_ADDR_NOMORE, },
};
static struct qla_board_info qla_board_tbl[] = {
{
.drv_name = qla_driver_name,
.isp_name = "ISP6312",
.fw_info = qla_fw_tbl,
},
{
.drv_name = qla_driver_name,
.isp_name = "ISP6322",
.fw_info = qla_fw_tbl,
},
};
static struct pci_device_id qla6312_pci_tbl[] = {
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP6312,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[0],
},
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP6322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[1],
},
{0, 0},
};
MODULE_DEVICE_TABLE(pci, qla6312_pci_tbl);
static int __devinit
qla6312_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
return qla2x00_probe_one(pdev,
(struct qla_board_info *)id->driver_data);
}
static void __devexit
qla6312_remove_one(struct pci_dev *pdev)
{
qla2x00_remove_one(pdev);
}
static struct pci_driver qla6312_pci_driver = {
.name = "qla6312",
.id_table = qla6312_pci_tbl,
.probe = qla6312_probe_one,
.remove = __devexit_p(qla6312_remove_one),
};
static int __init
qla6312_init(void)
{
return pci_module_init(&qla6312_pci_driver);
}
static void __exit
qla6312_exit(void)
{
pci_unregister_driver(&qla6312_pci_driver);
}
module_init(qla6312_init);
module_exit(qla6312_exit);
MODULE_AUTHOR("QLogic Corporation");
MODULE_DESCRIPTION("QLogic ISP63xx FC-SCSI Host Bus Adapter driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(QLA2XXX_VERSION);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -50,7 +50,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
ha->host_no); ha->host_no);
vfree(ha->fw_dump_buffer); vfree(ha->fw_dump_buffer);
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
free_pages((unsigned long)ha->fw_dump, free_pages((unsigned long)ha->fw_dump,
ha->fw_dump_order); ha->fw_dump_order);
@ -64,7 +64,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) { if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) {
ha->fw_dump_reading = 1; ha->fw_dump_reading = 1;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
dump_size = FW_DUMP_SIZE_24XX; dump_size = FW_DUMP_SIZE_24XX;
else { else {
dump_size = FW_DUMP_SIZE_1M; dump_size = FW_DUMP_SIZE_1M;
@ -138,7 +138,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
return 0; return 0;
/* Checksum NVRAM. */ /* Checksum NVRAM. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
uint32_t *iter; uint32_t *iter;
uint32_t chksum; uint32_t chksum;
@ -308,6 +308,61 @@ static struct bin_attribute sysfs_optrom_ctl_attr = {
.write = qla2x00_sysfs_write_optrom_ctl, .write = qla2x00_sysfs_write_optrom_ctl,
}; };
static ssize_t
qla2x00_sysfs_read_vpd(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)));
unsigned long flags;
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);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ha->vpd_size;
}
static ssize_t
qla2x00_sysfs_write_vpd(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)));
unsigned long flags;
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);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return count;
}
static struct bin_attribute sysfs_vpd_attr = {
.attr = {
.name = "vpd",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_vpd,
.write = qla2x00_sysfs_write_vpd,
};
void void
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
{ {
@ -318,6 +373,7 @@ 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_attr);
sysfs_create_bin_file(&host->shost_gendev.kobj, sysfs_create_bin_file(&host->shost_gendev.kobj,
&sysfs_optrom_ctl_attr); &sysfs_optrom_ctl_attr);
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
} }
void void
@ -330,6 +386,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
sysfs_remove_bin_file(&host->shost_gendev.kobj, sysfs_remove_bin_file(&host->shost_gendev.kobj,
&sysfs_optrom_ctl_attr); &sysfs_optrom_ctl_attr);
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
if (ha->beacon_blink_led == 1) if (ha->beacon_blink_led == 1)
ha->isp_ops.beacon_off(ha); ha->isp_ops.beacon_off(ha);
@ -450,9 +507,6 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
int len = 0; int len = 0;
switch (ha->zio_mode) { switch (ha->zio_mode) {
case QLA_ZIO_MODE_5:
len += snprintf(buf + len, PAGE_SIZE-len, "Mode 5\n");
break;
case QLA_ZIO_MODE_6: case QLA_ZIO_MODE_6:
len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n"); len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n");
break; break;
@ -470,20 +524,16 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
int val = 0; int val = 0;
uint16_t zio_mode; uint16_t zio_mode;
if (!IS_ZIO_SUPPORTED(ha))
return -ENOTSUPP;
if (sscanf(buf, "%d", &val) != 1) if (sscanf(buf, "%d", &val) != 1)
return -EINVAL; return -EINVAL;
switch (val) { if (val)
case 1:
zio_mode = QLA_ZIO_MODE_5;
break;
case 2:
zio_mode = QLA_ZIO_MODE_6; zio_mode = QLA_ZIO_MODE_6;
break; else
default:
zio_mode = QLA_ZIO_DISABLED; zio_mode = QLA_ZIO_DISABLED;
break;
}
/* Update per-hba values and queue a reset. */ /* Update per-hba values and queue a reset. */
if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) { if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) {
@ -750,7 +800,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
pfc_host_stat = &ha->fc_host_stat; pfc_host_stat = &ha->fc_host_stat;
memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
sizeof(stat_buf) / 4, mb_stat); sizeof(stat_buf) / 4, mb_stat);
} else { } else {

Просмотреть файл

@ -31,82 +31,6 @@
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport_fc.h> #include <scsi/scsi_transport_fc.h>
#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
#else
#define IS_QLA2100(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA22XX) || defined(CONFIG_SCSI_QLA22XX_MODULE)
#define IS_QLA2200(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200)
#else
#define IS_QLA2200(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA2300) || defined(CONFIG_SCSI_QLA2300_MODULE)
#define IS_QLA2300(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300)
#define IS_QLA2312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312)
#else
#define IS_QLA2300(ha) 0
#define IS_QLA2312(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA2322) || defined(CONFIG_SCSI_QLA2322_MODULE)
#define IS_QLA2322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322)
#else
#define IS_QLA2322(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA6312) || defined(CONFIG_SCSI_QLA6312_MODULE)
#define IS_QLA6312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312)
#define IS_QLA6322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322)
#else
#define IS_QLA6312(ha) 0
#define IS_QLA6322(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA24XX) || defined(CONFIG_SCSI_QLA24XX_MODULE)
#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422)
#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
#else
#define IS_QLA2422(ha) 0
#define IS_QLA2432(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA25XX) || defined(CONFIG_SCSI_QLA25XX_MODULE)
#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512)
#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522)
#else
#define IS_QLA2512(ha) 0
#define IS_QLA2522(ha) 0
#endif
#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
#define IS_QLA2200(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200)
#define IS_QLA2300(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300)
#define IS_QLA2312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312)
#define IS_QLA2322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322)
#define IS_QLA6312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312)
#define IS_QLA6322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322)
#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422)
#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512)
#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522)
#endif
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha))
/*
* Only non-ISP2[12]00 have extended addressing support in the firmware.
*/
#define HAS_EXTENDED_IDS(ha) (!IS_QLA2100(ha) && !IS_QLA2200(ha))
/* /*
* We have MAILBOX_REGISTER_COUNT sized arrays in a few places, * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
* but that's fine as we don't look at the last 24 ones for * but that's fine as we don't look at the last 24 ones for
@ -838,7 +762,6 @@ typedef struct {
#define PD_STATE_WAIT_PORT_LOGOUT_ACK 11 #define PD_STATE_WAIT_PORT_LOGOUT_ACK 11
#define QLA_ZIO_MODE_5 (BIT_2 | BIT_0)
#define QLA_ZIO_MODE_6 (BIT_2 | BIT_1) #define QLA_ZIO_MODE_6 (BIT_2 | BIT_1)
#define QLA_ZIO_DISABLED 0 #define QLA_ZIO_DISABLED 0
#define QLA_ZIO_DEFAULT_TIMER 2 #define QLA_ZIO_DEFAULT_TIMER 2
@ -2300,6 +2223,47 @@ typedef struct scsi_qla_host {
#define SWITCH_FOUND BIT_3 #define SWITCH_FOUND BIT_3
#define DFLG_NO_CABLE BIT_4 #define DFLG_NO_CABLE BIT_4
uint32_t device_type;
#define DT_ISP2100 BIT_0
#define DT_ISP2200 BIT_1
#define DT_ISP2300 BIT_2
#define DT_ISP2312 BIT_3
#define DT_ISP2322 BIT_4
#define DT_ISP6312 BIT_5
#define DT_ISP6322 BIT_6
#define DT_ISP2422 BIT_7
#define DT_ISP2432 BIT_8
#define DT_ISP5422 BIT_9
#define DT_ISP5432 BIT_10
#define DT_ISP_LAST (DT_ISP5432 << 1)
#define DT_ZIO_SUPPORTED BIT_28
#define DT_OEM_001 BIT_29
#define DT_ISP2200A BIT_30
#define DT_EXTENDED_IDS BIT_31
#define DT_MASK(ha) ((ha)->device_type & (DT_ISP_LAST - 1))
#define IS_QLA2100(ha) (DT_MASK(ha) & DT_ISP2100)
#define IS_QLA2200(ha) (DT_MASK(ha) & DT_ISP2200)
#define IS_QLA2300(ha) (DT_MASK(ha) & DT_ISP2300)
#define IS_QLA2312(ha) (DT_MASK(ha) & DT_ISP2312)
#define IS_QLA2322(ha) (DT_MASK(ha) & DT_ISP2322)
#define IS_QLA6312(ha) (DT_MASK(ha) & DT_ISP6312)
#define IS_QLA6322(ha) (DT_MASK(ha) & DT_ISP6322)
#define IS_QLA2422(ha) (DT_MASK(ha) & DT_ISP2422)
#define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432)
#define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422)
#define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432)
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
#define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha))
#define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED)
#define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001)
#define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS)
/* SRB cache. */ /* SRB cache. */
#define SRB_MIN_REQ 128 #define SRB_MIN_REQ 128
mempool_t *srb_mempool; mempool_t *srb_mempool;
@ -2381,6 +2345,8 @@ typedef struct scsi_qla_host {
/* NVRAM configuration data */ /* NVRAM configuration data */
uint16_t nvram_size; uint16_t nvram_size;
uint16_t nvram_base; uint16_t nvram_base;
uint16_t vpd_size;
uint16_t vpd_base;
uint16_t loop_reset_delay; uint16_t loop_reset_delay;
uint8_t retry_count; uint8_t retry_count;
@ -2414,11 +2380,7 @@ typedef struct scsi_qla_host {
struct sns_cmd_pkt *sns_cmd; struct sns_cmd_pkt *sns_cmd;
dma_addr_t sns_cmd_dma; dma_addr_t sns_cmd_dma;
pid_t dpc_pid; struct task_struct *dpc_thread;
int dpc_should_die;
struct completion dpc_inited;
struct completion dpc_exited;
struct semaphore *dpc_wait;
uint8_t dpc_active; /* DPC routine is active */ uint8_t dpc_active; /* DPC routine is active */
/* Timeout timers. */ /* Timeout timers. */

Просмотреть файл

@ -1,146 +1,81 @@
#define QLA_MODEL_NAMES 0x44 #define QLA_MODEL_NAMES 0x4A
/* /*
* Adapter model names. * Adapter model names and descriptions.
*/ */
static char *qla2x00_model_name[QLA_MODEL_NAMES] = { static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
"QLA2340", /* 0x100 */ "QLA2340", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x100 */
"QLA2342", /* 0x101 */ "QLA2342", "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x101 */
"QLA2344", /* 0x102 */ "QLA2344", "133MHz PCI-X to 2Gb FC, Quad Channel", /* 0x102 */
"QCP2342", /* 0x103 */ "QCP2342", "cPCI to 2Gb FC, Dual Channel", /* 0x103 */
"QSB2340", /* 0x104 */ "QSB2340", "SBUS to 2Gb FC, Single Channel", /* 0x104 */
"QSB2342", /* 0x105 */ "QSB2342", "SBUS to 2Gb FC, Dual Channel", /* 0x105 */
"QLA2310", /* 0x106 */ "QLA2310", "Sun 66MHz PCI-X to 2Gb FC, Single Channel", /* 0x106 */
"QLA2332", /* 0x107 */ "QLA2332", "Sun 66MHz PCI-X to 2Gb FC, Single Channel", /* 0x107 */
"QCP2332", /* 0x108 */ "QCP2332", "Sun cPCI to 2Gb FC, Dual Channel", /* 0x108 */
"QCP2340", /* 0x109 */ "QCP2340", "cPCI to 2Gb FC, Single Channel", /* 0x109 */
"QLA2342", /* 0x10a */ "QLA2342", "Sun 133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10a */
"QCP2342", /* 0x10b */ "QCP2342", "Sun - cPCI to 2Gb FC, Dual Channel", /* 0x10b */
"QLA2350", /* 0x10c */ "QLA2350", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x10c */
"QLA2352", /* 0x10d */ "QLA2352", "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10d */
"QLA2352", /* 0x10e */ "QLA2352", "Sun 133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10e */
"HPQ SVS", /* 0x10f */ " ", " ", /* 0x10f */
"HPQ SVS", /* 0x110 */ " ", " ", /* 0x110 */
" ", /* 0x111 */ " ", " ", /* 0x111 */
" ", /* 0x112 */ " ", " ", /* 0x112 */
" ", /* 0x113 */ " ", " ", /* 0x113 */
" ", /* 0x114 */ " ", " ", /* 0x114 */
"QLA2360", /* 0x115 */ "QLA2360", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x115 */
"QLA2362", /* 0x116 */ "QLA2362", "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x116 */
"QLE2360", /* 0x117 */ "QLE2360", "PCI-Express to 2Gb FC, Single Channel", /* 0x117 */
"QLE2362", /* 0x118 */ "QLE2362", "PCI-Express to 2Gb FC, Dual Channel", /* 0x118 */
"QLA200", /* 0x119 */ "QLA200", "133MHz PCI-X to 2Gb FC Optical", /* 0x119 */
"QLA200C", /* 0x11a */ " ", " ", /* 0x11a */
"QLA200P", /* 0x11b */ " ", " ", /* 0x11b */
"QLA200P", /* 0x11c */ "QLA200P", "133MHz PCI-X to 2Gb FC SFP", /* 0x11c */
" ", /* 0x11d */ " ", " ", /* 0x11d */
" ", /* 0x11e */ " ", " ", /* 0x11e */
" ", /* 0x11f */ " ", " ", /* 0x11f */
" ", /* 0x120 */ " ", " ", /* 0x120 */
" ", /* 0x121 */ " ", " ", /* 0x121 */
" ", /* 0x122 */ " ", " ", /* 0x122 */
" ", /* 0x123 */ " ", " ", /* 0x123 */
" ", /* 0x124 */ " ", " ", /* 0x124 */
" ", /* 0x125 */ " ", " ", /* 0x125 */
" ", /* 0x126 */ " ", " ", /* 0x126 */
" ", /* 0x127 */ " ", " ", /* 0x127 */
" ", /* 0x128 */ " ", " ", /* 0x128 */
" ", /* 0x129 */ " ", " ", /* 0x129 */
" ", /* 0x12a */ " ", " ", /* 0x12a */
" ", /* 0x12b */ " ", " ", /* 0x12b */
" ", /* 0x12c */ " ", " ", /* 0x12c */
" ", /* 0x12d */ " ", " ", /* 0x12d */
" ", /* 0x12e */ " ", " ", /* 0x12e */
"QLA210", /* 0x12f */ "QLA210", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x12f */
"EMC 250", /* 0x130 */ "EMC 250", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x130 */
"HP A7538A", /* 0x131 */ "HP A7538A", "HP 1p2g PCI-X to 2Gb FC, Single Channel", /* 0x131 */
"QLA210", /* 0x132 */ "QLA210", "Sun 133MHz PCI-X to 2Gb FC, Single Channel", /* 0x132 */
"QLA2460", /* 0x133 */ "QLA2460", "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x133 */
"QLA2462", /* 0x134 */ "QLA2462", "PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x134 */
"QMC2462", /* 0x135 */ "QMC2462", "IBM eServer BC 4Gb FC Expansion Card", /* 0x135 */
"QMC2462S", /* 0x136 */ "QMC2462S", "IBM eServer BC 4Gb FC Expansion Card SFF", /* 0x136 */
"QLE2460", /* 0x137 */ "QLE2460", "PCI-Express to 4Gb FC, Single Channel", /* 0x137 */
"QLE2462", /* 0x138 */ "QLE2462", "PCI-Express to 4Gb FC, Dual Channel", /* 0x138 */
"QME2462", /* 0x139 */ "QME2462", "Dell BS PCI-Express to 4Gb FC, Dual Channel", /* 0x139 */
"QLA2440", /* 0x13a */ " ", " ", /* 0x13a */
"QLA2442", /* 0x13b */ " ", " ", /* 0x13b */
"QSM2442", /* 0x13c */ " ", " ", /* 0x13c */
"QSM2462", /* 0x13d */ "QEM2462", "Sun Server I/O Module 4Gb FC, Dual Channel", /* 0x13d */
"QLE210", /* 0x13e */ "QLE210", "PCI-Express to 2Gb FC, Single Channel", /* 0x13e */
"QLE220", /* 0x13f */ "QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x13f */
"QLA2460", /* 0x140 */ "QLA2460", "Sun PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x140 */
"QLA2462", /* 0x141 */ "QLA2462", "Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */
"QLE2460", /* 0x142 */ "QLE2460", "Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */
"QLE2462" /* 0x143 */ "QLE2462", "Sun PCI-Express to 4Gb FC, Single Channel", /* 0x143 */
}; "QEM2462" "Server I/O Module 4Gb FC, Dual Channel", /* 0x144 */
"QLE2440", "PCI-Express to 4Gb FC, Single Channel", /* 0x145 */
static char *qla2x00_model_desc[QLA_MODEL_NAMES] = { "QLE2464", "PCI-Express to 4Gb FC, Quad Channel", /* 0x146 */
"133MHz PCI-X to 2Gb FC, Single Channel", /* 0x100 */ "QLA2440", "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x147 */
"133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x101 */ " ", " ", /* 0x148 */
"133MHz PCI-X to 2Gb FC, Quad Channel", /* 0x102 */ "QLA2340", "Sun 133MHz PCI-X to 2Gb FC, Single Channel", /* 0x149 */
" ", /* 0x103 */
" ", /* 0x104 */
" ", /* 0x105 */
" ", /* 0x106 */
" ", /* 0x107 */
" ", /* 0x108 */
" ", /* 0x109 */
" ", /* 0x10a */
" ", /* 0x10b */
"133MHz PCI-X to 2Gb FC, Single Channel", /* 0x10c */
"133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10d */
" ", /* 0x10e */
"HPQ SVS HBA- Initiator device", /* 0x10f */
"HPQ SVS HBA- Target device", /* 0x110 */
" ", /* 0x111 */
" ", /* 0x112 */
" ", /* 0x113 */
" ", /* 0x114 */
"133MHz PCI-X to 2Gb FC, Single Channel", /* 0x115 */
"133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x116 */
"PCI-Express to 2Gb FC, Single Channel", /* 0x117 */
"PCI-Express to 2Gb FC, Dual Channel", /* 0x118 */
"133MHz PCI-X to 2Gb FC Optical", /* 0x119 */
"133MHz PCI-X to 2Gb FC Copper", /* 0x11a */
"133MHz PCI-X to 2Gb FC SFP", /* 0x11b */
"133MHz PCI-X to 2Gb FC SFP", /* 0x11c */
" ", /* 0x11d */
" ", /* 0x11e */
" ", /* 0x11f */
" ", /* 0x120 */
" ", /* 0x121 */
" ", /* 0x122 */
" ", /* 0x123 */
" ", /* 0x124 */
" ", /* 0x125 */
" ", /* 0x126 */
" ", /* 0x127 */
" ", /* 0x128 */
" ", /* 0x129 */
" ", /* 0x12a */
" ", /* 0x12b */
" ", /* 0x12c */
" ", /* 0x12d */
" ", /* 0x12e */
"133MHz PCI-X to 2Gb FC SFF", /* 0x12f */
"133MHz PCI-X to 2Gb FC SFF", /* 0x130 */
"HP 1p2g QLA2340", /* 0x131 */
"133MHz PCI-X to 2Gb FC, Single Channel", /* 0x132 */
"PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x133 */
"PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x134 */
"IBM eServer BC 4Gb FC Expansion Card", /* 0x135 */
"IBM eServer BC 4Gb FC Expansion Card SFF", /* 0x136 */
"PCI-Express to 4Gb FC, Single Channel", /* 0x137 */
"PCI-Express to 4Gb FC, Dual Channel", /* 0x138 */
"Dell PCI-Express to 4Gb FC, Dual Channel", /* 0x139 */
"PCI-X 1.0 to 4Gb FC, Single Channel", /* 0x13a */
"PCI-X 1.0 to 4Gb FC, Dual Channel", /* 0x13b */
"Server I/O Module 4Gb FC, Single Channel", /* 0x13c */
"Server I/O Module 4Gb FC, Single Channel", /* 0x13d */
"PCI-Express to 2Gb FC, Single Channel", /* 0x13e */
"PCI-Express to 4Gb FC, Single Channel", /* 0x13f */
"Sun PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x140 */
"Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */
"Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */
"Sun PCI-Express to 4Gb FC, Single Channel" /* 0x143 */
}; };

Просмотреть файл

@ -759,7 +759,7 @@ struct device_reg_24xx {
#define FA_NVRAM_FUNC0_ADDR 0x80 #define FA_NVRAM_FUNC0_ADDR 0x80
#define FA_NVRAM_FUNC1_ADDR 0x180 #define FA_NVRAM_FUNC1_ADDR 0x180
#define FA_NVRAM_VPD_SIZE 0x80 #define FA_NVRAM_VPD_SIZE 0x200
#define FA_NVRAM_VPD0_ADDR 0x00 #define FA_NVRAM_VPD0_ADDR 0x00
#define FA_NVRAM_VPD1_ADDR 0x100 #define FA_NVRAM_VPD1_ADDR 0x100
/* /*

Просмотреть файл

@ -42,7 +42,7 @@ extern int qla2x00_loop_resync(scsi_qla_host_t *);
extern int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *); extern int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *);
extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
extern int qla2x00_local_device_login(scsi_qla_host_t *, uint16_t); extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
@ -81,6 +81,8 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
extern void qla2xxx_wake_dpc(scsi_qla_host_t *);
/* /*
* Global Function Prototypes in qla_iocb.c source file. * Global Function Prototypes in qla_iocb.c source file.
*/ */
@ -164,7 +166,8 @@ qla24xx_login_fabric(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t,
uint16_t *, uint8_t); uint16_t *, uint8_t);
extern int extern int
qla2x00_login_local_device(scsi_qla_host_t *, uint16_t, uint16_t *, uint8_t); qla2x00_login_local_device(scsi_qla_host_t *, fc_port_t *, uint16_t *,
uint8_t);
extern int extern int
qla2x00_fabric_logout(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t); qla2x00_fabric_logout(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t);

Просмотреть файл

@ -126,7 +126,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,
DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",
ha->host_no, routine, ms_pkt->entry_status)); ha->host_no, routine, ms_pkt->entry_status));
} else { } else {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
comp_status = comp_status =
((struct ct_entry_24xx *)ms_pkt)->comp_status; ((struct ct_entry_24xx *)ms_pkt)->comp_status;
else else
@ -1200,7 +1200,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size)
ms_iocb_entry_t *ms_pkt = ha->ms_iocb; ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
ct_pkt->cmd_byte_count = cpu_to_le32(req_size); ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
} else { } else {
@ -1529,9 +1529,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
eiter->len = __constant_cpu_to_be16(4 + 4); eiter->len = __constant_cpu_to_be16(4 + 4);
if (IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(8);
else if (IS_QLA24XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(4); eiter->a.sup_speed = __constant_cpu_to_be32(4);
else if (IS_QLA23XX(ha)) else if (IS_QLA23XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(2); eiter->a.sup_speed = __constant_cpu_to_be32(2);
@ -1566,7 +1564,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
eiter->len = __constant_cpu_to_be16(4 + 4); eiter->len = __constant_cpu_to_be16(4 + 4);
max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ? max_frame_size = IS_QLA24XX(ha) || IS_QLA54XX(ha) ?
(uint32_t) icb24->frame_payload_size: (uint32_t) icb24->frame_payload_size:
(uint32_t) ha->init_cb->frame_payload_size; (uint32_t) ha->init_cb->frame_payload_size;
eiter->a.max_frame_size = cpu_to_be32(max_frame_size); eiter->a.max_frame_size = cpu_to_be32(max_frame_size);

Просмотреть файл

@ -387,7 +387,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha)
/* Verify checksum of loaded RISC code. */ /* Verify checksum of loaded RISC code. */
rval = qla2x00_verify_checksum(ha, rval = qla2x00_verify_checksum(ha,
IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS : IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS :
*ha->brd_info->fw_info[0].fwstart); *ha->brd_info->fw_info[0].fwstart);
} }
@ -727,6 +727,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha)
DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n", DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n",
ha->host_no)); ha->host_no));
ha->device_type |= DT_ISP2200A;
ha->fw_transfer_size = 128; ha->fw_transfer_size = 128;
} }
@ -821,7 +822,7 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha)
if (IS_QLA2100(ha) || IS_QLA2200(ha)) if (IS_QLA2100(ha) || IS_QLA2200(ha))
return; return;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
qla2x00_alloc_fw_dump(ha); qla2x00_alloc_fw_dump(ha);
/* Retrieve IOCB counts available to the firmware. */ /* Retrieve IOCB counts available to the firmware. */
@ -1002,6 +1003,10 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha)
if (ha->flags.enable_led_scheme) if (ha->flags.enable_led_scheme)
ha->fw_options[2] |= BIT_12; ha->fw_options[2] |= BIT_12;
/* Detect ISP6312. */
if (IS_QLA6312(ha))
ha->fw_options[2] |= BIT_13;
/* Update firmware options. */ /* Update firmware options. */
qla2x00_set_fw_options(ha, ha->fw_options); qla2x00_set_fw_options(ha, ha->fw_options);
} }
@ -1500,9 +1505,9 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
index = (ha->pdev->subsystem_device & 0xff); index = (ha->pdev->subsystem_device & 0xff);
if (index < QLA_MODEL_NAMES) { if (index < QLA_MODEL_NAMES) {
strcpy(ha->model_number, strcpy(ha->model_number,
qla2x00_model_name[index]); qla2x00_model_name[index * 2]);
ha->model_desc = ha->model_desc =
qla2x00_model_desc[index]; qla2x00_model_name[index * 2 + 1];
} else { } else {
strcpy(ha->model_number, "QLA23xx"); strcpy(ha->model_number, "QLA23xx");
} }
@ -1654,6 +1659,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
~(BIT_3 | BIT_2 | BIT_1 | BIT_0); ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->flags.process_response_queue = 0; ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) { if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer " DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
"delay (%d us).\n", ha->host_no, ha->zio_mode, "delay (%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100)); ha->zio_timer * 100));
@ -2122,7 +2129,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
LIST_HEAD(new_fcports); LIST_HEAD(new_fcports);
/* If FL port exists, then SNS is present */ /* If FL port exists, then SNS is present */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
loop_id = NPH_F_PORT; loop_id = NPH_F_PORT;
else else
loop_id = SNS_FL_PORT; loop_id = SNS_FL_PORT;
@ -2148,7 +2155,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
qla2x00_fdmi_register(ha); qla2x00_fdmi_register(ha);
/* Ensure we are logged into the SNS. */ /* Ensure we are logged into the SNS. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
loop_id = NPH_SNS; loop_id = NPH_SNS;
else else
loop_id = SIMPLE_NAME_SERVER; loop_id = SIMPLE_NAME_SERVER;
@ -2639,7 +2646,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
if (ql2xprocessrscn && if (ql2xprocessrscn &&
!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
!IS_QLA6312(ha) && !IS_QLA6322(ha) && !IS_QLA6312(ha) && !IS_QLA6322(ha) &&
!IS_QLA24XX(ha) && !IS_QLA25XX(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
ha->flags.init_done) { ha->flags.init_done) {
/* Handle port RSCN via asyncronous IOCBs */ /* Handle port RSCN via asyncronous IOCBs */
rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, rval2 = qla2x00_handle_port_rscn(ha, rscn_entry,
@ -2881,13 +2888,13 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
* 3 - Fatal error * 3 - Fatal error
*/ */
int int
qla2x00_local_device_login(scsi_qla_host_t *ha, uint16_t loop_id) qla2x00_local_device_login(scsi_qla_host_t *ha, fc_port_t *fcport)
{ {
int rval; int rval;
uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t mb[MAILBOX_REGISTER_COUNT];
memset(mb, 0, sizeof(mb)); memset(mb, 0, sizeof(mb));
rval = qla2x00_login_local_device(ha, loop_id, mb, BIT_0); rval = qla2x00_login_local_device(ha, fcport, mb, BIT_0);
if (rval == QLA_SUCCESS) { if (rval == QLA_SUCCESS) {
/* Interrogate mailbox registers for any errors */ /* Interrogate mailbox registers for any errors */
if (mb[0] == MBS_COMMAND_ERROR) if (mb[0] == MBS_COMMAND_ERROR)
@ -3129,7 +3136,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
/* /*
* Disable SRAM, Instruction RAM and GP RAM * Disable SRAM, Instruction RAM and GP RAM
* parity. * parity.
@ -3145,7 +3152,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
/* Enable proper parity */ /* Enable proper parity */
if (IS_QLA2300(ha)) if (IS_QLA2300(ha))
/* SRAM parity */ /* SRAM parity */
@ -3258,8 +3265,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
/* Determine NVRAM starting address. */ /* Determine NVRAM starting address. */
ha->nvram_size = sizeof(struct nvram_24xx); ha->nvram_size = sizeof(struct nvram_24xx);
ha->nvram_base = FA_NVRAM_FUNC0_ADDR; ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
if (PCI_FUNC(ha->pdev->devfn)) ha->vpd_size = FA_NVRAM_VPD_SIZE;
ha->vpd_base = FA_NVRAM_VPD0_ADDR;
if (PCI_FUNC(ha->pdev->devfn)) {
ha->nvram_base = FA_NVRAM_FUNC1_ADDR; ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
ha->vpd_base = FA_NVRAM_VPD1_ADDR;
}
/* Get NVRAM data and calculate checksum. */ /* Get NVRAM data and calculate checksum. */
dptr = (uint32_t *)nv; dptr = (uint32_t *)nv;
@ -3368,7 +3379,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
index = (ha->pdev->subsystem_device & 0xff); index = (ha->pdev->subsystem_device & 0xff);
if (index < QLA_MODEL_NAMES) if (index < QLA_MODEL_NAMES)
ha->model_desc = qla2x00_model_desc[index]; ha->model_desc = qla2x00_model_name[index * 2 + 1];
} else } else
strcpy(ha->model_number, "QLA2462"); strcpy(ha->model_number, "QLA2462");
@ -3465,6 +3476,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
ha->flags.process_response_queue = 0; ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) { if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay " DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
"(%d us).\n", ha->host_no, ha->zio_mode, "(%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100)); ha->zio_timer * 100));

Просмотреть файл

@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
static inline int static inline int
qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id)
{ {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
return (loop_id > NPH_LAST_HANDLE); return (loop_id > NPH_LAST_HANDLE);
return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||

Просмотреть файл

@ -466,7 +466,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
mrk->entry_type = MARKER_TYPE; mrk->entry_type = MARKER_TYPE;
mrk->modifier = type; mrk->modifier = type;
if (type != MK_SYNC_ALL) { if (type != MK_SYNC_ALL) {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mrk24 = (struct mrk_entry_24xx *) mrk; mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->nport_handle = cpu_to_le16(loop_id);
mrk24->lun[1] = LSB(lun); mrk24->lun[1] = LSB(lun);
@ -519,7 +519,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
for (timer = HZ; timer; timer--) { for (timer = HZ; timer; timer--) {
if ((req_cnt + 2) >= ha->req_q_cnt) { if ((req_cnt + 2) >= ha->req_q_cnt) {
/* Calculate number of free request entries. */ /* Calculate number of free request entries. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
cnt = (uint16_t)RD_REG_DWORD( cnt = (uint16_t)RD_REG_DWORD(
&reg->isp24.req_q_out); &reg->isp24.req_q_out);
else else
@ -593,7 +593,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha)
ha->request_ring_ptr++; ha->request_ring_ptr++;
/* Set chip new ring index. */ /* Set chip new ring index. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
WRT_REG_DWORD(&reg->isp24.req_q_in, ha->req_ring_index); WRT_REG_DWORD(&reg->isp24.req_q_in, ha->req_ring_index);
RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in); RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
} else { } else {

Просмотреть файл

@ -343,7 +343,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->isp_ops.fw_dump(ha, 1); ha->isp_ops.fw_dump(ha, 1);
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
if (mb[1] == 0 && mb[2] == 0) { if (mb[1] == 0 && mb[2] == 0) {
qla_printk(KERN_ERR, ha, qla_printk(KERN_ERR, ha,
"Unrecoverable Hardware Error: adapter " "Unrecoverable Hardware Error: adapter "
@ -521,7 +521,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
*/ */
if (ql2xprocessrscn && if (ql2xprocessrscn &&
!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
!IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
ha->flags.init_done && mb[1] != 0xffff && ha->flags.init_done && mb[1] != 0xffff &&
((ha->operating_mode == P2P && mb[1] != 0) || ((ha->operating_mode == P2P && mb[1] != 0) ||
(ha->operating_mode != P2P && mb[1] != (ha->operating_mode != P2P && mb[1] !=
@ -638,7 +638,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
"scsi(%ld): [R|Z]IO update completion.\n", "scsi(%ld): [R|Z]IO update completion.\n",
ha->host_no)); ha->host_no));
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
qla24xx_process_response_queue(ha); qla24xx_process_response_queue(ha);
else else
qla2x00_process_response_queue(ha); qla2x00_process_response_queue(ha);
@ -810,7 +810,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
sts = (sts_entry_t *) pkt; sts = (sts_entry_t *) pkt;
sts24 = (struct sts_entry_24xx *) pkt; sts24 = (struct sts_entry_24xx *) pkt;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
comp_status = le16_to_cpu(sts24->comp_status); comp_status = le16_to_cpu(sts24->comp_status);
scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
} else { } else {
@ -838,9 +838,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n"); qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
if (ha->dpc_wait && !ha->dpc_active) qla2xxx_wake_dpc(ha);
up(ha->dpc_wait);
return; return;
} }
cp = sp->cmd; cp = sp->cmd;
@ -862,7 +860,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
fcport = sp->fcport; fcport = sp->fcport;
sense_len = rsp_info_len = resid_len = 0; sense_len = rsp_info_len = resid_len = 0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
sense_len = le32_to_cpu(sts24->sense_len); sense_len = le32_to_cpu(sts24->sense_len);
rsp_info_len = le32_to_cpu(sts24->rsp_data_len); rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
resid_len = le32_to_cpu(sts24->rsp_residual_count); resid_len = le32_to_cpu(sts24->rsp_residual_count);
@ -880,7 +878,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
/* Check for any FCP transport errors. */ /* Check for any FCP transport errors. */
if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
/* Sense data lies beyond any FCP RESPONSE data. */ /* Sense data lies beyond any FCP RESPONSE data. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
sense_data += rsp_info_len; sense_data += rsp_info_len;
if (rsp_info_len > 3 && rsp_info[3]) { if (rsp_info_len > 3 && rsp_info[3]) {
DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
@ -1119,7 +1117,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
case CS_TIMEOUT: case CS_TIMEOUT:
cp->result = DID_BUS_BUSY << 16; cp->result = DID_BUS_BUSY << 16;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
DEBUG2(printk(KERN_INFO DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d:%d): TIMEOUT status detected " "scsi(%ld:%d:%d:%d): TIMEOUT status detected "
"0x%x-0x%x\n", ha->host_no, cp->device->channel, "0x%x-0x%x\n", ha->host_no, cp->device->channel,
@ -1199,7 +1197,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
} }
/* Move sense data. */ /* Move sense data. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
host_to_fcp_swap(pkt->data, sizeof(pkt->data)); host_to_fcp_swap(pkt->data, sizeof(pkt->data));
memcpy(sp->request_sense_ptr, pkt->data, sense_sz); memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));
@ -1271,8 +1269,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
"Error entry - invalid handle\n"); "Error entry - invalid handle\n");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
if (ha->dpc_wait && !ha->dpc_active) qla2xxx_wake_dpc(ha);
up(ha->dpc_wait);
} }
} }

Просмотреть файл

@ -91,7 +91,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
/* Load mailbox registers. */ /* Load mailbox registers. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
optr = (uint16_t __iomem *)&reg->isp24.mailbox0; optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
else else
optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0); optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0);
@ -155,7 +155,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT); WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
else else
WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT); WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@ -179,7 +179,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
ha->host_no, command);) ha->host_no, command);)
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT); WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
else else
WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT); WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@ -237,7 +237,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
uint16_t mb0; uint16_t mb0;
uint32_t ictrl; uint32_t ictrl;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mb0 = RD_REG_WORD(&reg->isp24.mailbox0); mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
ictrl = RD_REG_DWORD(&reg->isp24.ictrl); ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
} else { } else {
@ -284,9 +284,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
"Mailbox command timeout occured. Scheduling ISP " "Mailbox command timeout occured. Scheduling ISP "
"abort.\n"); "abort.\n");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
if (ha->dpc_wait && !ha->dpc_active) qla2xxx_wake_dpc(ha);
up(ha->dpc_wait);
} else if (!abort_active) { } else if (!abort_active) {
/* call abort directly since we are in the DPC thread */ /* call abort directly since we are in the DPC thread */
DEBUG(printk("%s(%ld): timeout calling abort_isp\n", DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
@ -336,7 +334,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
mcp->mb[8] = MSW(risc_addr); mcp->mb[8] = MSW(risc_addr);
mcp->out_mb = MBX_8|MBX_0; mcp->out_mb = MBX_8|MBX_0;
@ -350,7 +348,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
mcp->mb[6] = MSW(MSD(req_dma)); mcp->mb[6] = MSW(MSD(req_dma));
mcp->mb[7] = LSW(MSD(req_dma)); mcp->mb[7] = LSW(MSD(req_dma));
mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[4] = MSW(risc_code_size); mcp->mb[4] = MSW(risc_code_size);
mcp->mb[5] = LSW(risc_code_size); mcp->mb[5] = LSW(risc_code_size);
mcp->out_mb |= MBX_5|MBX_4; mcp->out_mb |= MBX_5|MBX_4;
@ -401,7 +399,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[1] = MSW(risc_addr); mcp->mb[1] = MSW(risc_addr);
mcp->mb[2] = LSW(risc_addr); mcp->mb[2] = LSW(risc_addr);
mcp->mb[3] = 0; mcp->mb[3] = 0;
@ -424,7 +422,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
ha->host_no, rval, mcp->mb[0])); ha->host_no, rval, mcp->mb[0]));
} else { } else {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
DEBUG11(printk("%s(%ld): done exchanges=%x.\n", DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
__func__, ha->host_no, mcp->mb[1]);) __func__, ha->host_no, mcp->mb[1]);)
} else { } else {
@ -565,7 +563,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
mcp->mb[3] = fwopts[3]; mcp->mb[3] = fwopts[3];
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->in_mb |= MBX_1; mcp->in_mb |= MBX_1;
} else { } else {
mcp->mb[10] = fwopts[10]; mcp->mb[10] = fwopts[10];
@ -678,7 +676,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
mcp->mb[0] = MBC_VERIFY_CHECKSUM; mcp->mb[0] = MBC_VERIFY_CHECKSUM;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[1] = MSW(risc_addr); mcp->mb[1] = MSW(risc_addr);
mcp->mb[2] = LSW(risc_addr); mcp->mb[2] = LSW(risc_addr);
mcp->out_mb |= MBX_2|MBX_1; mcp->out_mb |= MBX_2|MBX_1;
@ -695,7 +693,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__,
ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ?
(mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));) (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));)
} else { } else {
DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
@ -753,7 +751,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
/* Mask reserved bits. */ /* Mask reserved bits. */
sts_entry->entry_status &= sts_entry->entry_status &=
IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RF_MASK_24XX :RF_MASK; IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RF_MASK_24XX :RF_MASK;
} }
return rval; return rval;
@ -1093,7 +1091,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
mcp->mb[0] = MBC_GET_PORT_DATABASE; mcp->mb[0] = MBC_GET_PORT_DATABASE;
if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA25XX(ha)) if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA54XX(ha))
mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE;
mcp->mb[2] = MSW(pd_dma); mcp->mb[2] = MSW(pd_dma);
mcp->mb[3] = LSW(pd_dma); mcp->mb[3] = LSW(pd_dma);
@ -1101,7 +1099,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
mcp->mb[7] = LSW(MSD(pd_dma)); mcp->mb[7] = LSW(MSD(pd_dma));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[1] = fcport->loop_id; mcp->mb[1] = fcport->loop_id;
mcp->mb[10] = opt; mcp->mb[10] = opt;
mcp->out_mb |= MBX_10|MBX_1; mcp->out_mb |= MBX_10|MBX_1;
@ -1114,7 +1112,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
mcp->mb[1] = fcport->loop_id << 8 | opt; mcp->mb[1] = fcport->loop_id << 8 | opt;
mcp->out_mb |= MBX_1; mcp->out_mb |= MBX_1;
} }
mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA54XX(ha) ?
PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE);
mcp->flags = MBX_DMA_IN; mcp->flags = MBX_DMA_IN;
mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
@ -1122,7 +1120,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
if (rval != QLA_SUCCESS) if (rval != QLA_SUCCESS)
goto gpd_error_out; goto gpd_error_out;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
pd24 = (struct port_database_24xx *) pd; pd24 = (struct port_database_24xx *) pd;
/* Check for logged in state. */ /* Check for logged in state. */
@ -1339,7 +1337,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[0] = MBC_LIP_FULL_LOGIN;
mcp->mb[1] = BIT_0; mcp->mb[1] = BIT_0;
mcp->mb[2] = 0xff; mcp->mb[2] = 0xff;
@ -1633,20 +1631,25 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
* *
*/ */
int int
qla2x00_login_local_device(scsi_qla_host_t *ha, uint16_t loop_id, qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport,
uint16_t *mb_ret, uint8_t opt) uint16_t *mb_ret, uint8_t opt)
{ {
int rval; int rval;
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
return qla24xx_login_fabric(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, mb_ret, opt);
DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);) DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
mcp->mb[0] = MBC_LOGIN_LOOP_PORT; mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
if (HAS_EXTENDED_IDS(ha)) if (HAS_EXTENDED_IDS(ha))
mcp->mb[1] = loop_id; mcp->mb[1] = fcport->loop_id;
else else
mcp->mb[1] = loop_id << 8; mcp->mb[1] = fcport->loop_id << 8;
mcp->mb[2] = opt; mcp->mb[2] = opt;
mcp->out_mb = MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0;
@ -1868,7 +1871,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
mcp->mb[0] = MBC_GET_ID_LIST; mcp->mb[0] = MBC_GET_ID_LIST;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[2] = MSW(id_list_dma); mcp->mb[2] = MSW(id_list_dma);
mcp->mb[3] = LSW(id_list_dma); mcp->mb[3] = LSW(id_list_dma);
mcp->mb[6] = MSW(MSD(id_list_dma)); mcp->mb[6] = MSW(MSD(id_list_dma));
@ -2059,7 +2062,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
mcp->mb[7] = LSW(MSD(stat_buf_dma)); mcp->mb[7] = LSW(MSD(stat_buf_dma));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[1] = loop_id; mcp->mb[1] = loop_id;
mcp->mb[4] = 0; mcp->mb[4] = 0;
mcp->mb[10] = 0; mcp->mb[10] = 0;
@ -2326,7 +2329,7 @@ qla2x00_system_error(scsi_qla_host_t *ha)
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
@ -2408,9 +2411,9 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
mcp->mb[0] = MBC_SERDES_PARAMS; mcp->mb[0] = MBC_SERDES_PARAMS;
mcp->mb[1] = BIT_0; mcp->mb[1] = BIT_0;
mcp->mb[2] = sw_em_1g; mcp->mb[2] = sw_em_1g | BIT_15;
mcp->mb[3] = sw_em_2g; mcp->mb[3] = sw_em_2g | BIT_15;
mcp->mb[4] = sw_em_4g; mcp->mb[4] = sw_em_4g | BIT_15;
mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
mcp->tov = 30; mcp->tov = 30;
@ -2436,7 +2439,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha)
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));

Просмотреть файл

@ -8,8 +8,8 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/smp_lock.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kthread.h>
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
@ -1146,6 +1146,57 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha)
pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);
} }
static inline void
qla2x00_set_isp_flags(scsi_qla_host_t *ha)
{
ha->device_type = DT_EXTENDED_IDS;
switch (ha->pdev->device) {
case PCI_DEVICE_ID_QLOGIC_ISP2100:
ha->device_type |= DT_ISP2100;
ha->device_type &= ~DT_EXTENDED_IDS;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2200:
ha->device_type |= DT_ISP2200;
ha->device_type &= ~DT_EXTENDED_IDS;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2300:
ha->device_type |= DT_ISP2300;
ha->device_type |= DT_ZIO_SUPPORTED;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2312:
ha->device_type |= DT_ISP2312;
ha->device_type |= DT_ZIO_SUPPORTED;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2322:
ha->device_type |= DT_ISP2322;
ha->device_type |= DT_ZIO_SUPPORTED;
if (ha->pdev->subsystem_vendor == 0x1028 &&
ha->pdev->subsystem_device == 0x0170)
ha->device_type |= DT_OEM_001;
break;
case PCI_DEVICE_ID_QLOGIC_ISP6312:
ha->device_type |= DT_ISP6312;
break;
case PCI_DEVICE_ID_QLOGIC_ISP6322:
ha->device_type |= DT_ISP6322;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2422:
ha->device_type |= DT_ISP2422;
ha->device_type |= DT_ZIO_SUPPORTED;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2432:
ha->device_type |= DT_ISP2432;
ha->device_type |= DT_ZIO_SUPPORTED;
break;
case PCI_DEVICE_ID_QLOGIC_ISP5422:
ha->device_type |= DT_ISP5422;
break;
case PCI_DEVICE_ID_QLOGIC_ISP5432:
ha->device_type |= DT_ISP5432;
break;
}
}
static int static int
qla2x00_iospace_config(scsi_qla_host_t *ha) qla2x00_iospace_config(scsi_qla_host_t *ha)
{ {
@ -1307,7 +1358,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->brd_info = brd_info; ha->brd_info = brd_info;
sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no);
ha->dpc_pid = -1; /* Set ISP-type information. */
qla2x00_set_isp_flags(ha);
/* Configure PCI I/O space */ /* Configure PCI I/O space */
ret = qla2x00_iospace_config(ha); ret = qla2x00_iospace_config(ha);
@ -1386,7 +1438,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->gid_list_info_size = 6; ha->gid_list_info_size = 6;
if (IS_QLA2322(ha) || IS_QLA6322(ha)) if (IS_QLA2322(ha) || IS_QLA6322(ha))
ha->optrom_size = OPTROM_SIZE_2322; ha->optrom_size = OPTROM_SIZE_2322;
} else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
host->max_id = MAX_TARGETS_2200; host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_24XX; ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
@ -1449,9 +1501,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
*/ */
spin_lock_init(&ha->mbx_reg_lock); spin_lock_init(&ha->mbx_reg_lock);
init_completion(&ha->dpc_inited);
init_completion(&ha->dpc_exited);
qla2x00_config_dma_addressing(ha); qla2x00_config_dma_addressing(ha);
if (qla2x00_mem_alloc(ha)) { if (qla2x00_mem_alloc(ha)) {
qla_printk(KERN_WARNING, ha, qla_printk(KERN_WARNING, ha,
@ -1478,16 +1527,14 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
/* /*
* Startup the kernel thread for this host adapter * Startup the kernel thread for this host adapter
*/ */
ha->dpc_should_die = 0; ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
ha->dpc_pid = kernel_thread(qla2x00_do_dpc, ha, 0); "%s_dpc", ha->host_str);
if (ha->dpc_pid < 0) { if (IS_ERR(ha->dpc_thread)) {
qla_printk(KERN_WARNING, ha, qla_printk(KERN_WARNING, ha,
"Unable to start DPC thread!\n"); "Unable to start DPC thread!\n");
ret = PTR_ERR(ha->dpc_thread);
ret = -ENODEV;
goto probe_failed; goto probe_failed;
} }
wait_for_completion(&ha->dpc_inited);
host->this_id = 255; host->this_id = 255;
host->cmd_per_lun = 3; host->cmd_per_lun = 3;
@ -1517,7 +1564,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
reg = ha->iobase; reg = ha->iobase;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT); WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT); WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
} else { } else {
@ -1621,8 +1668,6 @@ EXPORT_SYMBOL_GPL(qla2x00_remove_one);
static void static void
qla2x00_free_device(scsi_qla_host_t *ha) qla2x00_free_device(scsi_qla_host_t *ha)
{ {
int ret;
/* Abort any outstanding IO descriptors. */ /* Abort any outstanding IO descriptors. */
if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
qla2x00_cancel_io_descriptors(ha); qla2x00_cancel_io_descriptors(ha);
@ -1632,18 +1677,15 @@ qla2x00_free_device(scsi_qla_host_t *ha)
qla2x00_stop_timer(ha); qla2x00_stop_timer(ha);
/* Kill the kernel thread for this host */ /* Kill the kernel thread for this host */
if (ha->dpc_pid >= 0) { if (ha->dpc_thread) {
ha->dpc_should_die = 1; struct task_struct *t = ha->dpc_thread;
wmb();
ret = kill_proc(ha->dpc_pid, SIGHUP, 1);
if (ret) {
qla_printk(KERN_ERR, ha,
"Unable to signal DPC thread -- (%d)\n", ret);
/* TODO: SOMETHING MORE??? */ /*
} else { * qla2xxx_wake_dpc checks for ->dpc_thread
wait_for_completion(&ha->dpc_exited); * so we need to zero it out.
} */
ha->dpc_thread = NULL;
kthread_stop(t);
} }
/* Stop currently executing firmware. */ /* Stop currently executing firmware. */
@ -1775,8 +1817,8 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
atomic_set(&fcport->state, FCS_DEVICE_LOST); atomic_set(&fcport->state, FCS_DEVICE_LOST);
} }
if (defer && ha->dpc_wait && !ha->dpc_active) if (defer)
up(ha->dpc_wait); qla2xxx_wake_dpc(ha);
} }
/* /*
@ -1993,7 +2035,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
{ {
struct list_head *fcpl, *fcptemp; struct list_head *fcpl, *fcptemp;
fc_port_t *fcport; fc_port_t *fcport;
unsigned int wtime;/* max wait time if mbx cmd is busy. */
if (ha == NULL) { if (ha == NULL) {
/* error */ /* error */
@ -2001,11 +2042,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
return; return;
} }
/* Make sure all other threads are stopped. */
wtime = 60 * 1000;
while (ha->dpc_wait && wtime)
wtime = msleep_interruptible(wtime);
/* free ioctl memory */ /* free ioctl memory */
qla2x00_free_ioctl_mem(ha); qla2x00_free_ioctl_mem(ha);
@ -2156,7 +2192,6 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha)
static int static int
qla2x00_do_dpc(void *data) qla2x00_do_dpc(void *data)
{ {
DECLARE_MUTEX_LOCKED(sem);
scsi_qla_host_t *ha; scsi_qla_host_t *ha;
fc_port_t *fcport; fc_port_t *fcport;
uint8_t status; uint8_t status;
@ -2164,32 +2199,19 @@ qla2x00_do_dpc(void *data)
ha = (scsi_qla_host_t *)data; ha = (scsi_qla_host_t *)data;
lock_kernel();
daemonize("%s_dpc", ha->host_str);
allow_signal(SIGHUP);
ha->dpc_wait = &sem;
set_user_nice(current, -20); set_user_nice(current, -20);
unlock_kernel(); while (!kthread_should_stop()) {
complete(&ha->dpc_inited);
while (1) {
DEBUG3(printk("qla2x00: DPC handler sleeping\n")); DEBUG3(printk("qla2x00: DPC handler sleeping\n"));
if (down_interruptible(&sem)) set_current_state(TASK_INTERRUPTIBLE);
break; schedule();
__set_current_state(TASK_RUNNING);
if (ha->dpc_should_die)
break;
DEBUG3(printk("qla2x00: DPC handler waking up\n")); DEBUG3(printk("qla2x00: DPC handler waking up\n"));
/* Initialization not yet finished. Don't do anything yet. */ /* Initialization not yet finished. Don't do anything yet. */
if (!ha->flags.init_done || ha->dpc_active) if (!ha->flags.init_done)
continue; continue;
DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no)); DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no));
@ -2273,7 +2295,7 @@ qla2x00_do_dpc(void *data)
} else } else
status = status =
qla2x00_local_device_login( qla2x00_local_device_login(
ha, fcport->loop_id); ha, fcport);
if (status == QLA_SUCCESS) { if (status == QLA_SUCCESS) {
fcport->old_loop_id = fcport->loop_id; fcport->old_loop_id = fcport->loop_id;
@ -2356,10 +2378,16 @@ qla2x00_do_dpc(void *data)
/* /*
* Make sure that nobody tries to wake us up again. * Make sure that nobody tries to wake us up again.
*/ */
ha->dpc_wait = NULL;
ha->dpc_active = 0; ha->dpc_active = 0;
complete_and_exit(&ha->dpc_exited, 0); return 0;
}
void
qla2xxx_wake_dpc(scsi_qla_host_t *ha)
{
if (ha->dpc_thread)
wake_up_process(ha->dpc_thread);
} }
/* /*
@ -2540,11 +2568,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) && test_bit(RELOGIN_NEEDED, &ha->dpc_flags)))
ha->dpc_wait && !ha->dpc_active) { qla2xxx_wake_dpc(ha);
up(ha->dpc_wait);
}
qla2x00_restart_timer(ha, WATCH_INTERVAL); qla2x00_restart_timer(ha, WATCH_INTERVAL);
} }
@ -2576,13 +2601,12 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
/* Firmware interface routines. */ /* Firmware interface routines. */
#define FW_BLOBS 6 #define FW_BLOBS 5
#define FW_ISP21XX 0 #define FW_ISP21XX 0
#define FW_ISP22XX 1 #define FW_ISP22XX 1
#define FW_ISP2300 2 #define FW_ISP2300 2
#define FW_ISP2322 3 #define FW_ISP2322 3
#define FW_ISP63XX 4 #define FW_ISP24XX 4
#define FW_ISP24XX 5
static DECLARE_MUTEX(qla_fw_lock); static DECLARE_MUTEX(qla_fw_lock);
@ -2591,7 +2615,6 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
{ .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, }, { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, },
{ .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, }, { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
{ .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
{ .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, },
{ .name = "ql2400_fw.bin", }, { .name = "ql2400_fw.bin", },
}; };
@ -2605,13 +2628,11 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
blob = &qla_fw_blobs[FW_ISP21XX]; blob = &qla_fw_blobs[FW_ISP21XX];
} else if (IS_QLA2200(ha)) { } else if (IS_QLA2200(ha)) {
blob = &qla_fw_blobs[FW_ISP22XX]; blob = &qla_fw_blobs[FW_ISP22XX];
} else if (IS_QLA2300(ha) || IS_QLA2312(ha)) { } else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
blob = &qla_fw_blobs[FW_ISP2300]; blob = &qla_fw_blobs[FW_ISP2300];
} else if (IS_QLA2322(ha)) { } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
blob = &qla_fw_blobs[FW_ISP2322]; blob = &qla_fw_blobs[FW_ISP2322];
} else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
blob = &qla_fw_blobs[FW_ISP63XX];
} else if (IS_QLA24XX(ha)) {
blob = &qla_fw_blobs[FW_ISP24XX]; blob = &qla_fw_blobs[FW_ISP24XX];
} }
@ -2667,6 +2688,10 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, }, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432,
PCI_ANY_ID, PCI_ANY_ID, }, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0 }, { 0 },
}; };
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);

Просмотреть файл

@ -1191,11 +1191,6 @@ qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
return status; return status;
} }
#define IS_OEM_001(ha) \
((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322 && \
(ha)->pdev->subsystem_vendor == 0x1028 && \
(ha)->pdev->subsystem_device == 0x0170)
/** /**
* qla2x00_program_flash_address() - Programs a flash address * qla2x00_program_flash_address() - Programs a flash address
* @ha: HA context * @ha: HA context
@ -1354,7 +1349,7 @@ qla2x00_resume_hba(struct scsi_qla_host *ha)
/* Resume HBA. */ /* Resume HBA. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
up(ha->dpc_wait); qla2xxx_wake_dpc(ha);
qla2x00_wait_for_hba_online(ha); qla2x00_wait_for_hba_online(ha);
scsi_unblock_requests(ha->host); scsi_unblock_requests(ha->host);
} }
@ -1652,7 +1647,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
/* Resume HBA -- RISC reset needed. */ /* Resume HBA -- RISC reset needed. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
up(ha->dpc_wait); qla2xxx_wake_dpc(ha);
qla2x00_wait_for_hba_online(ha); qla2x00_wait_for_hba_online(ha);
scsi_unblock_requests(ha->host); scsi_unblock_requests(ha->host);

Просмотреть файл

@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = MV_USE_Q_DEPTH, .can_queue = MV_USE_Q_DEPTH,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -229,7 +229,6 @@ static struct scsi_host_template nv_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -288,7 +288,6 @@ static struct scsi_host_template k2_sata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -75,7 +75,6 @@ static struct scsi_host_template uli_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Просмотреть файл

@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше