1
0
Fork 0

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
  ...
hifive-unleashed-5.1
Linus Torvalds 2006-03-22 10:47:24 -08:00
commit 2152f85366
132 changed files with 35523 additions and 42706 deletions

View File

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

View File

@ -536,6 +536,28 @@ void bus_rescan_devices(struct bus_type * bus)
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)
{

View File

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

View File

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

View File

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

View File

@ -3,38 +3,11 @@
* *
* Copyright 2003 LSI Logic Corporation. All rights reserved. *
* *
* This file is confidential and a trade secret of LSI Logic. The *
* receipt of or possession of this file does not convey any rights to *
* reproduce or disclose its contents or to manufacture, use, or sell *
* anything it may describe, in whole, or in part, without the specific *
* written consent of LSI Logic Corporation. *
* Description *
* ------------ *
* This include file contains SAS firmware interface IOC Log Info codes *
* *
***************************************************************************
*
* 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
@ -57,6 +30,8 @@
#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)
#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)
#define IOC_LOGINFO_ORIGINATOR_MASK (0x0F000000)
/****************************************************************************/
/* LOGINFO_CODE defines */
/****************************************************************************/
@ -78,11 +53,27 @@
#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
#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 */
/****************************************************************************/
#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_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
@ -97,6 +88,7 @@
#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
#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_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
#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_NO_OWNER (0x000F0700) /* No Owner Found */
#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
#define PL_LOGINFO_CODE_RESET (0x00110000)
#define PL_LOGINFO_CODE_ABORT (0x00120000)
#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */
#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */
#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
#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_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_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
#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_SATA_LINK_DOWN (0x00000D00)
#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_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_WRITE_ERROR (0x00200002) /* 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_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* 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_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */
#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 (0x00200040) /* Encl Mgmt services not available for this WWID */
#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */
#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 (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_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_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_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */
#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */
#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */
#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_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */
#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense 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 */
/****************************************************************************/

View File

@ -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_spi_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 */
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);
if (results != evHandlers) {
/* 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));
}
@ -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) {
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));
} 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));
}
@ -1120,65 +1121,6 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
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.
@ -1482,7 +1424,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
*/
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
": WARNING - %s did not initialize properly! (%d)\n",
ioc->name, r);
@ -1629,7 +1572,6 @@ mpt_resume(struct pci_dev *pdev)
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state;
int recovery_state;
int ii;
printk(MYIOC_s_INFO_FMT
"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);
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
"pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
ioc->name,
@ -4938,7 +4872,7 @@ done_and_free:
return rc;
}
int
static int
mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
{
IOCPage3_t *pIoc3;
@ -5146,13 +5080,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
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));
return 0;
}
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->ChainOffset = 0;
@ -5907,24 +5841,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break;
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
{
char buf[50];
u8 id = (u8)(evData0);
u8 ReasonCode = (u8)(evData0 >> 16);
switch (ReasonCode) {
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;
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;
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;
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;
default:
ds = "SAS Device Status Change: Unknown";
sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
break;
}
ds = buf;
break;
}
case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@ -5940,11 +5877,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
ds = "Persistent Table Full";
break;
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;
}
case MPI_EVENT_SAS_DISCOVERY_ERROR:
ds = "SAS Discovery Error";
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...
@ -5989,12 +6012,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
}
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,
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);
for (ii = 0; ii < evDataLen; 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--) {
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));
r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
handlers++;
@ -6065,10 +6088,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
* If needed, send (a single) EventAck.
*/
if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
devtprintk((MYIOC_s_WARN_FMT
devtverboseprintk((MYIOC_s_WARN_FMT
"EventAck required\n",ioc->name));
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));
}
}
@ -6205,8 +6228,8 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
"Abort", /* 12h */
"IO Not Yet Executed", /* 13h */
"IO Executed", /* 14h */
NULL, /* 15h */
NULL, /* 16h */
"Persistant Reservation Out Not Affiliation Owner", /* 15h */
"Open Transmit DMA Abort", /* 16h */
NULL, /* 17h */
NULL, /* 18h */
NULL, /* 19h */
@ -6431,11 +6454,9 @@ EXPORT_SYMBOL(mpt_stm_index);
EXPORT_SYMBOL(mpt_HardResetHandler);
EXPORT_SYMBOL(mpt_config);
EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
EXPORT_SYMBOL(mpt_alt_ioc_wait);
EXPORT_SYMBOL(mptbase_GetFcPortPage0);

View File

@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.03.07"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07"
#define MPT_LINUX_VERSION_COMMON "3.03.08"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.08"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS
* VirtDevice - FC LUN device or SCSI target device
*/
typedef struct _VirtTarget {
struct scsi_target *starget;
u8 tflags;
u8 ioc_id;
u8 target_id;
@ -343,14 +344,10 @@ typedef struct _VirtTarget {
u8 type; /* byte 0 of Inquiry data */
u32 num_luns;
u32 luns[8]; /* Max LUNs is 256 */
u8 inq_data[8];
} VirtTarget;
typedef struct _VirtDevice {
VirtTarget *vtarget;
u8 ioc_id;
u8 bus_id;
u8 target_id;
VirtTarget *vtarget;
u8 configured_lun;
u32 lun;
} VirtDevice;
@ -364,6 +361,7 @@ typedef struct _VirtDevice {
#define MPT_TARGET_FLAGS_Q_YES 0x08
#define MPT_TARGET_FLAGS_VALID_56 0x10
#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40
/*
* /proc/mpt interface
@ -447,13 +445,6 @@ typedef struct _mpt_ioctl_events {
* Substructure to store SCSI specific configuration page data
*/
/* 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_ALL_IDS 0x02 /* WriteSDP1 to all IDS */
/* #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 */
dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */
int IocPg4Sz; /* IOCPage4 size */
u8 dvStatus[MPT_MAX_SCSI_DEVICES];
u8 minSyncFactor; /* 0xFF if async */
u8 maxSyncOffset; /* 0 if async */
u8 maxBusWidth; /* 0 if narrow, 1 if wide */
@ -474,13 +464,11 @@ typedef struct _SpiCfgData {
u8 sdp0version; /* SDP0 version */
u8 sdp0length; /* SDP0 length */
u8 dvScheduled; /* 1 if scheduled */
u8 forceDv; /* 1 to force DV scheduling */
u8 noQas; /* Disable QAS for this adapter */
u8 Saf_Te; /* 1 to force all Processors as
* SAF-TE if Inquiry data length
* 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 rsvd[1];
}SpiCfgData;
@ -631,6 +619,10 @@ typedef struct _MPT_ADAPTER
struct net_device *netdev;
struct list_head sas_topology;
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;
int num_ports;
struct work_struct mptscsih_persistTask;
@ -728,12 +720,18 @@ typedef struct _mpt_sge {
#define dhsprintk(x)
#endif
#ifdef MPT_DEBUG_EVENTS
#if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS)
#define devtprintk(x) printk x
#else
#define devtprintk(x)
#endif
#ifdef MPT_DEBUG_VERBOSE_EVENTS
#define devtverboseprintk(x) printk x
#else
#define devtverboseprintk(x)
#endif
#ifdef MPT_DEBUG_RESET
#define drsprintk(x) printk x
#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_free_fw_memory(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_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
/*
* Public data decl's...

View File

@ -140,7 +140,7 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
* Event Handler function
*/
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 ) {
ioc->aen_event_read_flag=1;
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);
return 1;
}
@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
ioc->aen_event_read_flag=1;
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);
}
return 1;
@ -2968,7 +2968,7 @@ static int __init mptctl_init(void)
}
if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
devtverboseprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}

View File

@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
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,
.show_host_node_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;
}
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
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) {
vtarget->target_id = pg0->CurrentTargetID;
vtarget->bus_id = pg0->CurrentBus;
starget_for_each_device(ri->starget,
vtarget,mptfc_remap_sdev);
}
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, "
"rport tid %d, tmo %d\n",
ioc->name,
oc->sh->host_no,
ioc->sh->host_no,
pg0->PortIdentifier,
pg0->WWNN,
pg0->WWPN,
@ -514,7 +494,7 @@ mptfc_target_alloc(struct scsi_target *starget)
* Return non-zero if allocation fails.
* Init memory once per LUN.
*/
int
static int
mptfc_slave_alloc(struct scsi_device *sdev)
{
MPT_SCSI_HOST *hd;
@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev)
}
vdev->vtarget = vtarget;
vdev->ioc_id = hd->ioc->id;
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);
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
"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
"CurrentTargetID %d, %x %llx %llx\n",
ioc->name,
hd->ioc->name,
sdev->host->host_no,
vtarget->num_luns,
sdev->id, ri->pg0.CurrentTargetID,
ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
}
#endif
return 0;
}
@ -941,7 +924,7 @@ mptfc_init(void)
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
devtverboseprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -60,16 +60,6 @@
#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
* 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 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_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);

View File

@ -56,12 +56,15 @@
#include <linux/reboot.h> /* notifier code */
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/raid_class.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "mptbase.h"
#include "mptscsih.h"
@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/* 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;
module_param(mpt_saf_te, int, 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_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 mptspiTaskCtx = -1;
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 = {
.module = THIS_MODULE,
.proc_name = "mptspi",
@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = {
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.target_alloc = mptscsih_target_alloc,
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_alloc = mptspi_target_alloc,
.slave_alloc = mptspi_slave_alloc,
.slave_configure = mptspi_slave_configure,
.target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.slave_destroy = mptspi_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = {
.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
@ -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_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;
/* Required entry.
@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* indicates a device exists.
* 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) {
error = -ENOMEM;
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;
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;
ddvprintk((MYIOC_s_INFO_FMT
"saf_te %x mpt_pq_filter %x\n",
ioc->name,
mpt_saf_te,
mpt_pq_filter));
#endif
ioc->spi_data.forceDv = 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);
hd->scandv_wait_done = 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);
if(error) {
dprintk((KERN_ERR MYNAM
@ -423,15 +1046,18 @@ static struct pci_driver mptspi_driver = {
static int __init
mptspi_init(void)
{
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);
mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
devtverboseprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
@ -465,6 +1091,7 @@ mptspi_exit(void)
mpt_deregister(mptspiInternalCtx);
mpt_deregister(mptspiTaskCtx);
mpt_deregister(mptspiDoneCtx);
spi_release_transport(mptspi_transport_template);
}
module_init(mptspi_init);

View File

@ -57,6 +57,13 @@ struct i2o_exec_wait {
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 */
static struct i2o_class_id i2o_exec_class_id[] = {
{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
* 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;
struct i2o_controller *c = work->c;
kfree(work);
if (i2o_device_parse_lct(c) != -EAGAIN)
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);
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);
@ -418,8 +428,11 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
if (!work)
return -ENOMEM;
INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c);
queue_work(i2o_exec_driver.event_queue, work);
work->c = c;
INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified,
work);
queue_work(i2o_exec_driver.event_queue, &work->work);
return 1;
}

View File

@ -2,8 +2,9 @@
3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
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
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.004 - Add support for 9550SX controllers.
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>
@ -85,7 +88,7 @@
#include "3w-9xxx.h"
/* 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 unsigned int twa_device_extension_count;
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];
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];
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--;
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;
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;
}
aen = header->status_block.error;
aen = le16_to_cpu(header->status_block.error);
memset(event, 0, sizeof(TW_Event));
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';
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)
printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
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->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
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].length = TW_SECTOR_SIZE;
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 = cpu_to_le32(TW_SECTOR_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 */
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
memset(param, 0, TW_SECTOR_SIZE);
param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */
param->parameter_id = 0x3; /* SchedulerTime */
param->parameter_size_bytes = 4;
param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
param->parameter_size_bytes = cpu_to_le16(4);
/* Convert system time in UTC to local time seconds since last
Sunday 12:00AM */
do_gettimeofday(&utc);
local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
schedulertime = local_time - (3 * 86400);
schedulertime = schedulertime % 604800;
schedulertime = cpu_to_le32(schedulertime % 604800);
memcpy(param->data, &schedulertime, sizeof(u32));
@ -931,26 +934,19 @@ out:
/* This function will clear the pchip/response queue on 9550SX */
static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
{
u32 status_reg_value, response_que_value;
int count = 0, retval = 1;
u32 response_que_value = 0;
unsigned long before;
int retval = 1;
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
before = jiffies;
while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) {
response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) {
/* P-chip settle time */
msleep(500);
retval = 0;
if (time_after(jiffies, before + HZ * 30))
goto out;
}
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
count++;
}
if (count == TW_MAX_RESPONSE_DRAIN)
goto out;
/* P-chip settle time */
msleep(500);
retval = 0;
} else
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]);
/* 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 (print_host)
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->size = TW_COMMAND_SIZE;
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 */
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
memset(param, 0, TW_SECTOR_SIZE);
param->table_id = table_id | 0x8000;
param->parameter_id = parameter_id;
param->parameter_size_bytes = parameter_size_bytes;
param->table_id = cpu_to_le16(table_id | 0x8000);
param->parameter_id = cpu_to_le16(parameter_id);
param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
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].length = TW_SECTOR_SIZE;
command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value);
command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
/* Post the command packet to the board */
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->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
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;
/* Turn on 64-bit sgl support if we need to */
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) {
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
tw_initconnect->fw_srl = current_fw_srl;
tw_initconnect->fw_arch_id = current_fw_arch_id;
tw_initconnect->fw_branch = current_fw_branch;
tw_initconnect->fw_build = current_fw_build;
tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
} else
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");
} else {
if (set_features & TW_EXTENDED_INIT_CONNECT) {
*fw_on_ctlr_srl = tw_initconnect->fw_srl;
*fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id;
*fw_on_ctlr_branch = tw_initconnect->fw_branch;
*fw_on_ctlr_build = tw_initconnect->fw_build;
*init_connect_result = tw_initconnect->result;
*fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
*fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id);
*fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch);
*fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build);
*init_connect_result = le32_to_cpu(tw_initconnect->result);
}
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->request_id__lunl =
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].length = length;
newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
newcommand->sg_list[0].length = cpu_to_le32(length);
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 {
oldcommand = &full_command_packet->command.oldcommand;
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)) {
/* Load the sg list */
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
sgl->length = length;
sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
sgl->length = cpu_to_le32(length);
if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
oldcommand->size += 1;
@ -1828,10 +1826,10 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (srb) {
command_packet->unit = srb->device->id;
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 {
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;
}
@ -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 */
if (tw_dev->srb[request_id]->use_sg == 0) {
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].length = TW_MIN_SGL_LENGTH;
command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
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)
memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
} else {
@ -1850,12 +1848,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (buffaddr == 0)
goto out;
command_packet->sg_list[0].address = buffaddr;
command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen;
command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
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");
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);
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].length = TW_MIN_SGL_LENGTH;
command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
} else {
sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
if (sg_count == 0)
goto out;
for (i = 0; i < sg_count; i++) {
command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
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");
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 {
/* Internal cdb post */
for (i = 0; i < use_sg; i++) {
command_packet->sg_list[i].address = sglistarg[i].address;
command_packet->sg_list[i].length = sglistarg[i].length;
if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length);
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");
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) {
@ -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),
(char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE,
TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH));
le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
/* Now setup the interrupt handler */
retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);

View File

@ -2,8 +2,9 @@
3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
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
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_VALID_INTERRUPT 0x00DF0000
/* RESPONSE QUEUE BIT DEFINITIONS */
#define TW_RESPONSE_ID_MASK 0x00000FF0
/* PCI related defines */
#define TW_NUMDEVICES 1
#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_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
#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)
@ -614,13 +613,6 @@ typedef union TAG_TW_Response_Queue {
u32 value;
} TW_Response_Queue;
typedef struct TAG_TW_Info {
char *buffer;
int length;
int offset;
int position;
} TW_Info;
/* Compatibility information structure */
typedef struct TAG_TW_Compatibility_Info
{
@ -636,6 +628,8 @@ typedef struct TAG_TW_Compatibility_Info
unsigned short driver_build_low;
} TW_Compatibility_Info;
#pragma pack()
typedef struct TAG_TW_Device_Extension {
u32 __iomem *base_addr;
unsigned long *generic_buffer_virt[TW_Q_LENGTH];
@ -679,7 +673,5 @@ typedef struct TAG_TW_Device_Extension {
unsigned short working_build;
} TW_Device_Extension;
#pragma pack()
#endif /* _3W_9XXX_H */

View File

@ -238,14 +238,6 @@ static char *NCR_700_SBCL_to_phase[] = {
"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
* 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;
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;
}
XFERP = (period*4 * hostdata->sync_clock)/1000 - 4;
@ -1434,11 +1426,9 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
if(hostdata->fast &&
NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) {
memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg,
sizeof(NCR_700_SDTR_msg));
hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target);
hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target);
count += sizeof(NCR_700_SDTR_msg);
count += spi_populate_sync_msg(&hostdata->msgout[count],
spi_period(SCp->device->sdev_target),
spi_offset(SCp->device->sdev_target));
NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -997,7 +997,7 @@ struct aac_dev
int maximum_num_physicals;
int maximum_num_channels;
struct fsa_dev_info *fsa_dev;
pid_t thread_pid;
struct task_struct *thread;
int cardtype;
/*
@ -1017,7 +1017,6 @@ struct aac_dev
* AIF thread states
*/
u32 aif_thread;
struct completion aif_completion;
struct aac_adapter_info adapter_info;
struct aac_supplement_adapter_info supplement_adapter_info;
/* 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_command_normal(struct aac_queue * q);
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_fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);

View File

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

View File

@ -39,6 +39,7 @@
#include <linux/completion.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <asm/semaphore.h>
@ -1045,8 +1046,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
* 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 fib *fib, *newfib;
struct aac_fib_context *fibctx;
@ -1058,12 +1060,7 @@ int aac_command_thread(struct aac_dev * dev)
*/
if (dev->aif_thread)
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.
*/
@ -1266,13 +1263,12 @@ int aac_command_thread(struct aac_dev * dev)
spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
schedule();
if(signal_pending(current))
if (kthread_should_stop())
break;
set_current_state(TASK_INTERRUPTIBLE);
}
if (dev->queues)
remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
dev->aif_thread = 0;
complete_and_exit(&dev->aif_completion, 0);
return 0;
}

View File

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

View File

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

View File

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

View File

@ -978,9 +978,13 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
break;
}
case INVALID_SEQINT:
printf("%s: Invalid Sequencer interrupt occurred.\n",
printf("%s: Invalid Sequencer interrupt occurred, "
"resetting channel.\n",
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);
break;
case STATUS_OVERRUN:
@ -3762,11 +3766,8 @@ ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
{
if (offset == 0)
period = AHD_ASYNC_XFER_PERIOD;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN;
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_index += spi_populate_sync_msg(
ahd->msgout_buf + ahd->msgout_index, period, offset);
ahd->msgout_len += 5;
if (bootverbose) {
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,
u_int bus_width)
{
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR;
ahd->msgout_buf[ahd->msgout_index++] = bus_width;
ahd->msgout_index += spi_populate_width_msg(
ahd->msgout_buf + ahd->msgout_index, bus_width);
ahd->msgout_len += 4;
if (bootverbose) {
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;
if (offset == 0)
period = AHD_ASYNC_XFER_PERIOD;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN;
ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR;
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_index += spi_populate_ppr_msg(
ahd->msgout_buf + ahd->msgout_index, period, offset,
bus_width, ppr_options);
ahd->msgout_len += 8;
if (bootverbose) {
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_platform_flushwork(ahd);
ahd->flags &= ~AHD_ALL_INTERRUPTS;
}

View File

@ -373,8 +373,7 @@ static void ahd_linux_handle_scsi_status(struct ahd_softc *,
struct scb *);
static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
struct scsi_cmnd *cmd);
static void ahd_linux_sem_timeout(u_long arg);
static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
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_linux_device *dev = scsi_transport_device_data(cmd->device);
int rtn = SCSI_MLQUEUE_HOST_BUSY;
unsigned long flags;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
ahd_lock(ahd, &flags);
if (ahd->platform_data->qfrozen == 0) {
cmd->scsi_done = scsi_done;
cmd->result = CAM_REQ_INPROG << 16;
rtn = ahd_linux_run_command(ahd, dev, cmd);
cmd->scsi_done = scsi_done;
cmd->result = CAM_REQ_INPROG << 16;
rtn = ahd_linux_run_command(ahd, dev, cmd);
}
ahd_unlock(ahd, &flags);
return rtn;
}
@ -487,6 +481,7 @@ ahd_linux_target_alloc(struct scsi_target *starget)
{
struct ahd_softc *ahd =
*((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
struct seeprom_config *sc = ahd->seep_config;
unsigned long flags;
struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
struct ahd_linux_target *targ = scsi_transport_target_data(starget);
@ -502,18 +497,38 @@ ahd_linux_target_alloc(struct scsi_target *starget)
*ahd_targp = starget;
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,
starget->id, &tstate);
ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
CAM_LUN_WILDCARD, channel,
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_TRANS_GOAL, /*paused*/FALSE);
ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
@ -654,10 +669,9 @@ static int
ahd_linux_abort(struct scsi_cmnd *cmd)
{
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;
}
@ -667,12 +681,97 @@ ahd_linux_abort(struct scsi_cmnd *cmd)
static int
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);
if (error != 0)
printf("aic79xx_dev_reset returns 0x%x\n", error);
return error;
reset_scb = NULL;
paused = FALSE;
wait = FALSE;
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)
{
struct ahd_softc *ahd;
u_long s;
int found;
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",
ahd_name(ahd), cmd);
#endif
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
/*initiate reset*/TRUE);
ahd_unlock(ahd, &s);
if (bootverbose)
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 ***************************/
/*
* 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
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));
ahd->platform_data->irq = AHD_LINUX_NOIRQ;
ahd_lockinit(ahd);
init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
ahd->seltime = (aic79xx_seltime & 0x3) << 4;
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))) {
case AHD_DEV_Q_BASIC:
scsi_adjust_queue_depth(sdev,
MSG_SIMPLE_TASK,
dev->openings + dev->active);
scsi_set_tag_type(sdev, MSG_SIMPLE_TASK);
scsi_activate_tcq(sdev, dev->openings + dev->active);
break;
case AHD_DEV_Q_TAGGED:
scsi_adjust_queue_depth(sdev,
MSG_ORDERED_TASK,
dev->openings + dev->active);
scsi_set_tag_type(sdev, MSG_ORDERED_TASK);
scsi_activate_tcq(sdev, dev->openings + dev->active);
break;
default:
/*
@ -1362,9 +1402,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
* serially on the controller/device. This should
* remove some latency.
*/
scsi_adjust_queue_depth(sdev,
/*NON-TAGGED*/0,
/*queue depth*/2);
scsi_deactivate_tcq(sdev, 1);
break;
}
}
@ -1443,6 +1481,9 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
struct ahd_tmode_tstate *tstate;
u_int col_idx;
uint16_t mask;
unsigned long flags;
ahd_lock(ahd, &flags);
/*
* 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) {
ahd->flags |= AHD_RESOURCE_SHORTAGE;
ahd_unlock(ahd, &flags);
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) {
scb->flags |= SCB_AUTO_NEGOTIATE;
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) {
@ -1583,6 +1601,8 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
scb->flags |= SCB_ACTIVE;
ahd_queue_scb(ahd, scb);
ahd_unlock(ahd, &flags);
return 0;
}
@ -1603,12 +1623,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
return IRQ_RETVAL(ours);
}
void
ahd_platform_flushwork(struct ahd_softc *ahd)
{
}
void
ahd_send_async(struct ahd_softc *ahd, char channel,
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];
struct scsi_target *starget;
struct ahd_linux_target *targ;
struct info_str info;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
@ -1651,7 +1664,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
starget = ahd->platform_data->starget[target];
if (starget == NULL)
break;
targ = scsi_transport_target_data(starget);
target_ppr_options =
(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
|| ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
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;
up(&ahd->platform_data->eh_sem);
}
if (ahd->platform_data->eh_done)
complete(ahd->platform_data->eh_done);
}
ahd_free_scb(ahd, scb);
@ -1961,133 +1972,125 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
static void
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
* avoid the conversion so that the DV code has the
* full error information available when making
* state change decisions.
*/
{
uint32_t status;
u_int new_status;
status = ahd_cmd_get_transaction_status(cmd);
switch (status) {
case CAM_REQ_INPROG:
case CAM_REQ_CMP:
case CAM_SCSI_STATUS_ERROR:
new_status = DID_OK;
break;
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;
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;
status = ahd_cmd_get_transaction_status(cmd);
switch (status) {
case CAM_REQ_INPROG:
case CAM_REQ_CMP:
new_status = DID_OK;
break;
case CAM_AUTOSENSE_FAIL:
new_status = DID_ERROR;
/* Fallthrough */
case CAM_SCSI_STATUS_ERROR:
scsi_status = ahd_cmd_get_scsi_status(cmd);
switch(scsi_status) {
case SCSI_STATUS_CMD_TERMINATED:
case SCSI_STATUS_CHECK_COND:
if ((cmd->result >> 24) != DRIVER_SENSE) {
do_fallback = 1;
} else {
struct scsi_sense_data *sense;
sense = (struct scsi_sense_data *)
&cmd->sense_buffer;
if (sense->extra_len >= 5 &&
(sense->add_sense_code == 0x47
|| sense->add_sense_code == 0x48))
do_fallback = 1;
}
break;
default:
/* We should never get here */
new_status = DID_ERROR;
break;
}
ahd_cmd_set_transaction_status(cmd, new_status);
break;
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);
}
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
ahd_freeze_simq(struct ahd_softc *ahd)
{
unsigned long s;
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);
scsi_block_requests(ahd->platform_data->host);
}
void
ahd_release_simq(struct ahd_softc *ahd)
{
u_long s;
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);
scsi_unblock_requests(ahd->platform_data->host);
}
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_linux_device *dev;
@ -2102,7 +2105,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int paused;
int wait;
int disconnected;
int found;
ahd_mode_state saved_modes;
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;
scmd_printk(KERN_INFO, cmd,
"Attempting to queue a%s message:",
flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
"Attempting to queue an ABORT message:");
printf("CDB:");
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;
}
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) {
scmd_printk(KERN_INFO, cmd, "Command not found\n");
goto no_cmd;
@ -2195,25 +2183,17 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
ahd_dump_card_state(ahd);
disconnected = TRUE;
if (flag == SCB_ABORT) {
if (ahd_search_qinfifo(ahd, cmd->device->id,
cmd->device->channel + 'A',
cmd->device->lun,
pending_scb->hscb->tag,
ROLE_INITIATOR, CAM_REQ_ABORTED,
SEARCH_COMPLETE) > 0) {
printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
ahd_name(ahd), cmd->device->channel,
cmd->device->id, cmd->device->lun);
retval = SUCCESS;
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;
if (ahd_search_qinfifo(ahd, cmd->device->id,
cmd->device->channel + 'A',
cmd->device->lun,
pending_scb->hscb->tag,
ROLE_INITIATOR, CAM_REQ_ABORTED,
SEARCH_COMPLETE) > 0) {
printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
ahd_name(ahd), cmd->device->channel,
cmd->device->id, cmd->device->lun);
retval = SUCCESS;
goto done;
}
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);
saved_scbptr = ahd_get_scbptr(ahd);
active_scbptr = saved_scbptr;
if (disconnected && ((last_phase != P_BUSFREE) ||
(ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
struct scb *bus_scb;
bus_scb = ahd_lookup_scb(ahd, active_scbptr);
if (bus_scb == pending_scb)
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.
*/
saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
if (SCB_GET_TAG(pending_scb) == active_scbptr
|| (flag == SCB_DEVICE_RESET
&& SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
if (last_phase != P_BUSFREE
&& SCB_GET_TAG(pending_scb) == active_scbptr) {
/*
* We're active on the bus, so assert ATN
* and hope that the target responds.
*/
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, 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;
} 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) {
/*
* Actually re-queue this SCB in an attempt
* 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));
pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0;
@ -2344,30 +2304,29 @@ done:
if (paused)
ahd_unpause(ahd);
if (wait) {
struct timer_list timer;
int ret;
DECLARE_COMPLETION(done);
ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM;
ahd->platform_data->eh_done = &done;
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));
down(&ahd->platform_data->eh_sem);
printf("%s: Recovery code awake\n", ahd_name(ahd));
ret = del_timer_sync(&timer);
if (ret == 0) {
if (!wait_for_completion_timeout(&done, 5 * HZ)) {
ahd_lock(ahd, &flags);
ahd->platform_data->eh_done = NULL;
ahd_unlock(ahd, &flags);
printf("%s: Timer Expired (active %d)\n",
ahd_name(ahd), dev->active);
retval = FAILED;
}
printf("Recovery code awake\n");
} else
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)

View File

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

View File

@ -2461,11 +2461,8 @@ ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
{
if (offset == 0)
period = AHC_ASYNC_XFER_PERIOD;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN;
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_index += spi_populate_sync_msg(
ahc->msgout_buf + ahc->msgout_index, period, offset);
ahc->msgout_len += 5;
if (bootverbose) {
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,
u_int bus_width)
{
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR;
ahc->msgout_buf[ahc->msgout_index++] = bus_width;
ahc->msgout_index += spi_populate_width_msg(
ahc->msgout_buf + ahc->msgout_index, bus_width);
ahc->msgout_len += 4;
if (bootverbose) {
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)
period = AHC_ASYNC_XFER_PERIOD;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN;
ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR;
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_index += spi_populate_ppr_msg(
ahc->msgout_buf + ahc->msgout_index, period, offset,
bus_width, ppr_options);
ahc->msgout_len += 8;
if (bootverbose) {
printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "

View File

@ -373,7 +373,6 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *,
struct scb *);
static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
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_release_simq(struct ahc_softc *ahc);
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));
ahc->platform_data->irq = AHC_LINUX_NOIRQ;
ahc_lockinit(ahc);
init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
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
|| ahc_get_transaction_status(scb) == CAM_REQ_ABORTED)
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;
up(&ahc->platform_data->eh_sem);
}
if (ahc->platform_data->eh_done)
complete(ahc->platform_data->eh_done);
}
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);
}
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
ahc_linux_freeze_simq(struct ahc_softc *ahc)
{
@ -2355,25 +2336,21 @@ done:
if (paused)
ahc_unpause(ahc);
if (wait) {
struct timer_list timer;
int ret;
DECLARE_COMPLETION(done);
ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE;
ahc->platform_data->eh_done = &done;
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");
down(&ahc->platform_data->eh_sem);
printf("Recovery code awake\n");
ret = del_timer_sync(&timer);
if (ret == 0) {
if (!wait_for_completion_timeout(&done, 5 * HZ)) {
ahc_lock(ahc, &flags);
ahc->platform_data->eh_done = NULL;
ahc_unlock(ahc, &flags);
printf("Timer Expired\n");
retval = FAILED;
}
printf("Recovery code awake\n");
} else
ahc_unlock(ahc, &flags);
return (retval);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */
host_index = i;
if (!shpnt) {
len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n",
shpnt->host_no);
len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter");
return len;
}
max_pun = subsystem_maxid(host_index);

View File

@ -5830,6 +5830,109 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
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(..)
* @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);
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 = {
.name = IPR_NAME,
.id_table = ipr_pci_table,
.probe = ipr_probe,
.remove = ipr_remove,
.shutdown = ipr_shutdown,
.err_handler = &ipr_err_handler,
};
/**

View File

@ -1146,7 +1146,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
return (0);
}
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->scsi_done(SC);
return (0);

View File

@ -52,7 +52,6 @@ static volatile unsigned char cmd_buffer[16];
* via PIO.
*/
int jazz_esp_detect(struct scsi_host_template *tpnt);
static int jazz_esp_release(struct Scsi_Host *shost)
{
if (shost->irq)
@ -75,7 +74,7 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt)
* first assumption it is there:-)
*/
if (1) {
esp_dev = 0;
esp_dev = NULL;
esp = esp_allocate(tpnt, (void *) esp_dev);
/* 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;
/* Optional functions */
esp->dma_barrier = 0;
esp->dma_drain = 0;
esp->dma_invalidate = 0;
esp->dma_irq_entry = 0;
esp->dma_irq_exit = 0;
esp->dma_poll = 0;
esp->dma_reset = 0;
esp->dma_barrier = NULL;
esp->dma_drain = NULL;
esp->dma_invalidate = NULL;
esp->dma_irq_entry = NULL;
esp->dma_irq_exit = NULL;
esp->dma_poll = NULL;
esp->dma_reset = NULL;
esp->dma_led_off = &dma_led_off;
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
*
*/
esp->dregs = JAZZ_SCSI_DMA;
esp->dregs = (void *) JAZZ_SCSI_DMA;
/* ESP register base */
esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE);

View File

@ -4653,6 +4653,8 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
if (!host)
return NULL;
host->transportt = &ata_scsi_transport_template;
ap = (struct ata_port *) &host->hostdata[0];
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_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_timed_out);
EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release);

View File

@ -41,6 +41,7 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_transport.h>
#include <linux/libata.h>
#include <linux/hdreg.h>
#include <asm/uaccess.h>
@ -52,6 +53,7 @@
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
static struct ata_device *
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_LEN 12
@ -92,6 +94,14 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
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,
void (*done)(struct scsi_cmnd *))

View File

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

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -121,7 +121,9 @@ struct lpfc_stats {
uint32_t elsRcvLOGO;
uint32_t elsRcvPRLO;
uint32_t elsRcvPRLI;
uint32_t elsRcvRRQ;
uint32_t elsRcvLIRR;
uint32_t elsRcvRPS;
uint32_t elsRcvRPL;
uint32_t elsXmitFLOGI;
uint32_t elsXmitPLOGI;
uint32_t elsXmitPRLI;
@ -167,33 +169,35 @@ struct lpfc_sysfs_mbox {
};
struct lpfc_hba {
struct list_head hba_list; /* List of hbas/ports */
struct lpfc_sli sli;
struct lpfc_sli2_slim *slim2p;
dma_addr_t slim2p_mapping;
uint16_t pci_cfg_value;
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_INIT_MBX_CMDS 2 /* Initialize HBA with mbox commands */
#define LPFC_LINK_DOWN 3 /* HBA initialized, link is down */
#define LPFC_LINK_UP 4 /* Link is up - issue READ_LA */
#define LPFC_LOCAL_CFG_LINK 5 /* local NPORT Id configured */
#define LPFC_FLOGI 6 /* FLOGI sent to Fabric */
#define LPFC_FABRIC_CFG_LINK 7 /* Fabric assigned NPORT Id
#define LPFC_STATE_UNKNOWN 0 /* HBA state is unknown */
#define LPFC_WARM_START 1 /* HBA state after selective reset */
#define LPFC_INIT_START 2 /* Initial state after board reset */
#define LPFC_INIT_MBX_CMDS 3 /* Initialize HBA with mbox commands */
#define LPFC_LINK_DOWN 4 /* HBA initialized, link is down */
#define LPFC_LINK_UP 5 /* Link is up - issue READ_LA */
#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 */
#define LPFC_NS_REG 8 /* Register with NameServer */
#define LPFC_NS_QRY 9 /* Query NameServer for NPort ID list */
#define LPFC_BUILD_DISC_LIST 10 /* Build ADISC and PLOGI lists for
#define LPFC_NS_REG 9 /* Register with NameServer */
#define LPFC_NS_QRY 10 /* Query NameServer for NPort ID list */
#define LPFC_BUILD_DISC_LIST 11 /* Build ADISC and PLOGI lists for
* device authentication / discovery */
#define LPFC_DISC_AUTH 11 /* Processing ADISC list */
#define LPFC_CLEAR_LA 12 /* authentication cmplt - issue
#define LPFC_DISC_AUTH 12 /* Processing ADISC list */
#define LPFC_CLEAR_LA 13 /* authentication cmplt - issue
CLEAR_LA */
#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 */
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_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
#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 */
@ -289,8 +294,8 @@ struct lpfc_hba {
uint32_t cfg_link_speed;
uint32_t cfg_cr_delay;
uint32_t cfg_cr_count;
uint32_t cfg_multi_ring_support;
uint32_t cfg_fdmi_on;
uint32_t cfg_fcp_bind_method;
uint32_t cfg_discovery_threads;
uint32_t cfg_max_luns;
uint32_t cfg_poll;

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -79,7 +79,7 @@ static ssize_t
lpfc_serialnum_show(struct class_device *cdev, char *buf)
{
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);
}
@ -87,7 +87,7 @@ static ssize_t
lpfc_modeldesc_show(struct class_device *cdev, char *buf)
{
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);
}
@ -95,7 +95,7 @@ static ssize_t
lpfc_modelname_show(struct class_device *cdev, char *buf)
{
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);
}
@ -103,7 +103,7 @@ static ssize_t
lpfc_programtype_show(struct class_device *cdev, char *buf)
{
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);
}
@ -111,7 +111,7 @@ static ssize_t
lpfc_portnum_show(struct class_device *cdev, char *buf)
{
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);
}
@ -119,7 +119,7 @@ static ssize_t
lpfc_fwrev_show(struct class_device *cdev, char *buf)
{
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];
lpfc_decode_firmware_rev(phba, fwrev, 1);
return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
@ -130,7 +130,7 @@ lpfc_hdw_show(struct class_device *cdev, char *buf)
{
char hdw[9];
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_jedec_to_ascii(vp->rev.biuRev, 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)
{
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);
}
static ssize_t
lpfc_state_show(struct class_device *cdev, char *buf)
{
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;
switch (phba->hba_state) {
case LPFC_STATE_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN:
@ -194,7 +196,7 @@ static ssize_t
lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
{
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 +
phba->fc_unmap_cnt);
}
@ -203,7 +205,7 @@ lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
static int
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;
int mbxstatus = MBXERR_ERROR;
@ -235,7 +237,7 @@ static ssize_t
lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
{
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);
}
@ -243,7 +245,7 @@ static ssize_t
lpfc_board_online_show(struct class_device *cdev, char *buf)
{
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)
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)
{
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;
int val=0, status=0;
@ -278,11 +280,63 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
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
lpfc_poll_show(struct class_device *cdev, char *buf)
{
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);
}
@ -292,7 +346,7 @@ lpfc_poll_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[0];
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
uint32_t creg_val;
uint32_t old_val;
int val=0;
@ -349,7 +403,7 @@ static ssize_t \
lpfc_##attr##_show(struct class_device *cdev, char *buf) \
{ \
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;\
val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n",\
@ -361,7 +415,7 @@ static ssize_t \
lpfc_##attr##_show(struct class_device *cdev, char *buf) \
{ \
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;\
val = phba->cfg_##attr;\
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) \
{ \
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;\
if (!isdigit(buf[0]))\
return -EINVAL;\
@ -480,6 +534,8 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
NULL);
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
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;
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,
"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.
# 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
# 0x0 = attempt loop mode then point-to-point
# 0x01 = internal loopback mode
# 0x02 = attempt point-to-point mode only
# 0x04 = attempt loop mode only
# 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].
# 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
@ -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
# 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");
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");
/*
# 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.
# 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
# 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");
/*
@ -649,6 +724,7 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_drvr_version,
&class_device_attr_lpfc_log_verbose,
&class_device_attr_lpfc_lun_queue_depth,
&class_device_attr_lpfc_hba_queue_depth,
&class_device_attr_lpfc_nodev_tmo,
&class_device_attr_lpfc_fcp_class,
&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_cr_delay,
&class_device_attr_lpfc_cr_count,
&class_device_attr_lpfc_multi_ring_support,
&class_device_attr_lpfc_fdmi_on,
&class_device_attr_lpfc_max_luns,
&class_device_attr_nport_evt_cnt,
&class_device_attr_management_version,
&class_device_attr_board_online,
&class_device_attr_board_mode,
&class_device_attr_lpfc_poll,
&class_device_attr_lpfc_poll_tmo,
NULL,
@ -674,7 +752,7 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
size_t buf_off;
struct Scsi_Host *host = 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;
if ((off + count) > FF_REG_AREA_SIZE)
return -ERANGE;
@ -707,7 +785,7 @@ sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
uint32_t * tmp_ptr;
struct Scsi_Host *host = 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;
if (off > FF_REG_AREA_SIZE)
return -ERANGE;
@ -762,7 +840,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct Scsi_Host * host =
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;
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);
if (!mbox)
return -ENOMEM;
memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
}
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 =
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;
int rc;
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_DOWN_LOAD:
case MBX_UPDATE_CFG:
case MBX_KILL_BOARD:
case MBX_LOAD_AREA:
case MBX_LOAD_EXP_ROM:
case MBX_BEACON:
case MBX_DEL_LD_ENTRY:
break;
case MBX_READ_SPARM64:
case MBX_READ_LA:
@ -990,7 +1071,7 @@ lpfc_free_sysfs_attr(struct lpfc_hba *phba)
static void
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 */
fc_host_port_id(shost) = phba->fc_myDID;
}
@ -998,7 +1079,7 @@ lpfc_get_host_port_id(struct Scsi_Host *shost)
static void
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);
@ -1023,7 +1104,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
static void
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);
@ -1031,6 +1112,8 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
else {
switch (phba->hba_state) {
case LPFC_STATE_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN:
@ -1064,7 +1147,7 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
static void
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);
@ -1091,7 +1174,7 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
static void
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;
spin_lock_irq(shost->host_lock);
@ -1113,7 +1196,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
static struct fc_host_statistics *
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 fc_host_statistics *hs = &phba->link_stats;
LPFC_MBOXQ_t *pmboxq;
@ -1203,7 +1286,7 @@ static void
lpfc_get_starget_port_id(struct scsi_target *starget)
{
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;
struct lpfc_nodelist *ndlp = NULL;
@ -1224,7 +1307,7 @@ static void
lpfc_get_starget_node_name(struct scsi_target *starget)
{
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;
struct lpfc_nodelist *ndlp = NULL;
@ -1245,7 +1328,7 @@ static void
lpfc_get_starget_port_name(struct scsi_target *starget)
{
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;
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_cr_delay_init(phba, lpfc_cr_delay);
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_fcp_class_init(phba, lpfc_fcp_class);
lpfc_use_adisc_init(phba, lpfc_use_adisc);
@ -1411,5 +1495,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
default:
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;
}

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* 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 *);
int lpfc_read_sparam(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);
int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_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_ns_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);
void lpfc_set_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 *);
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_rscn_node(struct lpfc_hba *, uint32_t);
void lpfc_disc_list_loopmap(struct lpfc_hba *);
void lpfc_disc_start(struct lpfc_hba *);
void lpfc_disc_flush_list(struct lpfc_hba *);
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);
@ -68,19 +64,13 @@ int lpfc_do_work(void *);
int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
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 *,
struct serv_parm *, uint32_t);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
int);
int lpfc_els_abort_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_adisc(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 *);
int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
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_handler(struct lpfc_nodelist *);
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_post(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 *);
int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, 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_offline(struct lpfc_hba *);
int lpfc_sli_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_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_config_ring(struct lpfc_hba *, int, 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 *);
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 *);
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);
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_down(struct lpfc_hba *);
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_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,
uint32_t did);
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t);
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,
uint32_t timeout);

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* 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.Type = FC_COMMON_TRANSPORT_ULP;
if (!tmo)
tmo = (2 * phba->fc_ratov) + 1;
if (!tmo) {
/* FC spec states we need 3 * ratov for CT requests */
tmo = (3 * phba->fc_ratov);
}
icmd->ulpTimeout = tmo;
icmd->ulpBdeCount = 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 *) mp->virt;
struct lpfc_nodelist *ndlp = NULL;
struct lpfc_nodelist *next_ndlp;
struct lpfc_dmabuf *mlast, *next_mp;
uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
uint32_t Did;
@ -389,8 +392,36 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
nsout1:
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) {
/*
* 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);
spin_lock_irq(phba->host->host_lock);
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;
if (CTrsp->CommandResponse.bits.CmdRsp ==
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,
(uint32_t) (irsp->un.genreq64.bdl.bdeSize));
} 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->ad.bits.AttrType = be16_to_cpu(SUPPORTED_SPEED);
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;
else if (FC_JEDEC_ID(vp->rev.biuRev) == HELIOS_JEDEC_ID)
ae->un.SupportSpeed = HBA_PORTSPEED_4GBIT;
else if ((FC_JEDEC_ID(vp->rev.biuRev) ==
CENTAUR_2G_JEDEC_ID)
|| (FC_JEDEC_ID(vp->rev.biuRev) ==
PEGASUS_JEDEC_ID)
|| (FC_JEDEC_ID(vp->rev.biuRev) ==
THOR_JEDEC_ID))
ae->un.SupportSpeed = HBA_PORTSPEED_2GBIT;
else
ae->un.SupportSpeed = HBA_PORTSPEED_1GBIT;
if (phba->lmt & LMT_8Gb)
ae->un.SupportSpeed |= HBA_PORTSPEED_8GBIT;
if (phba->lmt & LMT_4Gb)
ae->un.SupportSpeed |= HBA_PORTSPEED_4GBIT;
if (phba->lmt & LMT_2Gb)
ae->un.SupportSpeed |= HBA_PORTSPEED_2GBIT;
if (phba->lmt & LMT_1Gb)
ae->un.SupportSpeed |= HBA_PORTSPEED_1GBIT;
pab->ab.EntryCnt++;
size += FOURBYTES + 4;
@ -1130,11 +1166,6 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
{
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);
if (ndlp) {
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);
}
}
spin_unlock_irq(phba->host->host_lock);
return;
}

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* *
@ -28,18 +28,24 @@
* 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 */
struct lpfc_work_evt {
struct list_head evt_listp;
void * evt_arg1;
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 list_head nlp_listp;
@ -56,6 +62,7 @@ struct lpfc_nodelist {
uint16_t nlp_rpi;
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_sid; /* scsi id */
#define NLP_NO_SID 0xffff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* *
@ -454,10 +454,13 @@ struct serv_parm { /* Structure is in Big Endian format */
#define ELS_CMD_ADISC 0x52000000
#define ELS_CMD_FARP 0x54000000
#define ELS_CMD_FARPR 0x55000000
#define ELS_CMD_RPS 0x56000000
#define ELS_CMD_RPL 0x57000000
#define ELS_CMD_FAN 0x60000000
#define ELS_CMD_RSCN 0x61040000
#define ELS_CMD_SCR 0x62000000
#define ELS_CMD_RNID 0x78000000
#define ELS_CMD_LIRR 0x7A000000
#else /* __LITTLE_ENDIAN_BITFIELD */
#define ELS_CMD_MASK 0xffff
#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_FARP 0x54
#define ELS_CMD_FARPR 0x55
#define ELS_CMD_RPS 0x56
#define ELS_CMD_RPL 0x57
#define ELS_CMD_FAN 0x60
#define ELS_CMD_RSCN 0x0461
#define ELS_CMD_SCR 0x62
#define ELS_CMD_RNID 0x78
#define ELS_CMD_LIRR 0x7A
#endif
/*
@ -758,12 +764,40 @@ typedef struct _RNID { /* Structure is in Big Endian format */
} un;
} RNID;
typedef struct _RRQ { /* Structure is in Big Endian format */
uint32_t SID;
uint16_t Oxid;
uint16_t Rxid;
uint8_t resv[32]; /* optional association hdr */
} RRQ;
typedef struct _RPS { /* Structure is in Big Endian format */
union {
uint32_t portNum;
struct lpfc_name portName;
} un;
} 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 */
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 */
FAN fan; /* Payload for FAN */
SCR scr; /* Payload for SCR/ACC */
RRQ rrq; /* Payload for RRQ */
RNID rnid; /* Payload for RNID */
uint8_t pad[128 - 4]; /* Pad out to payload of 128 bytes */
} un;
@ -1200,7 +1233,9 @@ typedef struct { /* FireFly BIU registers */
#define MBX_SET_MASK 0x20
#define MBX_SET_SLIM 0x21
#define MBX_UNREG_D_ID 0x23
#define MBX_KILL_BOARD 0x24
#define MBX_CONFIG_FARP 0x25
#define MBX_BEACON 0x2A
#define MBX_LOAD_AREA 0x81
#define MBX_RUN_BIU_DIAG64 0x84
@ -1676,13 +1711,13 @@ typedef struct {
uint32_t rttov;
uint32_t altov;
uint32_t lmt;
#define LMT_RESERVED 0x0 /* Not used */
#define LMT_266_10bit 0x1 /* 265.625 Mbaud 10 bit iface */
#define LMT_532_10bit 0x2 /* 531.25 Mbaud 10 bit iface */
#define LMT_1063_20bit 0x3 /* 1062.5 Mbaud 20 bit iface */
#define LMT_1063_10bit 0x4 /* 1062.5 Mbaud 10 bit iface */
#define LMT_2125_10bit 0x8 /* 2125 Mbaud 10 bit iface */
#define LMT_4250_10bit 0x40 /* 4250 Mbaud 10 bit iface */
#define LMT_RESERVED 0x000 /* Not used */
#define LMT_1Gb 0x004
#define LMT_2Gb 0x008
#define LMT_4Gb 0x040
#define LMT_8Gb 0x080
#define LMT_10Gb 0x100
uint32_t rsvd2;
uint32_t rsvd3;

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -42,7 +42,7 @@
#include "lpfc_crtn.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 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],
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 */
pmb->context2 = kmalloc(DMP_RSP_SIZE, GFP_KERNEL);
if (!pmb->context2)
@ -182,16 +179,15 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
"mbxCmd x%x DUMP VPD, mbxStatus x%x\n",
phba->brd_no,
mb->mbxCommand, mb->mbxStatus);
kfree(lpfc_vpd_data);
lpfc_vpd_data = NULL;
break;
mb->un.varDmp.word_cnt = 0;
}
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,
mb->un.varDmp.word_cnt);
offset += mb->un.varDmp.word_cnt;
} while (mb->un.varDmp.word_cnt);
lpfc_parse_vpd(phba, lpfc_vpd_data);
} while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
kfree(lpfc_vpd_data);
out_free_context2:
@ -327,13 +323,22 @@ lpfc_config_port_post(struct lpfc_hba * phba)
mb->un.varRdConfig.max_xri + 1;
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 */
if ((((phba->lmt & LMT_4250_10bit) != LMT_4250_10bit) &&
(phba->cfg_link_speed > LINK_SPEED_2G)) ||
(((phba->lmt & LMT_2125_10bit) != LMT_2125_10bit) &&
(phba->cfg_link_speed > LINK_SPEED_1G))) {
/* Reset link speed to auto. 1G/2GB HBA cfg'd for 4G */
/* Get the default values for Model Name and Description */
lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
if ((phba->cfg_link_speed > LINK_SPEED_10G)
|| ((phba->cfg_link_speed == LINK_SPEED_1G)
&& !(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,
KERN_WARNING,
LOG_LINK_EVENT,
@ -462,6 +467,40 @@ lpfc_hba_down_prep(struct lpfc_hba * phba)
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 */
@ -476,20 +515,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
struct lpfc_sli *psli = &phba->sli;
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) {
/* Re-establishing Link */
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]);
spin_lock_irq(phba->host->host_lock);
phba->fc_flag |= FC_ESTABLISH_LINK;
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(phba->host->host_lock);
/*
@ -516,6 +542,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
* attempt to restart it.
*/
lpfc_offline(phba);
lpfc_sli_brdrestart(phba);
if (lpfc_online(phba) == 0) { /* Initialize the HBA */
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
return;
@ -531,8 +558,10 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
phba->brd_no, phba->work_hs,
phba->work_status[0], phba->work_status[1]);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
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
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;
uint32_t Length;
@ -642,9 +671,10 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd)
phba->brd_no,
(uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
(uint32_t) vpd[3]);
do {
while (!finished && (index < (len - 4))) {
switch (vpd[index]) {
case 0x82:
case 0x91:
index += 1;
lenlo = vpd[index];
index += 1;
@ -660,7 +690,8 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd)
lenhi = vpd[index];
index += 1;
Length = ((((unsigned short)lenhi) << 8) + lenlo);
if (Length > len - index)
Length = len - index;
while (Length > 0) {
/* Look for Serial Number */
if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) {
@ -754,7 +785,7 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd)
index ++;
break;
}
} while (!finished && (index < 108));
}
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;
uint16_t dev_id = phba->pcidev->device;
uint16_t dev_subid = phba->pcidev->subsystem_device;
uint8_t hdrtype = phba->pcidev->hdr_type;
char *model_str = "";
uint8_t hdrtype;
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;
switch (dev_id) {
case PCI_DEVICE_ID_FIREFLY:
model_str = "LP6000 1Gb PCI";
m = (typeof(m)){"LP6000", max_speed, "", "PCI"};
break;
case PCI_DEVICE_ID_SUPERFLY:
if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
model_str = "LP7000 1Gb PCI";
m = (typeof(m)){"LP7000", max_speed, "", "PCI"};
else
model_str = "LP7000E 1Gb PCI";
m = (typeof(m)){"LP7000E", max_speed, "", "PCI"};
break;
case PCI_DEVICE_ID_DRAGONFLY:
model_str = "LP8000 1Gb PCI";
m = (typeof(m)){"LP8000", max_speed, "", "PCI"};
break;
case PCI_DEVICE_ID_CENTAUR:
if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
model_str = "LP9002 2Gb PCI";
m = (typeof(m)){"LP9002", max_speed, "", "PCI"};
else
model_str = "LP9000 1Gb PCI";
m = (typeof(m)){"LP9000", max_speed, "", "PCI"};
break;
case PCI_DEVICE_ID_RFLY:
model_str = "LP952 2Gb PCI";
m = (typeof(m)){"LP952", max_speed, "", "PCI"};
break;
case PCI_DEVICE_ID_PEGASUS:
model_str = "LP9802 2Gb PCI-X";
m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"};
break;
case PCI_DEVICE_ID_THOR:
if (hdrtype == 0x80)
model_str = "LP10000DC 2Gb 2-port PCI-X";
m = (typeof(m)){"LP10000DC",
max_speed, ports, "PCI-X"};
else
model_str = "LP10000 2Gb PCI-X";
m = (typeof(m)){"LP10000",
max_speed, ports, "PCI-X"};
break;
case PCI_DEVICE_ID_VIPER:
model_str = "LPX1000 10Gb PCI-X";
m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"};
break;
case PCI_DEVICE_ID_PFLY:
model_str = "LP982 2Gb PCI-X";
m = (typeof(m)){"LP982", max_speed, "", "PCI-X"};
break;
case PCI_DEVICE_ID_TFLY:
if (hdrtype == 0x80)
model_str = "LP1050DC 2Gb 2-port PCI-X";
m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"};
else
model_str = "LP1050 2Gb PCI-X";
m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"};
break;
case PCI_DEVICE_ID_HELIOS:
if (hdrtype == 0x80)
model_str = "LP11002 4Gb 2-port PCI-X2";
m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"};
else
model_str = "LP11000 4Gb PCI-X2";
m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"};
break;
case PCI_DEVICE_ID_HELIOS_SCSP:
model_str = "LP11000-SP 4Gb PCI-X2";
m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"};
break;
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;
case PCI_DEVICE_ID_NEPTUNE:
if (hdrtype == 0x80)
model_str = "LPe1002 4Gb 2-port";
m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"};
else
model_str = "LPe1000 4Gb PCIe";
m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_NEPTUNE_SCSP:
model_str = "LPe1000-SP 4Gb PCIe";
m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_NEPTUNE_DCSP:
model_str = "LPe1002-SP 4Gb 2-port PCIe";
m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_BMID:
model_str = "LP1150 4Gb PCI-X2";
m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"};
break;
case PCI_DEVICE_ID_BSMB:
model_str = "LP111 4Gb PCI-X2";
m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"};
break;
case PCI_DEVICE_ID_ZEPHYR:
if (hdrtype == 0x80)
model_str = "LPe11002 4Gb 2-port PCIe";
m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"};
else
model_str = "LPe11000 4Gb PCIe";
m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_ZEPHYR_SCSP:
model_str = "LPe11000-SP 4Gb PCIe";
m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_ZEPHYR_DCSP:
model_str = "LPe11002-SP 4Gb 2-port PCIe";
m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_ZMID:
model_str = "LPe1150 4Gb PCIe";
m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_ZSMB:
model_str = "LPe111 4Gb PCIe";
m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"};
break;
case PCI_DEVICE_ID_LP101:
model_str = "LP101 2Gb PCI-X";
m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"};
break;
case PCI_DEVICE_ID_LP10000S:
model_str = "LP10000-S 2Gb PCI";
m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"};
break;
case PCI_DEVICE_ID_LP11000S:
case PCI_DEVICE_ID_LPE11000S:
switch (dev_subid) {
case PCI_SUBSYSTEM_ID_LP11000S:
model_str = "LP11002-S 4Gb PCI-X2";
m = (typeof(m)){"LP11000-S", max_speed,
ports, "PCI-X2"};
break;
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;
case PCI_SUBSYSTEM_ID_LPE11000S:
model_str = "LPe11002-S 4Gb PCIe";
m = (typeof(m)){"LPe11000-S", max_speed,
ports, "PCIe"};
break;
case PCI_SUBSYSTEM_ID_LPE11002S:
model_str = "LPe11002-S 4Gb 2-port PCIe";
m = (typeof(m)){"LPe11002-S", max_speed,
ports, "PCIe"};
break;
case PCI_SUBSYSTEM_ID_LPE11010S:
model_str = "LPe11010-S 4Gb 10-port PCIe";
m = (typeof(m)){"LPe11010-S", max_speed,
"10-port ", "PCIe"};
break;
default:
m = (typeof(m)){ 0 };
break;
}
break;
default:
m = (typeof(m)){ 0 };
break;
}
if (mdp)
sscanf(model_str, "%s", mdp);
if (descp)
sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str);
if (mdp && mdp[0] == '\0')
snprintf(mdp, 79,"%s", m.name);
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);
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);
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);
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 */
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);
host->transportt = lpfc_transport_template;
host->hostdata[0] = (unsigned long)phba;
pci_set_drvdata(pdev, host);
error = scsi_add_host(host, &pdev->dev);
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));
fc_host_supported_speeds(host) = 0;
switch (FC_JEDEC_ID(phba->vpd.rev.biuRev)) {
case VIPER_JEDEC_ID:
if (phba->lmt & LMT_10Gb)
fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT;
break;
case HELIOS_JEDEC_ID:
if (phba->lmt & LMT_4Gb)
fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT;
/* Fall through */
case CENTAUR_2G_JEDEC_ID:
case PEGASUS_JEDEC_ID:
case THOR_JEDEC_ID:
if (phba->lmt & LMT_2Gb)
fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT;
/* Fall through */
default:
fc_host_supported_speeds(host) = FC_PORTSPEED_1GBIT;
}
if (phba->lmt & LMT_1Gb)
fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT;
fc_host_maxframe_size(host) =
((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
@ -1643,6 +1716,7 @@ out_free_slim:
phba->slim2p_mapping);
out_iounmap:
iounmap(phba->ctrl_regs_memmap_p);
out_iounmap_slim:
iounmap(phba->slim_memmap_p);
out_idr_remove:
idr_remove(&lpfc_hba_index, phba->brd_no);
@ -1660,7 +1734,7 @@ static void __devexit
lpfc_pci_remove_one(struct pci_dev *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;
lpfc_free_sysfs_attr(phba);
@ -1681,6 +1755,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
* the HBA.
*/
lpfc_sli_hba_down(phba);
lpfc_sli_brdrestart(phba);
/* Release the irq reservation */
free_irq(phba->pcidev->irq, phba);

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* 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_FAILOVER;
break;
case FLAGS_LOCAL_LB:
mb->un.varInitLnk.link_flags = FLAGS_LOCAL_LB;
break;
}
/* NEW_FEATURE
@ -336,6 +339,23 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
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 */
/* mailbox command */
@ -619,6 +639,17 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
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
lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
{

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* 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;
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) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((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
* 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;
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 *
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;
static char lpfcinfobuf[384];
@ -803,7 +808,7 @@ static int
lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
{
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_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
@ -877,7 +882,7 @@ static int
lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
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_iocbq *iocb;
struct lpfc_iocbq *abtsiocb;
@ -981,7 +986,7 @@ static int
lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{
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_iocbq *iocbq, *iocbqrsp;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
@ -1094,7 +1099,7 @@ static int
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
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;
int match;
int ret = FAILED, i, err_count = 0;
@ -1195,7 +1200,7 @@ out:
static int
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 fc_rport *rport = starget_to_rport(scsi_target(sdev));
uint32_t total = 0, i;
@ -1251,7 +1256,7 @@ lpfc_slave_alloc(struct scsi_device *sdev)
static int
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);
if (sdev->tagged_supported)

View File

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

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* 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_SLIM:
case MBX_UNREG_D_ID:
case MBX_KILL_BOARD:
case MBX_CONFIG_FARP:
case MBX_BEACON:
case MBX_LOAD_AREA:
case MBX_RUN_BIU_DIAG64:
case MBX_CONFIG_PORT:
@ -764,7 +766,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/* unSolicited Responses */
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;
} else {
/* 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)
&& (pring->prt[i].
type == Type)) {
(pring->prt[i].lpfc_sli_rcv_unsol_event)
(phba, pring, saveq);
if (pring->prt[i].lpfc_sli_rcv_unsol_event)
(pring->prt[i].lpfc_sli_rcv_unsol_event)
(phba, pring, saveq);
match = 1;
break;
}
@ -1149,12 +1154,17 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
spin_unlock_irqrestore(
phba->host->host_lock, iflag);
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
spin_lock_irqsave(phba->host->host_lock,
iflag);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
} else {
spin_unlock_irqrestore(
phba->host->host_lock, iflag);
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
spin_lock_irqsave(phba->host->host_lock,
iflag);
}
}
break;
default:
@ -1512,98 +1522,240 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return errcnt;
}
/******************************************************************************
* lpfc_sli_send_reset
*
* 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)
int
lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
{
MAILBOX_t *swpmb;
volatile uint32_t word0;
void __iomem *to_slim;
unsigned long flags = 0;
uint32_t status;
int i = 0;
int retval = 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;
swpmb = (MAILBOX_t *) & word0;
swpmb->mbxCommand = MBX_RESTART;
swpmb->mbxHc = 1;
if (i <= 5)
msleep(10);
else if (i <= 10)
msleep(500);
else
msleep(2500);
to_slim = phba->MBslimaddr;
writel(*(uint32_t *) swpmb, to_slim);
readl(to_slim); /* flush */
/* Only skip post after fc_ffinit is completed */
if (skip_post) {
word0 = 1; /* This is really setting up word1 */
} else {
word0 = 0; /* This is really setting up word1 */
if (i == 15) {
phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
lpfc_sli_brdrestart(phba);
}
/* Read the HBA Host Status Register */
status = readl(phba->HSregaddr);
}
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 */
pci_read_config_word(phba->pcidev, PCI_COMMAND, &phba->pci_cfg_value);
pci_write_config_word(phba->pcidev, PCI_COMMAND,
(phba->pci_cfg_value &
~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
/* Check to see if any errors occurred during init */
if ((status & HS_FFERM) || (i >= 20)) {
phba->hba_state = LPFC_HBA_ERROR;
retval = 1;
}
writel(HC_INITFF, phba->HCregaddr);
phba->hba_state = LPFC_INIT_START;
spin_unlock_irqrestore(phba->host->host_lock, flags);
return 0;
return retval;
}
static int
lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
#define BARRIER_TEST_PATTERN (0xdeadbeef)
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;
uint16_t cfg_value;
int i;
struct lpfc_dmabuf *mp, *next_mp;
unsigned long flags = 0;
lpfc_sli_send_reset(phba, skip_post);
mdelay(1);
psli = &phba->sli;
spin_lock_irqsave(phba->host->host_lock, flags);
/* Risk the write on flush case ie no delay after the readl */
readl(phba->HCregaddr); /* flush */
/* Now toggle INITFF bit set by lpfc_sli_send_reset */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
/* Restore PCI cmd register */
pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->pci_cfg_value);
/* Reset HBA */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
phba->hba_state, psli->sli_flag);
/* perform board reset */
phba->fc_eventTag = 0;
phba->fc_myDID = 0;
phba->fc_prevDID = Mask_DID;
phba->fc_prevDID = 0;
/* Reset HBA */
lpfc_printf_log(phba,
KERN_INFO,
LOG_SLI,
"%d:0325 Reset HBA Data: x%x x%x x%x\n",
phba->brd_no,
phba->hba_state,
phba->sli.sli_flag,
skip_post);
psli->sli_flag = 0;
/* Turn off parity checking and serr during the physical reset */
pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
pci_write_config_word(phba->pcidev, PCI_COMMAND,
(cfg_value &
~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
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 */
for (i = 0; i < phba->sli.num_rings; i++) {
pring = &phba->sli.ring[i];
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
pring->flag = 0;
pring->rspidx = 0;
pring->next_cmdidx = 0;
@ -1611,27 +1763,64 @@ lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
pring->cmdidx = 0;
pring->missbufcnt = 0;
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
if (skip_post) {
mdelay(100);
phba->hba_state = LPFC_WARM_START;
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 {
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);
}
spin_lock_irqsave(phba->host->host_lock, flags);
/* 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]);
lpfc_hba_down_post(phba);
return 0;
}
@ -1691,7 +1880,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
}
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 */
status = readl(phba->HSregaddr);
@ -1735,8 +1925,8 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
}
while (resetcount < 2 && !done) {
phba->hba_state = 0;
lpfc_sli_brdreset(phba, 0);
phba->hba_state = LPFC_STATE_UNKNOWN;
lpfc_sli_brdrestart(phba);
msleep(2500);
rc = lpfc_sli_chipset_init(phba);
if (rc)
@ -1920,6 +2110,21 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
mb = &pmbox->mb;
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) {
/* Polling for a mbox command when another one is already active
* 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 (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;
spin_unlock_irqrestore(phba->host->host_lock,
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);
/* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP)
|| !(ha_copy & HA_MBATT)) {
while (((word0 & OWN_CHIP) == OWN_CHIP) ||
(!(ha_copy & HA_MBATT) &&
(phba->hba_state > LPFC_WARM_START))) {
if (i++ >= 100) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
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)))
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)) &&
(nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
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;
}
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
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",
phba->brd_no, totiocb, MAX_SLI2_IOCB);
}
if (phba->cfg_multi_ring_support == 2)
lpfc_extra_ring_setup(phba);
return 0;
}
@ -2465,15 +2695,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
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;
}
@ -2877,11 +3098,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
pmboxq->context1 = NULL;
/* if schedule_timeout returns 0, we timed out and were not
woken up */
if (timeleft == 0) {
if ((timeleft == 0) || signal_pending(current))
retval = MBX_TIMEOUT;
} else {
else
retval = MBX_SUCCESS;
}
}
@ -2987,13 +3207,7 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
/* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
/*
* Reseting the HBA is the only reliable way
* to shutdown interrupt when there is a
* ERROR.
*/
lpfc_sli_send_reset(phba, phba->hba_state);
phba->stopped = 1;
}
spin_lock(phba->host->host_lock);

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* 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_HIGH_PRIORITY 2 /* High priority command */
#define IOCB_SUCCESS 0
#define IOCB_BUSY 1
@ -200,8 +199,6 @@ struct lpfc_sli {
struct timer_list mbox_tmo; /* Hold clk to timeout active mbox
cmd */
uint32_t *MBhostaddr; /* virtual address for mbox cmds */
#define LPFC_IOCBQ_LOOKUP_INCREMENT 1024
struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */
size_t iocbq_lookup_len; /* current lengs of the array */

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* 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. *
* www.emulex.com *
* *
@ -18,12 +18,12 @@
* 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_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
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"

View File

@ -772,8 +772,6 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
goto out_return_cmd;
cmd->scmd = scmd;
scmd->SCp.ptr = (char *)cmd;
scmd->SCp.sent_command = jiffies;
/*
* 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)
return -ENXIO;
/*
* The RAID firmware may require extended timeouts.
*/
if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
sdev->timeout = 90 * HZ;
return 0;
}
@ -875,23 +879,6 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
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
*/
@ -962,7 +949,6 @@ static struct scsi_host_template megasas_template = {
.eh_device_reset_handler = megasas_reset_device,
.eh_bus_reset_handler = megasas_reset_bus_host,
.eh_host_reset_handler = megasas_reset_bus_host,
.eh_timed_out = megasas_reset_timer,
.use_clustering = ENABLE_CLUSTERING,
};

View File

@ -69,6 +69,10 @@
** Low PCI traffic for command handling when on-chip RAM is present.
** 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)
/*==========================================================
**
** Include files
**
**==========================================================
*/
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@ -121,6 +118,7 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
@ -128,10 +126,8 @@
#include "ncr53c8xx.h"
#define NAME53C "ncr53c"
#define NAME53C8XX "ncr53c8xx"
/*==========================================================
**
** 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.
** Wait immediately for the selection to complete.
** (2.5x behaves so)
@ -2162,7 +2158,7 @@ static struct script script0 __initdata = {
/*
** Selection complete.
** 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,
offsetof (struct dsb, smsg),
@ -2191,7 +2187,7 @@ static struct script script0 __initdata = {
/*
** Initialize the msgout buffer with a NOOP message.
*/
SCR_LOAD_REG (scratcha, M_NOOP),
SCR_LOAD_REG (scratcha, NOP),
0,
SCR_COPY (1),
RADDR (scratcha),
@ -2343,21 +2339,21 @@ static struct script script0 __initdata = {
/*
** Handle this message.
*/
SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
SCR_JUMP ^ IFTRUE (DATA (COMMAND_COMPLETE)),
PADDR (complete),
SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
SCR_JUMP ^ IFTRUE (DATA (DISCONNECT)),
PADDR (disconnect),
SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
SCR_JUMP ^ IFTRUE (DATA (SAVE_POINTERS)),
PADDR (save_dp),
SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
SCR_JUMP ^ IFTRUE (DATA (RESTORE_POINTERS)),
PADDR (restore_dp),
SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
SCR_JUMP ^ IFTRUE (DATA (EXTENDED_MESSAGE)),
PADDRH (msg_extended),
SCR_JUMP ^ IFTRUE (DATA (M_NOOP)),
SCR_JUMP ^ IFTRUE (DATA (NOP)),
PADDR (clrack),
SCR_JUMP ^ IFTRUE (DATA (M_REJECT)),
SCR_JUMP ^ IFTRUE (DATA (MESSAGE_REJECT)),
PADDRH (msg_reject),
SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)),
SCR_JUMP ^ IFTRUE (DATA (IGNORE_WIDE_RESIDUE)),
PADDRH (msg_ign_residue),
/*
** Rest of the messages left as
@ -2372,7 +2368,7 @@ static struct script script0 __initdata = {
*/
SCR_INT,
SIR_REJECT_SENT,
SCR_LOAD_REG (scratcha, M_REJECT),
SCR_LOAD_REG (scratcha, MESSAGE_REJECT),
0,
}/*-------------------------< SETMSG >----------------------*/,{
SCR_COPY (1),
@ -2564,7 +2560,7 @@ static struct script script0 __initdata = {
/*
** If it was no ABORT message ...
*/
SCR_JUMP ^ IFTRUE (DATA (M_ABORT)),
SCR_JUMP ^ IFTRUE (DATA (ABORT_TASK_SET)),
PADDRH (msg_out_abort),
/*
** ... wait for the next phase
@ -2576,7 +2572,7 @@ static struct script script0 __initdata = {
/*
** ... else clear the message ...
*/
SCR_LOAD_REG (scratcha, M_NOOP),
SCR_LOAD_REG (scratcha, NOP),
0,
SCR_COPY (4),
RADDR (scratcha),
@ -3035,7 +3031,7 @@ static struct scripth scripth0 __initdata = {
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[2]),
SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)),
SCR_JUMP ^ IFTRUE (DATA (EXTENDED_WDTR)),
PADDRH (msg_wdtr),
/*
** unknown extended message
@ -3069,7 +3065,7 @@ static struct scripth scripth0 __initdata = {
}/*-------------------------< SEND_WDTR >----------------*/,{
/*
** Send the M_X_WIDE_REQ
** Send the EXTENDED_WDTR
*/
SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
NADDR (msgout),
@ -3089,7 +3085,7 @@ static struct scripth scripth0 __initdata = {
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[2]),
SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)),
SCR_JUMP ^ IFTRUE (DATA (EXTENDED_SDTR)),
PADDRH (msg_sdtr),
/*
** unknown extended message
@ -3124,7 +3120,7 @@ static struct scripth scripth0 __initdata = {
}/*-------------------------< SEND_SDTR >-------------*/,{
/*
** Send the M_X_SYNC_REQ
** Send the EXTENDED_SDTR
*/
SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
NADDR (msgout),
@ -3202,10 +3198,10 @@ static struct scripth scripth0 __initdata = {
}/*-------------------------< RESET >----------------------*/,{
/*
** Send a M_RESET message if bad IDENTIFY
** Send a TARGET_RESET message if bad IDENTIFY
** received on reselection.
*/
SCR_LOAD_REG (scratcha, M_ABORT_TAG),
SCR_LOAD_REG (scratcha, ABORT_TASK),
0,
SCR_JUMP,
PADDRH (abort_resel),
@ -3213,7 +3209,7 @@ static struct scripth scripth0 __initdata = {
/*
** Abort a wrong tag received on reselection.
*/
SCR_LOAD_REG (scratcha, M_ABORT_TAG),
SCR_LOAD_REG (scratcha, ABORT_TASK),
0,
SCR_JUMP,
PADDRH (abort_resel),
@ -3221,7 +3217,7 @@ static struct scripth scripth0 __initdata = {
/*
** Abort a reselection when no active CCB.
*/
SCR_LOAD_REG (scratcha, M_ABORT),
SCR_LOAD_REG (scratcha, ABORT_TASK_SET),
0,
}/*-------------------------< ABORT_RESEL >----------------*/,{
SCR_COPY (1),
@ -3333,7 +3329,7 @@ static struct scripth scripth0 __initdata = {
** Read the message, since we got it directly
** from the SCSI BUS data lines.
** 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,
SIR_RESEL_BAD_LUN,
@ -3345,7 +3341,7 @@ static struct scripth scripth0 __initdata = {
/*
** We donnot have a task for that I_T_L.
** Signal problem to C code for logging the event.
** Send a M_ABORT message.
** Send an ABORT_TASK_SET message.
*/
SCR_INT,
SIR_RESEL_BAD_I_T_L,
@ -3355,7 +3351,7 @@ static struct scripth scripth0 __initdata = {
/*
** We donnot have a task that matches the tag.
** Signal problem to C code for logging the event.
** Send a M_ABORTTAG message.
** Send an ABORT_TASK message.
*/
SCR_INT,
SIR_RESEL_BAD_I_T_L_Q,
@ -3366,7 +3362,7 @@ static struct scripth scripth0 __initdata = {
** We donnot know the target that reselected us.
** Grab the first message if any (IDENTIFY).
** Signal problem to C code for logging the event.
** M_RESET message.
** TARGET_RESET message.
*/
SCR_INT,
SIR_RESEL_BAD_TARGET,
@ -4109,17 +4105,11 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
switch (nego) {
case NS_SYNC:
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 3;
msgptr[msglen++] = M_X_SYNC_REQ;
msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0;
msgptr[msglen++] = tp->maxoffs;
msglen += spi_populate_sync_msg(msgptr + msglen,
tp->maxoffs ? tp->minsync : 0, tp->maxoffs);
break;
case NS_WIDE:
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 2;
msgptr[msglen++] = M_X_WIDE_REQ;
msgptr[msglen++] = tp->usrwide;
msglen += spi_populate_width_msg(msgptr + msglen, tp->usrwide);
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 ||
(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->tags_smap) {
order = M_ORDERED_TAG;
order = ORDERED_QUEUE_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
PRINT_ADDR(cmd,
"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 0x28: /* READ_BIG (10) */
case 0xa8: /* READ_HUGE (12) */
order = M_SIMPLE_TAG;
order = SIMPLE_QUEUE_TAG;
break;
default:
order = M_ORDERED_TAG;
order = ORDERED_QUEUE_TAG;
}
}
msgptr[msglen++] = order;
@ -6229,9 +6219,9 @@ static int ncr_int_par (struct ncb *np)
if (!(dbc & 0xc0000000))
phase = (dbc >> 24) & 7;
if (phase == 7)
msg = M_PARITY;
msg = MSG_PARITY_ERROR;
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 ...
** ("Everything you've always wanted to know about transfer mode
** negotiation")
**
** We try to negotiate sync and wide transfer only after
** a successful inquire command. We look at byte 7 of the
@ -6896,8 +6888,8 @@ void ncr_int_sir (struct ncb *np)
break;
}
np->msgin [0] = M_NOOP;
np->msgout[0] = M_NOOP;
np->msgin [0] = NOP;
np->msgout[0] = NOP;
cp->nego_status = 0;
break;
@ -6991,12 +6983,7 @@ void ncr_int_sir (struct ncb *np)
spi_offset(starget) = ofs;
ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 3;
np->msgout[2] = M_X_SYNC_REQ;
np->msgout[3] = per;
np->msgout[4] = ofs;
spi_populate_sync_msg(np->msgout, per, ofs);
cp->nego_status = NS_SYNC;
if (DEBUG_FLAGS & DEBUG_NEGO) {
@ -7007,7 +6994,7 @@ void ncr_int_sir (struct ncb *np)
OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
return;
}
np->msgin [0] = M_NOOP;
np->msgin [0] = NOP;
break;
@ -7082,13 +7069,9 @@ void ncr_int_sir (struct ncb *np)
spi_width(starget) = wide;
ncr_setwide(np, cp, wide, 1);
spi_populate_width_msg(np->msgout, wide);
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 2;
np->msgout[2] = M_X_WIDE_REQ;
np->msgout[3] = wide;
np->msgin [0] = M_NOOP;
np->msgin [0] = NOP;
cp->nego_status = NS_WIDE;
@ -7107,12 +7090,12 @@ void ncr_int_sir (struct ncb *np)
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]);
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;
/*--------------------------------------------------------------------
@ -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");
break;
#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",
(unsigned) INL (nc_temp),
(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.
** THERE IS NO SAVE DEFAULT VALUE.
** THERE IS NO SAFE DEFAULT VALUE.
**
** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock.
** 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 */
#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG
np->order = M_SIMPLE_TAG;
np->order = SIMPLE_QUEUE_TAG;
#endif
spin_unlock_irqrestore(&np->smp_lock, flags);

View File

@ -56,8 +56,10 @@
#include <linux/config.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.
*/
#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
*/

File diff suppressed because it is too large Load Diff

View File

@ -518,7 +518,8 @@ struct osst_buffer {
int writing;
int midlevel_result;
int syscall_result;
struct scsi_request *last_SRpnt;
struct osst_request *last_SRpnt;
struct st_cmdstatus cmdstat;
unsigned char *b_data;
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 */
@ -626,6 +627,15 @@ struct osst_tape {
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 */
#define OS_WRITE_DATA 0
#define OS_WRITE_EOD 1

View File

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

View File

@ -10,14 +10,13 @@ config SCSI_QLA_FC
By default, firmware for the ISP parts will be loaded
via the Firmware Loader interface.
ISP Firmware Filename
---------- -----------------
21xx ql2100_fw.bin
22xx ql2200_fw.bin
2300, 2312 ql2300_fw.bin
2322 ql2322_fw.bin
6312, 6322 ql6312_fw.bin
24xx ql2400_fw.bin
ISP Firmware Filename
---------- -----------------
21xx ql2100_fw.bin
22xx ql2200_fw.bin
2300, 2312, 6312 ql2300_fw.bin
2322, 6322 ql2322_fw.bin
24xx ql2400_fw.bin
Upon request, the driver caches the firmware image until
the driver is unloaded.
@ -51,23 +50,17 @@ config SCSI_QLA22XX
This driver supports the QLogic 22xx (ISP2200) host adapter family.
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
---help---
This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
adapter family.
This driver supports the QLogic 2300 (ISP2300, ISP2312 and
ISP6312) host adapter family.
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
---help---
This driver supports the QLogic 2322 (ISP2322) host adapter family.
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
This driver supports the QLogic 2322 (ISP2322 and ISP6322) host
adapter family.
config SCSI_QLA24XX

View File

@ -9,12 +9,10 @@ qla2100-y := ql2100.o ql2100_fw.o
qla2200-y := ql2200.o ql2200_fw.o
qla2300-y := ql2300.o ql2300_fw.o
qla2322-y := ql2322.o ql2322_fw.o
qla6312-y := ql6312.o ql6312_fw.o
qla2400-y := ql2400.o ql2400_fw.o
obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.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

View File

@ -40,6 +40,11 @@ static struct qla_board_info qla_board_tbl[] = {
.isp_name = "ISP2312",
.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[] = {
@ -57,6 +62,13 @@ static struct pci_device_id qla2300_pci_tbl[] = {
.subdevice = PCI_ANY_ID,
.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},
};
MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl);

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,11 @@ static struct qla_board_info qla_board_tbl[] = {
.isp_name = "ISP2322",
.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[] = {
@ -62,6 +67,13 @@ static struct pci_device_id qla2322_pci_tbl[] = {
.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, qla2322_pci_tbl);

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,18 @@ static struct qla_board_info qla_board_tbl[] = {
.fw_info = qla_fw_tbl,
.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[] = {
@ -66,6 +78,21 @@ static struct pci_device_id qla24xx_pci_tbl[] = {
.subdevice = PCI_ANY_ID,
.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},
};
MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl);

File diff suppressed because it is too large Load Diff

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
ha->host_no);
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,
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) {
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;
else {
dump_size = FW_DUMP_SIZE_1M;
@ -138,7 +138,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
return 0;
/* Checksum NVRAM. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
uint32_t *iter;
uint32_t chksum;
@ -308,6 +308,61 @@ static struct bin_attribute sysfs_optrom_ctl_attr = {
.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
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_ctl_attr);
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
}
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_ctl_attr);
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
if (ha->beacon_blink_led == 1)
ha->isp_ops.beacon_off(ha);
@ -450,9 +507,6 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
int len = 0;
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:
len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n");
break;
@ -470,20 +524,16 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
int val = 0;
uint16_t zio_mode;
if (!IS_ZIO_SUPPORTED(ha))
return -ENOTSUPP;
if (sscanf(buf, "%d", &val) != 1)
return -EINVAL;
switch (val) {
case 1:
zio_mode = QLA_ZIO_MODE_5;
break;
case 2:
if (val)
zio_mode = QLA_ZIO_MODE_6;
break;
default:
else
zio_mode = QLA_ZIO_DISABLED;
break;
}
/* Update per-hba values and queue a reset. */
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;
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,
sizeof(stat_buf) / 4, mb_stat);
} else {

View File

@ -31,82 +31,6 @@
#include <scsi/scsi_cmnd.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,
* 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 QLA_ZIO_MODE_5 (BIT_2 | BIT_0)
#define QLA_ZIO_MODE_6 (BIT_2 | BIT_1)
#define QLA_ZIO_DISABLED 0
#define QLA_ZIO_DEFAULT_TIMER 2
@ -2300,6 +2223,47 @@ typedef struct scsi_qla_host {
#define SWITCH_FOUND BIT_3
#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. */
#define SRB_MIN_REQ 128
mempool_t *srb_mempool;
@ -2381,6 +2345,8 @@ typedef struct scsi_qla_host {
/* NVRAM configuration data */
uint16_t nvram_size;
uint16_t nvram_base;
uint16_t vpd_size;
uint16_t vpd_base;
uint16_t loop_reset_delay;
uint8_t retry_count;
@ -2414,11 +2380,7 @@ typedef struct scsi_qla_host {
struct sns_cmd_pkt *sns_cmd;
dma_addr_t sns_cmd_dma;
pid_t dpc_pid;
int dpc_should_die;
struct completion dpc_inited;
struct completion dpc_exited;
struct semaphore *dpc_wait;
struct task_struct *dpc_thread;
uint8_t dpc_active; /* DPC routine is active */
/* Timeout timers. */

View File

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

View File

@ -759,7 +759,7 @@ struct device_reg_24xx {
#define FA_NVRAM_FUNC0_ADDR 0x80
#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_VPD1_ADDR 0x100
/*

View File

@ -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_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);
@ -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 void qla2xxx_wake_dpc(scsi_qla_host_t *);
/*
* 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);
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
qla2x00_fabric_logout(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t);

View File

@ -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",
ha->host_no, routine, ms_pkt->entry_status));
} else {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
comp_status =
((struct ct_entry_24xx *)ms_pkt)->comp_status;
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;
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->dseg_0_len = ct_pkt->cmd_byte_count;
} else {
@ -1529,9 +1529,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
eiter->len = __constant_cpu_to_be16(4 + 4);
if (IS_QLA25XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(8);
else if (IS_QLA24XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(4);
else if (IS_QLA23XX(ha))
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->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
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) ha->init_cb->frame_payload_size;
eiter->a.max_frame_size = cpu_to_be32(max_frame_size);

View File

@ -387,7 +387,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha)
/* Verify checksum of loaded RISC code. */
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);
}
@ -727,6 +727,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha)
DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n",
ha->host_no));
ha->device_type |= DT_ISP2200A;
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))
return;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
qla2x00_alloc_fw_dump(ha);
/* 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)
ha->fw_options[2] |= BIT_12;
/* Detect ISP6312. */
if (IS_QLA6312(ha))
ha->fw_options[2] |= BIT_13;
/* Update firmware 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);
if (index < QLA_MODEL_NAMES) {
strcpy(ha->model_number,
qla2x00_model_name[index]);
qla2x00_model_name[index * 2]);
ha->model_desc =
qla2x00_model_desc[index];
qla2x00_model_name[index * 2 + 1];
} else {
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);
ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
"delay (%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100));
@ -2122,7 +2129,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
LIST_HEAD(new_fcports);
/* 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;
else
loop_id = SNS_FL_PORT;
@ -2148,7 +2155,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
qla2x00_fdmi_register(ha);
/* 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;
else
loop_id = SIMPLE_NAME_SERVER;
@ -2639,7 +2646,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
if (ql2xprocessrscn &&
!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
!IS_QLA6312(ha) && !IS_QLA6322(ha) &&
!IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
!IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
ha->flags.init_done) {
/* Handle port RSCN via asyncronous IOCBs */
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
*/
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;
uint16_t mb[MAILBOX_REGISTER_COUNT];
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) {
/* Interrogate mailbox registers for any errors */
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);
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) {
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
/*
* Disable SRAM, Instruction RAM and GP RAM
* parity.
@ -3145,7 +3152,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) {
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
/* Enable proper parity */
if (IS_QLA2300(ha))
/* SRAM parity */
@ -3258,8 +3265,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
/* Determine NVRAM starting address. */
ha->nvram_size = sizeof(struct nvram_24xx);
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->vpd_base = FA_NVRAM_VPD1_ADDR;
}
/* Get NVRAM data and calculate checksum. */
dptr = (uint32_t *)nv;
@ -3368,7 +3379,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
index = (ha->pdev->subsystem_device & 0xff);
if (index < QLA_MODEL_NAMES)
ha->model_desc = qla2x00_model_desc[index];
ha->model_desc = qla2x00_model_name[index * 2 + 1];
} else
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));
ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) {
ha->zio_mode = QLA_ZIO_MODE_6;
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
"(%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100));

View File

@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
static inline int
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 > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||

View File

@ -466,7 +466,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
mrk->entry_type = MARKER_TYPE;
mrk->modifier = type;
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->nport_handle = cpu_to_le16(loop_id);
mrk24->lun[1] = LSB(lun);
@ -519,7 +519,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
for (timer = HZ; timer; timer--) {
if ((req_cnt + 2) >= ha->req_q_cnt) {
/* 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(
&reg->isp24.req_q_out);
else
@ -593,7 +593,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha)
ha->request_ring_ptr++;
/* 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);
RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
} else {

View File

@ -343,7 +343,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
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) {
qla_printk(KERN_ERR, ha,
"Unrecoverable Hardware Error: adapter "
@ -521,7 +521,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
*/
if (ql2xprocessrscn &&
!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->operating_mode == P2P && mb[1] != 0) ||
(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",
ha->host_no));
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
qla24xx_process_response_queue(ha);
else
qla2x00_process_response_queue(ha);
@ -810,7 +810,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
sts = (sts_entry_t *) 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);
scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
} 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");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
if (ha->dpc_wait && !ha->dpc_active)
up(ha->dpc_wait);
qla2xxx_wake_dpc(ha);
return;
}
cp = sp->cmd;
@ -862,7 +860,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
fcport = sp->fcport;
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);
rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
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. */
if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
/* 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;
if (rsp_info_len > 3 && rsp_info[3]) {
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:
cp->result = DID_BUS_BUSY << 16;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d:%d): TIMEOUT status detected "
"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. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
host_to_fcp_swap(pkt->data, sizeof(pkt->data));
memcpy(sp->request_sense_ptr, pkt->data, 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");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
if (ha->dpc_wait && !ha->dpc_active)
up(ha->dpc_wait);
qla2xxx_wake_dpc(ha);
}
}

View File

@ -91,7 +91,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Load mailbox registers. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
else
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);
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
else
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__,
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);
else
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;
uint32_t ictrl;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
} else {
@ -284,9 +284,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
"Mailbox command timeout occured. Scheduling ISP "
"abort.\n");
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
if (ha->dpc_wait && !ha->dpc_active)
up(ha->dpc_wait);
qla2xxx_wake_dpc(ha);
} else if (!abort_active) {
/* call abort directly since we are in the DPC thread */
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));
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[8] = MSW(risc_addr);
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[7] = LSW(MSD(req_dma));
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[5] = LSW(risc_code_size);
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->out_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[2] = LSW(risc_addr);
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__,
ha->host_no, rval, mcp->mb[0]));
} else {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
__func__, ha->host_no, mcp->mb[1]);)
} else {
@ -565,7 +563,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
mcp->mb[3] = fwopts[3];
mcp->out_mb = MBX_3|MBX_2|MBX_1|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;
} else {
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->out_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[2] = LSW(risc_addr);
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) {
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]));)
} else {
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. */
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;
@ -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));
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[2] = MSW(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->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|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[10] = opt;
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->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);
mcp->flags = MBX_DMA_IN;
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)
goto gpd_error_out;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
pd24 = (struct port_database_24xx *) pd;
/* 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);)
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
mcp->mb[1] = BIT_0;
mcp->mb[2] = 0xff;
@ -1633,20 +1631,25 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
*
*/
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)
{
int rval;
mbx_cmd_t 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);)
mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
if (HAS_EXTENDED_IDS(ha))
mcp->mb[1] = loop_id;
mcp->mb[1] = fcport->loop_id;
else
mcp->mb[1] = loop_id << 8;
mcp->mb[1] = fcport->loop_id << 8;
mcp->mb[2] = opt;
mcp->out_mb = MBX_2|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->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[3] = LSW(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->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|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[4] = 0;
mcp->mb[10] = 0;
@ -2326,7 +2329,7 @@ qla2x00_system_error(scsi_qla_host_t *ha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
return QLA_FUNCTION_FAILED;
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[1] = BIT_0;
mcp->mb[2] = sw_em_1g;
mcp->mb[3] = sw_em_2g;
mcp->mb[4] = sw_em_4g;
mcp->mb[2] = sw_em_1g | BIT_15;
mcp->mb[3] = sw_em_2g | BIT_15;
mcp->mb[4] = sw_em_4g | BIT_15;
mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = 30;
@ -2436,7 +2439,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));

View File

@ -8,8 +8,8 @@
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <scsi/scsi_tcq.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);
}
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
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;
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 */
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;
if (IS_QLA2322(ha) || IS_QLA6322(ha))
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;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
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);
init_completion(&ha->dpc_inited);
init_completion(&ha->dpc_exited);
qla2x00_config_dma_addressing(ha);
if (qla2x00_mem_alloc(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
*/
ha->dpc_should_die = 0;
ha->dpc_pid = kernel_thread(qla2x00_do_dpc, ha, 0);
if (ha->dpc_pid < 0) {
ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
"%s_dpc", ha->host_str);
if (IS_ERR(ha->dpc_thread)) {
qla_printk(KERN_WARNING, ha,
"Unable to start DPC thread!\n");
ret = -ENODEV;
ret = PTR_ERR(ha->dpc_thread);
goto probe_failed;
}
wait_for_completion(&ha->dpc_inited);
host->this_id = 255;
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);
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_RISC_INT);
} else {
@ -1621,8 +1668,6 @@ EXPORT_SYMBOL_GPL(qla2x00_remove_one);
static void
qla2x00_free_device(scsi_qla_host_t *ha)
{
int ret;
/* Abort any outstanding IO descriptors. */
if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
qla2x00_cancel_io_descriptors(ha);
@ -1632,18 +1677,15 @@ qla2x00_free_device(scsi_qla_host_t *ha)
qla2x00_stop_timer(ha);
/* Kill the kernel thread for this host */
if (ha->dpc_pid >= 0) {
ha->dpc_should_die = 1;
wmb();
ret = kill_proc(ha->dpc_pid, SIGHUP, 1);
if (ret) {
qla_printk(KERN_ERR, ha,
"Unable to signal DPC thread -- (%d)\n", ret);
if (ha->dpc_thread) {
struct task_struct *t = ha->dpc_thread;
/* TODO: SOMETHING MORE??? */
} else {
wait_for_completion(&ha->dpc_exited);
}
/*
* qla2xxx_wake_dpc checks for ->dpc_thread
* so we need to zero it out.
*/
ha->dpc_thread = NULL;
kthread_stop(t);
}
/* 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);
}
if (defer && ha->dpc_wait && !ha->dpc_active)
up(ha->dpc_wait);
if (defer)
qla2xxx_wake_dpc(ha);
}
/*
@ -1993,7 +2035,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
{
struct list_head *fcpl, *fcptemp;
fc_port_t *fcport;
unsigned int wtime;/* max wait time if mbx cmd is busy. */
if (ha == NULL) {
/* error */
@ -2001,11 +2042,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
return;
}
/* Make sure all other threads are stopped. */
wtime = 60 * 1000;
while (ha->dpc_wait && wtime)
wtime = msleep_interruptible(wtime);
/* free ioctl memory */
qla2x00_free_ioctl_mem(ha);
@ -2156,7 +2192,6 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha)
static int
qla2x00_do_dpc(void *data)
{
DECLARE_MUTEX_LOCKED(sem);
scsi_qla_host_t *ha;
fc_port_t *fcport;
uint8_t status;
@ -2164,32 +2199,19 @@ qla2x00_do_dpc(void *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);
unlock_kernel();
complete(&ha->dpc_inited);
while (1) {
while (!kthread_should_stop()) {
DEBUG3(printk("qla2x00: DPC handler sleeping\n"));
if (down_interruptible(&sem))
break;
if (ha->dpc_should_die)
break;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
__set_current_state(TASK_RUNNING);
DEBUG3(printk("qla2x00: DPC handler waking up\n"));
/* Initialization not yet finished. Don't do anything yet. */
if (!ha->flags.init_done || ha->dpc_active)
if (!ha->flags.init_done)
continue;
DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no));
@ -2273,7 +2295,7 @@ qla2x00_do_dpc(void *data)
} else
status =
qla2x00_local_device_login(
ha, fcport->loop_id);
ha, fcport);
if (status == QLA_SUCCESS) {
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.
*/
ha->dpc_wait = NULL;
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(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&
ha->dpc_wait && !ha->dpc_active) {
up(ha->dpc_wait);
}
test_bit(RELOGIN_NEEDED, &ha->dpc_flags)))
qla2xxx_wake_dpc(ha);
qla2x00_restart_timer(ha, WATCH_INTERVAL);
}
@ -2576,13 +2601,12 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
/* Firmware interface routines. */
#define FW_BLOBS 6
#define FW_BLOBS 5
#define FW_ISP21XX 0
#define FW_ISP22XX 1
#define FW_ISP2300 2
#define FW_ISP2322 3
#define FW_ISP63XX 4
#define FW_ISP24XX 5
#define FW_ISP24XX 4
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 = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
{ .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
{ .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, },
{ .name = "ql2400_fw.bin", },
};
@ -2605,13 +2628,11 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
blob = &qla_fw_blobs[FW_ISP21XX];
} else if (IS_QLA2200(ha)) {
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];
} else if (IS_QLA2322(ha)) {
} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
blob = &qla_fw_blobs[FW_ISP2322];
} else if (IS_QLA6312(ha) || IS_QLA6322(ha)) {
blob = &qla_fw_blobs[FW_ISP63XX];
} else if (IS_QLA24XX(ha)) {
} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
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_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432,
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 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);

View File

@ -1191,11 +1191,6 @@ qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
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
* @ha: HA context
@ -1354,7 +1349,7 @@ qla2x00_resume_hba(struct scsi_qla_host *ha)
/* Resume HBA. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
up(ha->dpc_wait);
qla2xxx_wake_dpc(ha);
qla2x00_wait_for_hba_online(ha);
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. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
up(ha->dpc_wait);
qla2xxx_wake_dpc(ha);
qla2x00_wait_for_hba_online(ha);
scsi_unblock_requests(ha->host);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More