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

This commit is contained in:
Linus Torvalds 2005-11-05 10:31:35 -08:00
commit fecb4a0c87
135 changed files with 29995 additions and 37077 deletions

View File

@ -0,0 +1,45 @@
Copyright (c) 2003-2005 QLogic Corporation
QLogic Linux Fibre Channel HBA Driver
This program includes a device driver for Linux 2.6 that may be
distributed with QLogic hardware specific firmware binary file.
You may modify and redistribute the device driver code under the
GNU General Public License as published by the Free Software
Foundation (version 2 or a later version).
You may redistribute the hardware specific firmware binary file
under the following terms:
1. Redistribution of source code (only if applicable),
must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistribution in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
3. The name of QLogic Corporation may not be used to
endorse or promote products derived from this software
without specific prior written permission
REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
COMBINATION WITH THIS PROGRAM.

View File

@ -77,8 +77,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.03.03"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.03"
#define MPT_LINUX_VERSION_COMMON "3.03.04"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.04"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@ -421,6 +421,17 @@ typedef struct _MPT_IOCTL {
struct semaphore sem_ioc;
} MPT_IOCTL;
#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */
#define MPT_SAS_MGMT_STATUS_COMMAND_GOOD 0x10 /* Command Status GOOD */
#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */
typedef struct _MPT_SAS_MGMT {
struct semaphore mutex;
struct completion done;
u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 status; /* current command status */
}MPT_SAS_MGMT;
/*
* Event Structure and define
*/
@ -604,6 +615,7 @@ typedef struct _MPT_ADAPTER
struct list_head list;
struct net_device *netdev;
struct list_head sas_topology;
MPT_SAS_MGMT sas_mgmt;
} MPT_ADAPTER;
/*

View File

@ -83,6 +83,7 @@ MODULE_PARM_DESC(mpt_pt_clear,
static int mptsasDoneCtx = -1;
static int mptsasTaskCtx = -1;
static int mptsasInternalCtx = -1; /* Used only for internal commands */
static int mptsasMgmtCtx = -1;
/*
@ -123,6 +124,104 @@ struct mptsas_portinfo {
struct mptsas_phyinfo *phy_info;
};
#ifdef SASDEBUG
static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
{
printk("---- IO UNIT PAGE 0 ------------\n");
printk("Handle=0x%X\n",
le16_to_cpu(phy_data->AttachedDeviceHandle));
printk("Controller Handle=0x%X\n",
le16_to_cpu(phy_data->ControllerDevHandle));
printk("Port=0x%X\n", phy_data->Port);
printk("Port Flags=0x%X\n", phy_data->PortFlags);
printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
printk("Controller PHY Device Info=0x%X\n",
le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
printk("DiscoveryStatus=0x%X\n",
le32_to_cpu(phy_data->DiscoveryStatus));
printk("\n");
}
static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
{
__le64 sas_address;
memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
printk("---- SAS PHY PAGE 0 ------------\n");
printk("Attached Device Handle=0x%X\n",
le16_to_cpu(pg0->AttachedDevHandle));
printk("SAS Address=0x%llX\n",
(unsigned long long)le64_to_cpu(sas_address));
printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
printk("Attached Device Info=0x%X\n",
le32_to_cpu(pg0->AttachedDeviceInfo));
printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
printk("Change Count=0x%X\n", pg0->ChangeCount);
printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
printk("\n");
}
static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
{
printk("---- SAS PHY PAGE 1 ------------\n");
printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
printk("Running Disparity Error Count=0x%x\n",
pg1->RunningDisparityErrorCount);
printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
printk("\n");
}
static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
{
__le64 sas_address;
memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
printk("---- SAS DEVICE PAGE 0 ---------\n");
printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
printk("Target ID=0x%X\n", pg0->TargetID);
printk("Bus=0x%X\n", pg0->Bus);
/* The PhyNum field specifies the PHY number of the parent
* device this device is linked to
*/
printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
printk("Physical Port=0x%X\n", pg0->PhysicalPort);
printk("\n");
}
static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
{
printk("---- SAS EXPANDER PAGE 1 ------------\n");
printk("Physical Port=0x%X\n", pg1->PhysicalPort);
printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
printk("Owner Device Handle=0x%X\n",
le16_to_cpu(pg1->OwnerDevHandle));
printk("Attached Device Handle=0x%X\n",
le16_to_cpu(pg1->AttachedDevHandle));
}
#else
#define mptsas_print_phy_data(phy_data) do { } while (0)
#define mptsas_print_phy_pg0(pg0) do { } while (0)
#define mptsas_print_phy_pg1(pg1) do { } while (0)
#define mptsas_print_device_pg0(pg0) do { } while (0)
#define mptsas_print_expander_pg1(pg1) do { } while (0)
#endif
/*
* This is pretty ugly. We will be able to seriously clean it up
* once the DV code in mptscsih goes away and we can properly
@ -200,92 +299,160 @@ static struct scsi_host_template mptsas_driver_template = {
.use_clustering = ENABLE_CLUSTERING,
};
static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
{
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
}
static int mptsas_get_linkerrors(struct sas_phy *phy)
{
MPT_ADAPTER *ioc = phy_to_ioc(phy);
ConfigExtendedPageHeader_t hdr;
CONFIGPARMS cfg;
SasPhyPage1_t *buffer;
dma_addr_t dma_handle;
int error;
hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
hdr.ExtPageLength = 0;
hdr.PageNumber = 1 /* page number 1*/;
hdr.Reserved1 = 0;
hdr.Reserved2 = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
cfg.cfghdr.ehdr = &hdr;
cfg.physAddr = -1;
cfg.pageAddr = phy->identify.phy_identifier;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0; /* read */
cfg.timeout = 10;
error = mpt_config(ioc, &cfg);
if (error)
return error;
if (!hdr.ExtPageLength)
return -ENXIO;
buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
&dma_handle);
if (!buffer)
return -ENOMEM;
cfg.physAddr = dma_handle;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
error = mpt_config(ioc, &cfg);
if (error)
goto out_free_consistent;
mptsas_print_phy_pg1(buffer);
phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
phy->running_disparity_error_count =
le32_to_cpu(buffer->RunningDisparityErrorCount);
phy->loss_of_dword_sync_count =
le32_to_cpu(buffer->LossDwordSynchCount);
phy->phy_reset_problem_count =
le32_to_cpu(buffer->PhyResetProblemCount);
out_free_consistent:
pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
buffer, dma_handle);
return error;
}
static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
MPT_FRAME_HDR *reply)
{
ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
if (reply != NULL) {
ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
memcpy(ioc->sas_mgmt.reply, reply,
min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
}
complete(&ioc->sas_mgmt.done);
return 1;
}
static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
{
MPT_ADAPTER *ioc = phy_to_ioc(phy);
SasIoUnitControlRequest_t *req;
SasIoUnitControlReply_t *reply;
MPT_FRAME_HDR *mf;
MPIHeader_t *hdr;
unsigned long timeleft;
int error = -ERESTARTSYS;
/* not implemented for expanders */
if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
return -ENXIO;
if (down_interruptible(&ioc->sas_mgmt.mutex))
goto out;
mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
if (!mf) {
error = -ENOMEM;
goto out_unlock;
}
hdr = (MPIHeader_t *) mf;
req = (SasIoUnitControlRequest_t *)mf;
memset(req, 0, sizeof(SasIoUnitControlRequest_t));
req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
req->MsgContext = hdr->MsgContext;
req->Operation = hard_reset ?
MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
req->PhyNum = phy->identify.phy_identifier;
mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
10 * HZ);
if (!timeleft) {
/* On timeout reset the board */
mpt_free_msg_frame(ioc, mf);
mpt_HardResetHandler(ioc, CAN_SLEEP);
error = -ETIMEDOUT;
goto out_unlock;
}
/* a reply frame is expected */
if ((ioc->sas_mgmt.status &
MPT_IOCTL_STATUS_RF_VALID) == 0) {
error = -ENXIO;
goto out_unlock;
}
/* process the completed Reply Message Frame */
reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
__FUNCTION__,
reply->IOCStatus,
reply->IOCLogInfo);
error = -ENXIO;
goto out_unlock;
}
error = 0;
out_unlock:
up(&ioc->sas_mgmt.mutex);
out:
return error;
}
static struct sas_function_template mptsas_transport_functions = {
.get_linkerrors = mptsas_get_linkerrors,
.phy_reset = mptsas_phy_reset,
};
static struct scsi_transport_template *mptsas_transport_template;
#ifdef SASDEBUG
static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
{
printk("---- IO UNIT PAGE 0 ------------\n");
printk("Handle=0x%X\n",
le16_to_cpu(phy_data->AttachedDeviceHandle));
printk("Controller Handle=0x%X\n",
le16_to_cpu(phy_data->ControllerDevHandle));
printk("Port=0x%X\n", phy_data->Port);
printk("Port Flags=0x%X\n", phy_data->PortFlags);
printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
printk("Controller PHY Device Info=0x%X\n",
le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
printk("DiscoveryStatus=0x%X\n",
le32_to_cpu(phy_data->DiscoveryStatus));
printk("\n");
}
static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
{
__le64 sas_address;
memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
printk("---- SAS PHY PAGE 0 ------------\n");
printk("Attached Device Handle=0x%X\n",
le16_to_cpu(pg0->AttachedDevHandle));
printk("SAS Address=0x%llX\n",
(unsigned long long)le64_to_cpu(sas_address));
printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
printk("Attached Device Info=0x%X\n",
le32_to_cpu(pg0->AttachedDeviceInfo));
printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
printk("Change Count=0x%X\n", pg0->ChangeCount);
printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
printk("\n");
}
static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
{
__le64 sas_address;
memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
printk("---- SAS DEVICE PAGE 0 ---------\n");
printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
printk("Target ID=0x%X\n", pg0->TargetID);
printk("Bus=0x%X\n", pg0->Bus);
printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
printk("Physical Port=0x%X\n", pg0->PhysicalPort);
printk("\n");
}
static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
{
printk("---- SAS EXPANDER PAGE 1 ------------\n");
printk("Physical Port=0x%X\n", pg1->PhysicalPort);
printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
printk("Owner Device Handle=0x%X\n",
le16_to_cpu(pg1->OwnerDevHandle));
printk("Attached Device Handle=0x%X\n",
le16_to_cpu(pg1->AttachedDevHandle));
}
#else
#define mptsas_print_phy_data(phy_data) do { } while (0)
#define mptsas_print_phy_pg0(pg0) do { } while (0)
#define mptsas_print_device_pg0(pg0) do { } while (0)
#define mptsas_print_expander_pg1(pg1) do { } while (0)
#endif
static int
mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
{
@ -680,7 +847,7 @@ mptsas_parse_device_info(struct sas_identify *identify,
}
static int mptsas_probe_one_phy(struct device *dev,
struct mptsas_phyinfo *phy_info, int index)
struct mptsas_phyinfo *phy_info, int index, int local)
{
struct sas_phy *port;
int error;
@ -773,6 +940,9 @@ static int mptsas_probe_one_phy(struct device *dev,
break;
}
if (local)
port->local_attached = 1;
error = sas_phy_add(port);
if (error) {
sas_phy_free(port);
@ -838,7 +1008,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
}
mptsas_probe_one_phy(&ioc->sh->shost_gendev,
&port_info->phy_info[i], *index);
&port_info->phy_info[i], *index, 1);
(*index)++;
}
@ -909,7 +1079,8 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
}
}
mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index);
mptsas_probe_one_phy(parent, &port_info->phy_info[i],
*index, 0);
(*index)++;
}
@ -1021,6 +1192,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->unique_id = ioc->id;
INIT_LIST_HEAD(&ioc->sas_topology);
init_MUTEX(&ioc->sas_mgmt.mutex);
init_completion(&ioc->sas_mgmt.done);
/* Verify that we won't exceed the maximum
* number of chain buffers
@ -1207,6 +1380,7 @@ mptsas_init(void)
mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
mptsasInternalCtx =
mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
@ -1230,6 +1404,7 @@ mptsas_exit(void)
mpt_reset_deregister(mptsasDoneCtx);
mpt_event_deregister(mptsasDoneCtx);
mpt_deregister(mptsasMgmtCtx);
mpt_deregister(mptsasInternalCtx);
mpt_deregister(mptsasTaskCtx);
mpt_deregister(mptsasDoneCtx);

View File

@ -1732,7 +1732,9 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev->num_resets++;
printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, TW_DRIVER, 0x2c, SCpnt->device->id, SCpnt->cmnd[0]);
sdev_printk(KERN_WARNING, SCpnt->device,
"WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n",
TW_DRIVER, 0x2c, SCpnt->cmnd[0]);
/* Now reset the card and some of the device extension data */
if (twa_reset_device_extension(tw_dev, 0)) {

View File

@ -1432,7 +1432,9 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev->num_resets++;
printk(KERN_WARNING "3w-xxxx: scsi%d: WARNING: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, SCpnt->device->id, SCpnt->cmnd[0]);
sdev_printk(KERN_WARNING, SCpnt->device,
"WARNING: Command (0x%x) timed out, resetting card.\n",
SCpnt->cmnd[0]);
/* Now reset the card and some of the device extension data */
if (tw_reset_device_extension(tw_dev, 0)) {

View File

@ -128,6 +128,7 @@
#include <linux/blkdev.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
@ -831,8 +832,8 @@ process_extended_message(struct Scsi_Host *host,
} else {
/* SDTR message out of the blue, reject it */
printk(KERN_WARNING "scsi%d Unexpected SDTR msg\n",
host->host_no);
shost_printk(KERN_WARNING, host,
"Unexpected SDTR msg\n");
hostdata->msgout[0] = A_REJECT_MSG;
dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE);
script_patch_16(hostdata->script, MessageCount, 1);
@ -906,15 +907,17 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
} else if(SCp != NULL && NCR_700_get_tag_neg_state(SCp->device) == NCR_700_DURING_TAG_NEGOTIATION) {
/* rejected our first simple tag message */
printk(KERN_WARNING "scsi%d (%d:%d) Rejected first tag queue attempt, turning off tag queueing\n", host->host_no, pun, lun);
scmd_printk(KERN_WARNING, SCp,
"Rejected first tag queue attempt, turning off tag queueing\n");
/* we're done negotiating */
NCR_700_set_tag_neg_state(SCp->device, NCR_700_FINISHED_TAG_NEGOTIATION);
hostdata->tag_negotiated &= ~(1<<SCp->device->id);
hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
SCp->device->tagged_supported = 0;
scsi_deactivate_tcq(SCp->device, host->cmd_per_lun);
} else {
printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n",
host->host_no, pun, lun,
shost_printk(KERN_WARNING, host,
"(%d:%d) Unexpected REJECT Message %s\n",
pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
/* however, just ignore it */
}
@ -983,7 +986,8 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
if(SCp->cmnd[0] == REQUEST_SENSE) {
/* OOPS: bad device, returning another
* contingent allegiance condition */
printk(KERN_ERR "scsi%d (%d:%d) broken device is looping in contingent allegiance: ignoring\n", host->host_no, pun, lun);
scmd_printk(KERN_ERR, SCp,
"broken device is looping in contingent allegiance: ignoring\n");
NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]);
} else {
#ifdef NCR_DEBUG
@ -1047,12 +1051,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
// SCp->request_bufflen,
// DMA_FROM_DEVICE);
// if(((char *)SCp->request_buffer)[7] & 0x02) {
// printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", host->host_no, pun, lun);
// hostdata->tag_negotiated |= (1<<SCp->device->id);
// scmd_printk(KERN_INFO, SCp,
// "Enabling Tag Command Queuing\n");
// hostdata->tag_negotiated |= (1<<scmd_id(SCp));
// NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);
// } else {
// NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);
// hostdata->tag_negotiated &= ~(1<<SCp->device->id);
// hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
// }
//}
NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]);
@ -1060,11 +1065,11 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
} else if((dsps & 0xfffff0f0) == A_UNEXPECTED_PHASE) {
__u8 i = (dsps & 0xf00) >> 8;
printk(KERN_ERR "scsi%d: (%d:%d), UNEXPECTED PHASE %s (%s)\n",
host->host_no, pun, lun,
scmd_printk(KERN_ERR, SCp, "UNEXPECTED PHASE %s (%s)\n",
NCR_700_phase[i],
sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
printk(KERN_ERR " len = %d, cmd =", SCp->cmd_len);
scmd_printk(KERN_ERR, SCp, " len = %d, cmd =",
SCp->cmd_len);
scsi_print_command(SCp);
NCR_700_internal_bus_reset(host);
@ -1115,14 +1120,14 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
}
slot = (struct NCR_700_command_slot *)SCp->host_scribble;
DEBUG(("53c700: %d:%d:%d, reselection is tag %d, slot %p(%d)\n",
host->host_no, SDp->id, SDp->lun,
hostdata->msgin[2], slot, slot->tag));
DDEBUG(KERN_DEBUG, SDp,
"reselection is tag %d, slot %p(%d)\n",
hostdata->msgin[2], slot, slot->tag);
} else {
struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG);
if(unlikely(SCp == NULL)) {
printk(KERN_ERR "scsi%d: (%d:%d) no saved request for untagged cmd\n",
host->host_no, reselection_id, lun);
sdev_printk(KERN_ERR, SDp,
"no saved request for untagged cmd\n");
BUG();
}
slot = (struct NCR_700_command_slot *)SCp->host_scribble;
@ -1422,7 +1427,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
* If a contingent allegiance condition exists, the device
* will refuse all tags, so send the request sense as untagged
* */
if((hostdata->tag_negotiated & (1<<SCp->device->id))
if((hostdata->tag_negotiated & (1<<scmd_id(SCp)))
&& (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) {
count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]);
}
@ -1441,7 +1446,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
script_patch_ID(hostdata->script,
Device_ID, 1<<SCp->device->id);
Device_ID, 1<<scmd_id(SCp));
script_patch_32_abs(hostdata->script, CommandAddress,
slot->pCmd);
@ -1764,17 +1769,15 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
* - The blk layer sent and untagged command
*/
if(NCR_700_get_depth(SCp->device) != 0
&& (!(hostdata->tag_negotiated & (1<<SCp->device->id))
&& (!(hostdata->tag_negotiated & (1<<scmd_id(SCp)))
|| !blk_rq_tagged(SCp->request))) {
DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun,
NCR_700_get_depth(SCp->device)));
CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n",
NCR_700_get_depth(SCp->device));
return SCSI_MLQUEUE_DEVICE_BUSY;
}
if(NCR_700_get_depth(SCp->device) >= SCp->device->queue_depth) {
DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun,
NCR_700_get_depth(SCp->device)));
CDEBUG(KERN_ERR, SCp, "has max tag depth %d\n",
NCR_700_get_depth(SCp->device));
return SCSI_MLQUEUE_DEVICE_BUSY;
}
NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);
@ -1796,10 +1799,10 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
scsi_print_command(SCp);
#endif
if(blk_rq_tagged(SCp->request)
&& (hostdata->tag_negotiated &(1<<SCp->device->id)) == 0
&& (hostdata->tag_negotiated &(1<<scmd_id(SCp))) == 0
&& NCR_700_get_tag_neg_state(SCp->device) == NCR_700_START_TAG_NEGOTIATION) {
printk(KERN_ERR "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
hostdata->tag_negotiated |= (1<<SCp->device->id);
scmd_printk(KERN_ERR, SCp, "Enabling Tag Command Queuing\n");
hostdata->tag_negotiated |= (1<<scmd_id(SCp));
NCR_700_set_tag_neg_state(SCp->device, NCR_700_DURING_TAG_NEGOTIATION);
}
@ -1810,17 +1813,16 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
* FIXME: This will royally screw up on multiple LUN devices
* */
if(!blk_rq_tagged(SCp->request)
&& (hostdata->tag_negotiated &(1<<SCp->device->id))) {
printk(KERN_INFO "scsi%d: (%d:%d) Disabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
hostdata->tag_negotiated &= ~(1<<SCp->device->id);
&& (hostdata->tag_negotiated &(1<<scmd_id(SCp)))) {
scmd_printk(KERN_INFO, SCp, "Disabling Tag Command Queuing\n");
hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
}
if((hostdata->tag_negotiated &(1<<SCp->device->id))
if((hostdata->tag_negotiated &(1<<scmd_id(SCp)))
&& scsi_get_tag_type(SCp->device)) {
slot->tag = SCp->request->tag;
DEBUG(("53c700 %d:%d:%d, sending out tag %d, slot %p\n",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun, slot->tag,
slot));
CDEBUG(KERN_DEBUG, SCp, "sending out tag %d, slot %p\n",
slot->tag, slot);
} else {
slot->tag = SCSI_NO_TAG;
/* must populate current_cmnd for scsi_find_tag to work */
@ -1920,8 +1922,8 @@ NCR_700_abort(struct scsi_cmnd * SCp)
{
struct NCR_700_command_slot *slot;
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants to abort command\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
scmd_printk(KERN_INFO, SCp,
"New error handler wants to abort command\n\t");
scsi_print_command(SCp);
slot = (struct NCR_700_command_slot *)SCp->host_scribble;
@ -1954,8 +1956,8 @@ NCR_700_bus_reset(struct scsi_cmnd * SCp)
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
scmd_printk(KERN_INFO, SCp,
"New error handler wants BUS reset, cmd %p\n\t", SCp);
scsi_print_command(SCp);
/* In theory, eh_complete should always be null because the
@ -1987,8 +1989,7 @@ NCR_700_bus_reset(struct scsi_cmnd * SCp)
STATIC int
NCR_700_host_reset(struct scsi_cmnd * SCp)
{
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants HOST reset\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
scmd_printk(KERN_INFO, SCp, "New error handler wants HOST reset\n\t");
scsi_print_command(SCp);
spin_lock_irq(SCp->device->host->host_lock);
@ -2110,7 +2111,7 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
/* shift back to the default unqueued number of commands
* (the user can still raise this) */
scsi_deactivate_tcq(SDp, SDp->host->cmd_per_lun);
hostdata->tag_negotiated &= ~(1 << SDp->id);
hostdata->tag_negotiated &= ~(1 << sdev_id(SDp));
} else {
/* Here, we cleared the negotiation flag above, so this
* will force the driver to renegotiate */

View File

@ -22,8 +22,14 @@
#ifdef NCR_700_DEBUG
#define DEBUG(x) printk x
#define DDEBUG(prefix, sdev, fmt, a...) \
sdev_printk(prefix, sdev, fmt, ##a)
#define CDEBUG(prefix, scmd, fmt, a...) \
scmd_printk(prefix, scmd, fmt, ##a)
#else
#define DEBUG(x)
#define DEBUG(x) do {} while (0)
#define DDEBUG(prefix, scmd, fmt, a...) do {} while (0)
#define CDEBUG(prefix, scmd, fmt, a...) do {} while (0)
#endif
/* The number of available command slots */

View File

@ -229,7 +229,7 @@ config SCSI_FC_ATTRS
config SCSI_ISCSI_ATTRS
tristate "iSCSI Transport Attributes"
depends on SCSI
depends on SCSI && NET
help
If you wish to export transport-specific information about
each attached iSCSI device to sysfs, say Y.
@ -247,6 +247,30 @@ endmenu
menu "SCSI low-level drivers"
depends on SCSI!=n
config ISCSI_TCP
tristate "iSCSI Initiator over TCP/IP"
depends on SCSI && INET
select CRYPTO
select CRYPTO_MD5
select CRYPTO_CRC32C
select SCSI_ISCSI_ATTRS
help
The iSCSI Driver provides a host with the ability to access storage
through an IP network. The driver uses the iSCSI protocol to transport
SCSI requests and responses over a TCP/IP network between the host
(the "initiator") and "targets". Architecturally, the iSCSI driver
combines with the host's TCP/IP stack, network drivers, and Network
Interface Card (NIC) to provide the same functions as a SCSI or a
Fibre Channel (FC) adapter driver with a Host Bus Adapter (HBA).
To compile this driver as a module, choose M here: the
module will be called iscsi_tcp.
The userspace component needed to initialize the driver, documentation,
and sample configuration files can be found here:
http://linux-iscsi.sf.net
config SGIWD93_SCSI
tristate "SGI WD93C93 SCSI Driver"
depends on SGI_IP22 && SCSI
@ -596,19 +620,6 @@ config SCSI_OMIT_FLASHPOINT
substantial, so users of MultiMaster Host Adapters may wish to omit
it.
#
# This is marked broken because it uses over 4kB of stack in
# just two routines:
# 2076 CpqTsProcessIMQEntry
# 2052 PeekIMQEntry
#
config SCSI_CPQFCTS
tristate "Compaq Fibre Channel 64-bit/66Mhz HBA support"
depends on PCI && SCSI && BROKEN
help
Say Y here to compile in support for the Compaq StorageWorks Fibre
Channel 64-bit/66Mhz Host Bus Adapter.
config SCSI_DMX3191D
tristate "DMX3191D SCSI support"
depends on PCI && SCSI

View File

@ -33,6 +33,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o
obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o
obj-$(CONFIG_ISCSI_TCP) += iscsi_tcp.o
obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
@ -119,7 +120,6 @@ obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
obj-$(CONFIG_SCSI_IPR) += ipr.o
@ -164,8 +164,6 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \
cpqfcTSworker.o cpqfcTStrigger.o
libata-objs := libata-core.o libata-scsi.o
# Files generated that shall be removed upon make clean

View File

@ -1247,13 +1247,13 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
case WRITE:
case WRITE_6:
case WRITE_10:
hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
hostdata->time_write[scmd_id(cmd)] += (jiffies - hostdata->timebase);
hostdata->pendingw--;
break;
case READ:
case READ_6:
case READ_10:
hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
hostdata->time_read[scmd_id(cmd)] += (jiffies - hostdata->timebase);
hostdata->pendingr--;
break;
}
@ -1385,7 +1385,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
* the host and target ID's on the SCSI bus.
*/
NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << scmd_id(cmd))));
/*
* Raise ATN while SEL is true before BSY goes false from arbitration,
@ -1430,7 +1430,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
udelay(1);
dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, cmd->device->id));
dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, scmd_id(cmd)));
/*
* The SCSI specification calls for a 250 ms timeout for the actual
@ -1483,7 +1483,7 @@ part2:
if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if (hostdata->targets_present & (1 << cmd->device->id)) {
if (hostdata->targets_present & (1 << scmd_id(cmd))) {
printk(KERN_DEBUG "scsi%d : weirdness\n", instance->host_no);
if (hostdata->restart_select)
printk(KERN_DEBUG "\trestart select\n");
@ -1499,7 +1499,7 @@ part2:
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return 0;
}
hostdata->targets_present |= (1 << cmd->device->id);
hostdata->targets_present |= (1 << scmd_id(cmd));
/*
* Since we followed the SCSI spec, and raised ATN while SEL
@ -2190,7 +2190,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* If the watchdog timer fires, all future accesses to this
* device will use the polled-IO.
*/
printk("scsi%d : switching target %d lun %d to slow handshake\n", instance->host_no, cmd->device->id, cmd->device->lun);
scmd_printk(KERN_INFO, cmd,
"switching to slow handshake\n");
cmd->device->borken = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
sink = 1;
@ -2429,9 +2430,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
scsi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n", instance->host_no, tmp, cmd->device->id, cmd->device->lun);
scmd_printk(KERN_INFO, cmd,
"rejecting unknown message %02x\n",tmp);
else
printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n", instance->host_no, extended_msg[1], extended_msg[0], cmd->device->id, cmd->device->lun);
scmd_printk(KERN_INFO, cmd,
"rejecting unknown extended message code %02x, length %d\n", extended_msg[1], extended_msg[0]);
msgout = MESSAGE_REJECT;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);

View File

@ -936,7 +936,7 @@ static void esp_release_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void esp_restore_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
{
struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
struct esp_pointers *ep = &esp->data_pointers[scmd_id(sp)];
sp->SCp.ptr = ep->saved_ptr;
sp->SCp.buffer = ep->saved_buffer;
@ -946,7 +946,7 @@ static void esp_restore_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void esp_save_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
{
struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
struct esp_pointers *ep = &esp->data_pointers[scmd_id(sp)];
ep->saved_ptr = sp->SCp.ptr;
ep->saved_buffer = sp->SCp.buffer;
@ -1693,13 +1693,13 @@ static inline void esp_connect(struct NCR_ESP *esp, struct ESP_regs *eregs,
if(esp->prev_soff != esp_dev->sync_max_offset ||
esp->prev_stp != esp_dev->sync_min_period ||
(esp->erev > esp100a &&
esp->prev_cfg3 != esp->config3[sp->device->id])) {
esp->prev_cfg3 != esp->config3[scmd_id(sp)])) {
esp->prev_soff = esp_dev->sync_max_offset;
esp_write(eregs->esp_soff, esp->prev_soff);
esp->prev_stp = esp_dev->sync_min_period;
esp_write(eregs->esp_stp, esp->prev_stp);
if(esp->erev > esp100a) {
esp->prev_cfg3 = esp->config3[sp->device->id];
esp->prev_cfg3 = esp->config3[scmd_id(sp)];
esp_write(eregs->esp_cfg3, esp->prev_cfg3);
}
}
@ -2205,7 +2205,7 @@ static int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(SCptr->SCp.Status != GOOD &&
SCptr->SCp.Status != CONDITION_GOOD &&
((1<<SCptr->device->id) & esp->targets_present) &&
((1<<scmd_id(SCptr)) & esp->targets_present) &&
esp_dev->sync && esp_dev->sync_max_offset) {
/* SCSI standard says that the synchronous capabilities
* should be renegotiated at this point. Most likely
@ -2597,7 +2597,7 @@ static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs)
*/
if(esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) {
/* target speaks... */
esp->targets_present |= (1<<SCptr->device->id);
esp->targets_present |= (1<<scmd_id(SCptr));
/* What if the target ignores the sdtr? */
if(esp->snip)
@ -3064,7 +3064,7 @@ static int check_multibyte_msg(struct NCR_ESP *esp,
ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
esp_dev->sync_max_offset,
esp_dev->sync_min_period,
esp->config3[SCptr->device->id]));
esp->config3[scmd_id(SCptr)]));
esp->snip = 0;
} else if(esp_dev->sync_max_offset) {
@ -3621,7 +3621,7 @@ void esp_slave_destroy(Scsi_Device *SDptr)
{
struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata;
esp->targets_present &= ~(1 << SDptr->id);
esp->targets_present &= ~(1 << sdev_id(SDptr));
kfree(SDptr->hostdata);
SDptr->hostdata = NULL;
}

View File

@ -710,7 +710,7 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
/* We are locked here already by the mid layer */
REG0;
outb(SCpnt->device->id, DEST_ID); /* set destination */
outb(scmd_id(SCpnt), DEST_ID); /* set destination */
outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */
for (i = 0; i < SCpnt->cmd_len; i++) {

View File

@ -923,7 +923,7 @@ static int inia100_device_reset(struct scsi_cmnd * SCpnt)
{ /* I need Host Control Block Information */
ORC_HCS *pHCB;
pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
return orc_device_reset(pHCB, SCpnt, SCpnt->device->id);
return orc_device_reset(pHCB, SCpnt, scmd_id(SCpnt));
}

View File

@ -57,7 +57,7 @@ Deanna Bonds (non-DASD support, PAE fibs and 64 bit,
(fixed 64bit and 64G memory model, changed confusing naming convention
where fibs that go to the hardware are consistently called hw_fibs and
not just fibs like the name of the driver tracking structure)
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas.
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
Original Driver
-------------------------

View File

@ -1,4 +1,3 @@
o Testing
o More testing
o Drop irq_mask, basically unused
o I/O size increase

View File

@ -359,15 +359,6 @@ int aac_get_containers(struct aac_dev *dev)
return status;
}
static void aac_io_done(struct scsi_cmnd * scsicmd)
{
unsigned long cpu_flags;
struct Scsi_Host *host = scsicmd->device->host;
spin_lock_irqsave(host->host_lock, cpu_flags);
scsicmd->scsi_done(scsicmd);
spin_unlock_irqrestore(host->host_lock, cpu_flags);
}
static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
{
void *buf;
@ -424,7 +415,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
fib_complete(fibptr);
fib_free(fibptr);
aac_io_done(scsicmd);
scsicmd->scsi_done(scsicmd);
}
/**
@ -608,17 +599,43 @@ static char *container_types[] = {
* files instead of in OS dependant driver source.
*/
static void setinqstr(int devtype, void *data, int tindex)
static void setinqstr(struct aac_dev *dev, void *data, int tindex)
{
struct scsi_inq *str;
struct aac_driver_ident *mp;
mp = aac_get_driver_ident(devtype);
str = (struct scsi_inq *)(data); /* cast data to scsi inq block */
memset(str, ' ', sizeof(*str));
inqstrcpy (mp->vname, str->vid);
inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */
if (dev->supplement_adapter_info.AdapterTypeText[0]) {
char * cp = dev->supplement_adapter_info.AdapterTypeText;
int c = sizeof(str->vid);
while (*cp && *cp != ' ' && --c)
++cp;
c = *cp;
*cp = '\0';
inqstrcpy (dev->supplement_adapter_info.AdapterTypeText,
str->vid);
*cp = c;
while (*cp && *cp != ' ')
++cp;
while (*cp == ' ')
++cp;
/* last six chars reserved for vol type */
c = 0;
if (strlen(cp) > sizeof(str->pid)) {
c = cp[sizeof(str->pid)];
cp[sizeof(str->pid)] = '\0';
}
inqstrcpy (cp, str->pid);
if (c)
cp[sizeof(str->pid)] = c;
} else {
struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype);
inqstrcpy (mp->vname, str->vid);
/* last six chars reserved for vol type */
inqstrcpy (mp->model, str->pid);
}
if (tindex < (sizeof(container_types)/sizeof(char *))){
char *findit = str->pid;
@ -627,7 +644,9 @@ static void setinqstr(int devtype, void *data, int tindex)
/* RAID is superfluous in the context of a RAID device */
if (memcmp(findit-4, "RAID", 4) == 0)
*(findit -= 4) = ' ';
inqstrcpy (container_types[tindex], findit + 1);
if (((findit - str->pid) + strlen(container_types[tindex]))
< (sizeof(str->pid) + sizeof(str->prl)))
inqstrcpy (container_types[tindex], findit + 1);
}
inqstrcpy ("V1.0", str->prl);
}
@ -822,12 +841,12 @@ int aac_get_adapter_info(struct aac_dev* dev)
dev->dac_support = (dacmode!=0);
}
if(dev->dac_support != 0) {
if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL) &&
!pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL)) {
if (!pci_set_dma_mask(dev->pdev, DMA_64BIT_MASK) &&
!pci_set_consistent_dma_mask(dev->pdev, DMA_64BIT_MASK)) {
printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
dev->name, dev->id);
} else if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFULL) &&
!pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFULL)) {
} else if (!pci_set_dma_mask(dev->pdev, DMA_32BIT_MASK) &&
!pci_set_consistent_dma_mask(dev->pdev, DMA_32BIT_MASK)) {
printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n",
dev->name, dev->id);
dev->dac_support = 0;
@ -960,7 +979,7 @@ static void io_callback(void *context, struct fib * fibptr)
fib_complete(fibptr);
fib_free(fibptr);
aac_io_done(scsicmd);
scsicmd->scsi_done(scsicmd);
}
static int aac_read(struct scsi_cmnd * scsicmd, int cid)
@ -1139,7 +1158,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
* For some reason, the Fib didn't queue, return QUEUE_FULL
*/
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
aac_io_done(scsicmd);
scsicmd->scsi_done(scsicmd);
fib_complete(cmd_fibcontext);
fib_free(cmd_fibcontext);
return 0;
@ -1211,7 +1230,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
*/
if (!(cmd_fibcontext = fib_alloc(dev))) {
scsicmd->result = DID_ERROR << 16;
aac_io_done(scsicmd);
scsicmd->scsi_done(scsicmd);
return 0;
}
fib_init(cmd_fibcontext);
@ -1308,7 +1327,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
* For some reason, the Fib didn't queue, return QUEUE_FULL
*/
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
aac_io_done(scsicmd);
scsicmd->scsi_done(scsicmd);
fib_complete(cmd_fibcontext);
fib_free(cmd_fibcontext);
@ -1352,7 +1371,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
fib_complete(fibptr);
fib_free(fibptr);
aac_io_done(cmd);
cmd->scsi_done(cmd);
}
static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
@ -1438,7 +1457,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
struct Scsi_Host *host = scsicmd->device->host;
struct aac_dev *dev = (struct aac_dev *)host->hostdata;
struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
int cardtype = dev->cardtype;
int ret;
/*
@ -1446,7 +1464,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* Test does not apply to ID 16, the pseudo id for the controller
* itself.
*/
if (scsicmd->device->id != host->this_id) {
if (scmd_id(scsicmd) != host->this_id) {
if ((scsicmd->device->channel == 0) ){
if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){
scsicmd->result = DID_NO_CONNECT << 16;
@ -1541,15 +1559,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* Set the Vendor, Product, and Revision Level
* see: <vendor>.c i.e. aac.c
*/
if (scsicmd->device->id == host->this_id) {
setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
if (scmd_id(scsicmd) == host->this_id) {
setinqstr(dev, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
return 0;
}
setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
return aac_get_container_name(scsicmd, cid);
@ -1931,7 +1949,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
* the channel is 2
*/
} else if ((dev->raid_scsi_mode) &&
(scsicmd->device->channel == 2)) {
(scmd_channel(scsicmd) == 2)) {
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8;
} else {
@ -1975,7 +1993,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
* the channel is 2
*/
} else if ((dev->raid_scsi_mode) &&
(scsicmd->device->channel == 2)) {
(scmd_channel(scsicmd) == 2)) {
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8;
} else {
@ -2070,7 +2088,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
fib_complete(fibptr);
fib_free(fibptr);
aac_io_done(scsicmd);
scsicmd->scsi_done(scsicmd);
}
/**

View File

@ -481,6 +481,7 @@ enum aac_log_level {
#define FSAFS_NTC_FIB_CONTEXT 0x030c
struct aac_dev;
struct fib;
struct adapter_ops
{
@ -489,6 +490,7 @@ struct adapter_ops
void (*adapter_disable_int)(struct aac_dev *dev);
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
int (*adapter_send)(struct fib * fib);
};
/*
@ -659,6 +661,10 @@ struct rx_mu_registers {
Status Register */
__le32 OIMR; /* 1334h | 34h | Outbound Interrupt
Mask Register */
__le32 reserved2; /* 1338h | 38h | Reserved */
__le32 reserved3; /* 133Ch | 3Ch | Reserved */
__le32 InboundQueue;/* 1340h | 40h | Inbound Queue Port relative to firmware */
__le32 OutboundQueue;/*1344h | 44h | Outbound Queue Port relative to firmware */
/* * Must access through ATU Inbound
Translation Window */
};
@ -693,8 +699,8 @@ struct rx_inbound {
#define OutboundDoorbellReg MUnit.ODR
struct rx_registers {
struct rx_mu_registers MUnit; /* 1300h - 1334h */
__le32 reserved1[6]; /* 1338h - 134ch */
struct rx_mu_registers MUnit; /* 1300h - 1344h */
__le32 reserved1[2]; /* 1348h - 134ch */
struct rx_inbound IndexRegs;
};
@ -711,8 +717,8 @@ struct rx_registers {
#define rkt_inbound rx_inbound
struct rkt_registers {
struct rkt_mu_registers MUnit; /* 1300h - 1334h */
__le32 reserved1[1010]; /* 1338h - 22fch */
struct rkt_mu_registers MUnit; /* 1300h - 1344h */
__le32 reserved1[1006]; /* 1348h - 22fch */
struct rkt_inbound IndexRegs; /* 2300h - */
};
@ -721,8 +727,6 @@ struct rkt_registers {
#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR))
#define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR))
struct fib;
typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
struct aac_fib_context {
@ -937,7 +941,6 @@ struct aac_dev
const char *name;
int id;
u16 irq_mask;
/*
* negotiated FIB settings
*/
@ -972,6 +975,7 @@ struct aac_dev
struct adapter_ops a_ops;
unsigned long fsrev; /* Main driver's revision number */
unsigned base_size; /* Size of mapped in region */
struct aac_init *init; /* Holds initialization info to communicate with adapter */
dma_addr_t init_pa; /* Holds physical address of the init struct */
@ -992,6 +996,9 @@ struct aac_dev
/*
* The following is the device specific extension.
*/
#if (!defined(AAC_MIN_FOOTPRINT_SIZE))
# define AAC_MIN_FOOTPRINT_SIZE 8192
#endif
union
{
struct sa_registers __iomem *sa;
@ -1012,6 +1019,7 @@ struct aac_dev
u8 nondasd_support;
u8 dac_support;
u8 raid_scsi_mode;
u8 new_comm_interface;
/* macro side-effects BEWARE */
# define raw_io_interface \
init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
@ -1034,6 +1042,8 @@ struct aac_dev
#define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev)
#define aac_adapter_send(fib) \
((fib)->dev)->a_ops.adapter_send(fib)
#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
@ -1560,7 +1570,7 @@ struct fib_ioctl
struct revision
{
__le32 compat;
u32 compat;
__le32 version;
__le32 build;
};
@ -1779,6 +1789,7 @@ int aac_rkt_init(struct aac_dev *dev);
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_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
int fib_adapter_complete(struct fib * fibptr, unsigned short size);

View File

@ -408,7 +408,7 @@ static int check_revision(struct aac_dev *dev, void __user *arg)
char *driver_version = aac_driver_version;
u32 version;
response.compat = cpu_to_le32(1);
response.compat = 1;
version = (simple_strtol(driver_version,
&driver_version, 10) << 24) | 0x00000400;
version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;
@ -574,7 +574,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
sg_user[i] = (void __user *)usg->sg[i].addr;
sg_user[i] = (void __user *)(long)usg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@ -624,7 +624,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
sg_user[i] = (void __user *)upsg->sg[i].addr;
sg_user[i] = (void __user *)(long)upsg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;

View File

@ -116,6 +116,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
}
init->InitFlags = 0;
if (dev->new_comm_interface) {
init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
}
init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
@ -315,12 +319,33 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
- sizeof(struct aac_fibhdr)
- sizeof(struct aac_write) + sizeof(struct sgentry))
/ sizeof(struct sgentry);
dev->new_comm_interface = 0;
dev->raw_io_64 = 0;
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
(status[0] == 0x00000001)) {
if (status[1] & AAC_OPT_NEW_COMM_64)
dev->raw_io_64 = 1;
if (status[1] & AAC_OPT_NEW_COMM)
dev->new_comm_interface = dev->a_ops.adapter_send != 0;
if (dev->new_comm_interface && (status[2] > dev->base_size)) {
iounmap(dev->regs.sa);
dev->base_size = status[2];
dprintk((KERN_DEBUG "ioremap(%lx,%d)\n",
host->base, status[2]));
dev->regs.sa = ioremap(host->base, status[2]);
if (dev->regs.sa == NULL) {
/* remap failed, go back ... */
dev->new_comm_interface = 0;
dev->regs.sa = ioremap(host->base,
AAC_MIN_FOOTPRINT_SIZE);
if (dev->regs.sa == NULL) {
printk(KERN_WARNING
"aacraid: unable to map adapter.\n");
return NULL;
}
}
}
}
if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
0, 0, 0, 0, 0, 0,

View File

@ -212,7 +212,7 @@ void fib_init(struct fib *fibptr)
hw_fib->header.StructType = FIB_MAGIC;
hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */
hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
}
@ -380,9 +380,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
{
u32 index;
struct aac_dev * dev = fibptr->dev;
unsigned long nointr = 0;
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_queue * q;
unsigned long flags = 0;
@ -417,7 +415,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
* Map the fib into 32bits by using the fib number
*/
hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr-dev->fibs)) << 1);
hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2);
hw_fib->header.SenderData = (u32)(fibptr - dev->fibs);
/*
* Set FIB state to indicate where it came from and if we want a
@ -456,10 +454,10 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
FIB_COUNTER_INCREMENT(aac_config.FibsSent);
dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
dprintk((KERN_DEBUG "Fib contents:.\n"));
dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command));
dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState));
dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command)));
dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));
dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState)));
dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib));
dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
@ -469,14 +467,37 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
if(wait)
spin_lock_irqsave(&fibptr->event_lock, flags);
spin_lock_irqsave(q->lock, qflags);
aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
if (dev->new_comm_interface) {
unsigned long count = 10000000L; /* 50 seconds */
list_add_tail(&fibptr->queue, &q->pendingq);
q->numpending++;
spin_unlock_irqrestore(q->lock, qflags);
while (aac_adapter_send(fibptr) != 0) {
if (--count == 0) {
if (wait)
spin_unlock_irqrestore(&fibptr->event_lock, flags);
spin_lock_irqsave(q->lock, qflags);
q->numpending--;
list_del(&fibptr->queue);
spin_unlock_irqrestore(q->lock, qflags);
return -ETIMEDOUT;
}
udelay(5);
}
} else {
u32 index;
unsigned long nointr = 0;
aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
list_add_tail(&fibptr->queue, &q->pendingq);
q->numpending++;
*(q->headers.producer) = cpu_to_le32(index + 1);
spin_unlock_irqrestore(q->lock, qflags);
dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
if (!(nointr & aac_config.irq_mod))
aac_adapter_notify(dev, AdapNormCmdQueue);
}
list_add_tail(&fibptr->queue, &q->pendingq);
q->numpending++;
*(q->headers.producer) = cpu_to_le32(index + 1);
spin_unlock_irqrestore(q->lock, qflags);
if (!(nointr & aac_config.irq_mod))
aac_adapter_notify(dev, AdapNormCmdQueue);
/*
* If the caller wanted us to wait for response wait now.
*/
@ -492,7 +513,6 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
* hardware failure has occurred.
*/
unsigned long count = 36000000L; /* 3 minutes */
unsigned long qflags;
while (down_trylock(&fibptr->event_wait)) {
if (--count == 0) {
spin_lock_irqsave(q->lock, qflags);
@ -621,12 +641,16 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
unsigned long qflags;
if (hw_fib->header.XferState == 0) {
if (dev->new_comm_interface)
kfree (hw_fib);
return 0;
}
/*
* If we plan to do anything check the structure type first.
*/
if ( hw_fib->header.StructType != FIB_MAGIC ) {
if (dev->new_comm_interface)
kfree (hw_fib);
return -EINVAL;
}
/*
@ -637,21 +661,25 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
* send the completed cdb to the adapter.
*/
if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
u32 index;
hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
if (size) {
size += sizeof(struct aac_fibhdr);
if (size > le16_to_cpu(hw_fib->header.SenderSize))
return -EMSGSIZE;
hw_fib->header.Size = cpu_to_le16(size);
if (dev->new_comm_interface) {
kfree (hw_fib);
} else {
u32 index;
hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
if (size) {
size += sizeof(struct aac_fibhdr);
if (size > le16_to_cpu(hw_fib->header.SenderSize))
return -EMSGSIZE;
hw_fib->header.Size = cpu_to_le16(size);
}
q = &dev->queues->queue[AdapNormRespQueue];
spin_lock_irqsave(q->lock, qflags);
aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr);
*(q->headers.producer) = cpu_to_le32(index + 1);
spin_unlock_irqrestore(q->lock, qflags);
if (!(nointr & (int)aac_config.irq_mod))
aac_adapter_notify(dev, AdapNormRespQueue);
}
q = &dev->queues->queue[AdapNormRespQueue];
spin_lock_irqsave(q->lock, qflags);
aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr);
*(q->headers.producer) = cpu_to_le32(index + 1);
spin_unlock_irqrestore(q->lock, qflags);
if (!(nointr & (int)aac_config.irq_mod))
aac_adapter_notify(dev, AdapNormRespQueue);
}
else
{

View File

@ -73,7 +73,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
int fast;
u32 index = le32_to_cpu(entry->addr);
fast = index & 0x01;
fib = &dev->fibs[index >> 1];
fib = &dev->fibs[index >> 2];
hwfib = fib->hw_fib;
aac_consumer_free(dev, q, HostNormRespQueue);
@ -213,3 +213,116 @@ unsigned int aac_command_normal(struct aac_queue *q)
spin_unlock_irqrestore(q->lock, flags);
return 0;
}
/**
* aac_intr_normal - Handle command replies
* @dev: Device
* @index: completion reference
*
* This DPC routine will be run when the adapter interrupts us to let us
* know there is a response on our normal priority queue. We will pull off
* all QE there are and wake up all the waiters before exiting.
*/
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
{
u32 index = le32_to_cpu(Index);
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, Index));
if ((index & 0x00000002L)) {
struct hw_fib * hw_fib;
struct fib * fib;
struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue];
unsigned long flags;
if (index == 0xFFFFFFFEL) /* Special Case */
return 0; /* Do nothing */
/*
* Allocate a FIB. For non queued stuff we can just use
* the stack so we are happy. We need a fib object in order to
* manage the linked lists.
*/
if ((!dev->aif_thread)
|| (!(fib = kmalloc(sizeof(struct fib),GFP_ATOMIC))))
return 1;
if (!(hw_fib = kmalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
kfree (fib);
return 1;
}
memset(hw_fib, 0, sizeof(struct hw_fib));
memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib));
memset(fib, 0, sizeof(struct fib));
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
fib->size = sizeof(struct fib);
fib->hw_fib = hw_fib;
fib->data = hw_fib->data;
fib->dev = dev;
spin_lock_irqsave(q->lock, flags);
list_add_tail(&fib->fiblink, &q->cmdq);
wake_up_interruptible(&q->cmdready);
spin_unlock_irqrestore(q->lock, flags);
return 1;
} else {
int fast = index & 0x01;
struct fib * fib = &dev->fibs[index >> 2];
struct hw_fib * hwfib = fib->hw_fib;
/*
* Remove this fib from the Outstanding I/O queue.
* But only if it has not already been timed out.
*
* If the fib has been timed out already, then just
* continue. The caller has already been notified that
* the fib timed out.
*/
if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
return 0;
}
list_del(&fib->queue);
dev->queues->queue[AdapNormCmdQueue].numpending--;
if (fast) {
/*
* Doctor the fib
*/
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
}
FIB_COUNTER_INCREMENT(aac_config.FibRecved);
if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
{
u32 *pstatus = (u32 *)hwfib->data;
if (*pstatus & cpu_to_le32(0xffff0000))
*pstatus = cpu_to_le32(ST_OK);
}
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async))
{
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected))
FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved);
else
FIB_COUNTER_INCREMENT(aac_config.AsyncRecved);
/*
* NOTE: we cannot touch the fib after this
* call, because it may have been deallocated.
*/
fib->callback(fib->callback_data, fib);
} else {
unsigned long flagv;
dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv);
fib->done = 1;
up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
}
return 0;
}
}

View File

@ -752,8 +752,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
if (error)
goto out;
if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL) ||
pci_set_consistent_dma_mask(pdev, 0xFFFFFFFFULL))
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
goto out;
/*
* If the quirk31 bit is set, the adapter needs adapter
@ -788,8 +788,29 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
goto out_free_host;
spin_lock_init(&aac->fib_lock);
if ((*aac_drivers[index].init)(aac))
/*
* Map in the registers from the adapter.
*/
aac->base_size = AAC_MIN_FOOTPRINT_SIZE;
if ((aac->regs.sa = ioremap(
(unsigned long)aac->scsi_host_ptr->base, AAC_MIN_FOOTPRINT_SIZE))
== NULL) {
printk(KERN_WARNING "%s: unable to map adapter.\n",
AAC_DRIVERNAME);
goto out_free_fibs;
}
if ((*aac_drivers[index].init)(aac))
goto out_unmap;
/*
* Start any kernel threads needed
*/
aac->thread_pid = kernel_thread((int (*)(void *))aac_command_thread,
aac, 0);
if (aac->thread_pid < 0) {
printk(KERN_ERR "aacraid: Unable to create command thread.\n");
goto out_deinit;
}
/*
* If we had set a smaller DMA mask earlier, set it to 4gig
@ -797,9 +818,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* address space.
*/
if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL))
goto out_free_fibs;
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
goto out_deinit;
aac->maximum_num_channels = aac_drivers[index].channels;
error = aac_get_adapter_info(aac);
if (error < 0)
@ -866,10 +887,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_send_shutdown(aac);
aac_adapter_disable_int(aac);
free_irq(pdev->irq, aac);
out_unmap:
fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues);
free_irq(pdev->irq, aac);
iounmap(aac->regs.sa);
out_free_fibs:
kfree(aac->fibs);
@ -910,6 +932,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
iounmap(aac->regs.sa);
kfree(aac->fibs);
kfree(aac->fsa_dev);
list_del(&aac->entry);
scsi_host_put(shost);

View File

@ -49,40 +49,57 @@
static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct aac_dev *dev = dev_id;
unsigned long bellbits;
u8 intstat, mask;
intstat = rkt_readb(dev, MUnit.OISR);
/*
* Read mask and invert because drawbridge is reversed.
* This allows us to only service interrupts that have
* been enabled.
*/
mask = ~(dev->OIMR);
/* Check to see if this is our interrupt. If it isn't just return */
if (intstat & mask)
{
bellbits = rkt_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
aac_printf(dev, rkt_readl(dev, IndexRegs.Mailbox[5]));
rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
if (dev->new_comm_interface) {
u32 Index = rkt_readl(dev, MUnit.OutboundQueue);
if (Index == 0xFFFFFFFFL)
Index = rkt_readl(dev, MUnit.OutboundQueue);
if (Index != 0xFFFFFFFFL) {
do {
if (aac_intr_normal(dev, Index)) {
rkt_writel(dev, MUnit.OutboundQueue, Index);
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
}
Index = rkt_readl(dev, MUnit.OutboundQueue);
} while (Index != 0xFFFFFFFFL);
return IRQ_HANDLED;
}
else if (bellbits & DoorBellAdapterNormCmdReady) {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
} else {
unsigned long bellbits;
u8 intstat;
intstat = rkt_readb(dev, MUnit.OISR);
/*
* Read mask and invert because drawbridge is reversed.
* This allows us to only service interrupts that have
* been enabled.
* Check to see if this is our interrupt. If it isn't just return
*/
if (intstat & ~(dev->OIMR))
{
bellbits = rkt_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
aac_printf(dev, rkt_readl (dev, IndexRegs.Mailbox[5]));
rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
else if (bellbits & DoorBellAdapterNormCmdReady) {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
// rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
}
else if (bellbits & DoorBellAdapterNormRespReady) {
rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
}
else if (bellbits & DoorBellAdapterNormCmdNotFull) {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
}
else if (bellbits & DoorBellAdapterNormRespNotFull) {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
}
return IRQ_HANDLED;
}
else if (bellbits & DoorBellAdapterNormRespReady) {
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
}
else if (bellbits & DoorBellAdapterNormCmdNotFull) {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
}
else if (bellbits & DoorBellAdapterNormRespNotFull) {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
}
return IRQ_HANDLED;
}
return IRQ_NONE;
}
@ -173,7 +190,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Restore interrupt mask even though we timed out
*/
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
if (dev->new_comm_interface)
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
else
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
return -ETIMEDOUT;
}
/*
@ -196,7 +216,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Restore interrupt mask
*/
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
if (dev->new_comm_interface)
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
else
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
return 0;
}
@ -268,15 +291,6 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
rkt_writeb(dev, MUnit.OIMR, 0xff);
rkt_writel(dev, MUnit.ODR, 0xffffffff);
// rkt_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here
rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
@ -349,6 +363,39 @@ static int aac_rkt_check_health(struct aac_dev *dev)
return 0;
}
/**
* aac_rkt_send
* @fib: fib to issue
*
* Will send a fib, returning 0 if successful.
*/
static int aac_rkt_send(struct fib * fib)
{
u64 addr = fib->hw_fib_pa;
struct aac_dev *dev = fib->dev;
volatile void __iomem *device = dev->regs.rkt;
u32 Index;
dprintk((KERN_DEBUG "%p->aac_rkt_send(%p->%llx)\n", dev, fib, addr));
Index = rkt_readl(dev, MUnit.InboundQueue);
if (Index == 0xFFFFFFFFL)
Index = rkt_readl(dev, MUnit.InboundQueue);
dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
if (Index == 0xFFFFFFFFL)
return Index;
device += Index;
dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
(u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
writel((u32)(addr & 0xffffffff), device);
device += sizeof(u32);
writel((u32)(addr >> 32), device);
device += sizeof(u32);
writel(le16_to_cpu(fib->hw_fib->header.Size), device);
rkt_writel(dev, MUnit.InboundQueue, Index);
dprintk((KERN_DEBUG "aac_rkt_send - return 0\n"));
return 0;
}
/**
* aac_rkt_init - initialize an i960 based AAC card
* @dev: device to configure
@ -369,13 +416,8 @@ int aac_rkt_init(struct aac_dev *dev)
name = dev->name;
/*
* Map in the registers from the adapter.
* Check to see if the board panic'd while booting.
*/
if((dev->regs.rkt = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
{
printk(KERN_WARNING "aacraid: unable to map i960.\n" );
goto error_iounmap;
}
/*
* Check to see if the board failed any self tests.
*/
@ -426,6 +468,7 @@ int aac_rkt_init(struct aac_dev *dev)
dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
dev->a_ops.adapter_check_health = aac_rkt_check_health;
dev->a_ops.adapter_send = aac_rkt_send;
/*
* First clear out all interrupts. Then enable the one's that we
@ -437,15 +480,24 @@ int aac_rkt_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL)
goto error_irq;
/*
* Start any kernel threads needed
*/
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
if(dev->thread_pid < 0)
{
printk(KERN_ERR "aacraid: Unable to create rkt thread.\n");
goto error_kfree;
}
if (dev->new_comm_interface) {
/*
* FIB Setup has already been done, but we can minimize the
* damage by at least ensuring the OS never issues more
* commands than we can handle. The Rocket adapters currently
* can only handle 246 commands and 8 AIFs at the same time,
* and in fact do notify us accordingly if we negotiate the
* FIB size. The problem that causes us to add this check is
* to ensure that we do not overdo it with the adapter when a
* hard coded FIB override is being utilized. This special
* case warrants this half baked, but convenient, check here.
*/
if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) {
dev->init->MaxIoCommands = cpu_to_le32(246);
dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB;
}
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
}
/*
* Tell the adapter that all is configured, and it can start
* accepting requests
@ -453,15 +505,11 @@ int aac_rkt_init(struct aac_dev *dev)
aac_rkt_start_adapter(dev);
return 0;
error_kfree:
kfree(dev->queues);
error_irq:
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
iounmap(dev->regs.rkt);
return -1;
}

View File

@ -49,40 +49,57 @@
static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct aac_dev *dev = dev_id;
unsigned long bellbits;
u8 intstat, mask;
intstat = rx_readb(dev, MUnit.OISR);
/*
* Read mask and invert because drawbridge is reversed.
* This allows us to only service interrupts that have
* been enabled.
*/
mask = ~(dev->OIMR);
/* Check to see if this is our interrupt. If it isn't just return */
if (intstat & mask)
{
bellbits = rx_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5]));
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
dprintk((KERN_DEBUG "aac_rx_intr(%d,%p,%p)\n", irq, dev_id, regs));
if (dev->new_comm_interface) {
u32 Index = rx_readl(dev, MUnit.OutboundQueue);
if (Index == 0xFFFFFFFFL)
Index = rx_readl(dev, MUnit.OutboundQueue);
if (Index != 0xFFFFFFFFL) {
do {
if (aac_intr_normal(dev, Index)) {
rx_writel(dev, MUnit.OutboundQueue, Index);
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
}
Index = rx_readl(dev, MUnit.OutboundQueue);
} while (Index != 0xFFFFFFFFL);
return IRQ_HANDLED;
}
else if (bellbits & DoorBellAdapterNormCmdReady) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
} else {
unsigned long bellbits;
u8 intstat;
intstat = rx_readb(dev, MUnit.OISR);
/*
* Read mask and invert because drawbridge is reversed.
* This allows us to only service interrupts that have
* been enabled.
* Check to see if this is our interrupt. If it isn't just return
*/
if (intstat & ~(dev->OIMR))
{
bellbits = rx_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
aac_printf(dev, rx_readl (dev, IndexRegs.Mailbox[5]));
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
else if (bellbits & DoorBellAdapterNormCmdReady) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
}
else if (bellbits & DoorBellAdapterNormRespReady) {
rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
}
else if (bellbits & DoorBellAdapterNormCmdNotFull) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
}
else if (bellbits & DoorBellAdapterNormRespNotFull) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
}
return IRQ_HANDLED;
}
else if (bellbits & DoorBellAdapterNormRespReady) {
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
}
else if (bellbits & DoorBellAdapterNormCmdNotFull) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
}
else if (bellbits & DoorBellAdapterNormRespNotFull) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
}
return IRQ_HANDLED;
}
return IRQ_NONE;
}
@ -173,7 +190,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Restore interrupt mask even though we timed out
*/
rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
if (dev->new_comm_interface)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
else
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
return -ETIMEDOUT;
}
/*
@ -196,7 +216,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Restore interrupt mask
*/
rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
if (dev->new_comm_interface)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
else
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
return 0;
}
@ -267,15 +290,6 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
rx_writeb(dev, MUnit.OIMR, 0xff);
rx_writel(dev, MUnit.ODR, 0xffffffff);
// rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here
rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
@ -348,6 +362,39 @@ static int aac_rx_check_health(struct aac_dev *dev)
return 0;
}
/**
* aac_rx_send
* @fib: fib to issue
*
* Will send a fib, returning 0 if successful.
*/
static int aac_rx_send(struct fib * fib)
{
u64 addr = fib->hw_fib_pa;
struct aac_dev *dev = fib->dev;
volatile void __iomem *device = dev->regs.rx;
u32 Index;
dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr));
Index = rx_readl(dev, MUnit.InboundQueue);
if (Index == 0xFFFFFFFFL)
Index = rx_readl(dev, MUnit.InboundQueue);
dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
if (Index == 0xFFFFFFFFL)
return Index;
device += Index;
dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
(u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
writel((u32)(addr & 0xffffffff), device);
device += sizeof(u32);
writel((u32)(addr >> 32), device);
device += sizeof(u32);
writel(le16_to_cpu(fib->hw_fib->header.Size), device);
rx_writel(dev, MUnit.InboundQueue, Index);
dprintk((KERN_DEBUG "aac_rx_send - return 0\n"));
return 0;
}
/**
* aac_rx_init - initialize an i960 based AAC card
* @dev: device to configure
@ -368,13 +415,8 @@ int aac_rx_init(struct aac_dev *dev)
name = dev->name;
/*
* Map in the registers from the adapter.
* Check to see if the board panic'd while booting.
*/
if((dev->regs.rx = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
{
printk(KERN_WARNING "aacraid: unable to map i960.\n" );
return -1;
}
/*
* Check to see if the board failed any self tests.
*/
@ -426,6 +468,7 @@ int aac_rx_init(struct aac_dev *dev)
dev->a_ops.adapter_notify = aac_rx_notify_adapter;
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_check_health = aac_rx_check_health;
dev->a_ops.adapter_send = aac_rx_send;
/*
* First clear out all interrupts. Then enable the one's that we
@ -437,15 +480,9 @@ int aac_rx_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL)
goto error_irq;
/*
* Start any kernel threads needed
*/
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
if(dev->thread_pid < 0)
{
printk(KERN_ERR "aacraid: Unable to create rx thread.\n");
goto error_kfree;
}
if (dev->new_comm_interface)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
/*
* Tell the adapter that all is configured, and it can start
* accepting requests
@ -453,15 +490,11 @@ int aac_rx_init(struct aac_dev *dev)
aac_rx_start_adapter(dev);
return 0;
error_kfree:
kfree(dev->queues);
error_irq:
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
iounmap(dev->regs.rx);
return -1;
}

View File

@ -237,29 +237,16 @@ static void aac_sa_interrupt_adapter (struct aac_dev *dev)
static void aac_sa_start_adapter(struct aac_dev *dev)
{
u32 ret;
struct aac_init *init;
/*
* Fill in the remaining pieces of the init.
*/
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
* Tell the adapter we are back and up and running so it will scan its command
* queues and enable our interrupts
*/
dev->irq_mask = (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4);
/*
* First clear out all interrupts. Then enable the one's that
* we can handle.
*/
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
/* We can only use a 32 bit address here */
sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
&ret, NULL, NULL, NULL, NULL);
NULL, NULL, NULL, NULL, NULL);
}
/**
@ -313,15 +300,6 @@ int aac_sa_init(struct aac_dev *dev)
instance = dev->id;
name = dev->name;
/*
* Map in the registers from the adapter.
*/
if((dev->regs.sa = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
{
printk(KERN_WARNING "aacraid: unable to map ARM.\n" );
goto error_iounmap;
}
/*
* Check to see if the board failed any self tests.
*/
@ -377,15 +355,6 @@ int aac_sa_init(struct aac_dev *dev)
if(aac_init_adapter(dev) == NULL)
goto error_irq;
/*
* Start any kernel threads needed
*/
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
if (dev->thread_pid < 0) {
printk(KERN_ERR "aacraid: Unable to create command thread.\n");
goto error_kfree;
}
/*
* Tell the adapter that all is configure, and it can start
* accepting requests
@ -393,16 +362,11 @@ int aac_sa_init(struct aac_dev *dev)
aac_sa_start_adapter(dev);
return 0;
error_kfree:
kfree(dev->queues);
error_irq:
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
iounmap(dev->regs.sa);
return -1;
}

View File

@ -2921,8 +2921,7 @@ static void disp_enintr(struct Scsi_Host *shpnt)
*/
static void show_command(Scsi_Cmnd *ptr)
{
printk(KERN_DEBUG "0x%08x: target=%d; lun=%d; cmnd=(",
(unsigned int) ptr, ptr->device->id, ptr->device->lun);
scmd_printk(KERN_DEBUG, ptr, "%p: cmnd=(", ptr);
__scsi_print_command(ptr->cmnd);

View File

@ -1405,7 +1405,8 @@ static int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
*/
aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1);
printk(KERN_WARNING "aha1542.c: Trying device reset for target %d\n", SCpnt->device->id);
scmd_printk(KERN_WARNING, SCpnt,
"Trying device reset for target\n");
return SUCCESS;

View File

@ -347,7 +347,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
{
unchar direction;
unchar *cmd = (unchar *) SCpnt->cmnd;
unchar target = SCpnt->device->id;
unchar target = scmd_id(SCpnt);
struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
unsigned long flags;
void *buff = SCpnt->request_buffer;

View File

@ -52,6 +52,7 @@ static struct scsi_transport_template *ahd_linux_transport_template = NULL;
#include <linux/mm.h> /* For fetching system memory size */
#include <linux/blkdev.h> /* For block_size() */
#include <linux/delay.h> /* For ssleep/msleep */
#include <linux/device.h>
/*
* Bucket size for counting good commands in between bad ones.
@ -397,7 +398,7 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
/******************************** Macros **************************************/
#define BUILD_SCSIID(ahd, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
(((scmd_id(cmd) << TID_SHIFT) & TID) | (ahd)->our_id)
/*
* Return a string describing the driver.
@ -565,7 +566,7 @@ ahd_linux_slave_configure(struct scsi_device *sdev)
ahd = *((struct ahd_softc **)sdev->host->hostdata);
if (bootverbose)
printf("%s: Slave Configure %d\n", ahd_name(ahd), sdev->id);
sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
ahd_linux_device_queue_depth(sdev);
@ -684,7 +685,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
ahd_name(ahd), cmd);
#endif
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
/*initiate reset*/TRUE);
ahd_unlock(ahd, &s);
@ -2067,9 +2068,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
wait = FALSE;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
printf("%s:%d:%d:%d: Attempting to queue a%s message:",
ahd_name(ahd), cmd->device->channel,
cmd->device->id, cmd->device->lun,
scmd_printk(KERN_INFO, cmd,
"Attempting to queue a%s message:",
flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
printf("CDB:");
@ -2093,9 +2093,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* No target device for this command exists,
* so we must not still own the command.
*/
printf("%s:%d:%d:%d: Is not an active device\n",
ahd_name(ahd), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
retval = SUCCESS;
goto no_cmd;
}
@ -2112,8 +2110,9 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
/* 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, cmd->device->id,
cmd->device->channel + 'A',
if (ahd_match_scb(ahd, pending_scb,
scmd_id(cmd),
scmd_channel(cmd) + 'A',
CAM_LUN_WILDCARD,
SCB_LIST_NULL, ROLE_INITIATOR) == 0)
break;
@ -2121,9 +2120,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
}
if (pending_scb == NULL) {
printf("%s:%d:%d:%d: Command not found\n",
ahd_name(ahd), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Command not found\n");
goto no_cmd;
}
@ -2146,9 +2143,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
paused = TRUE;
if ((pending_scb->flags & SCB_ACTIVE) == 0) {
printf("%s:%d:%d:%d: Command already completed\n",
ahd_name(ahd), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Command already completed\n");
goto no_cmd;
}
@ -2204,7 +2199,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
if (last_phase != P_BUSFREE
&& (SCB_GET_TAG(pending_scb) == active_scbptr
|| (flag == SCB_DEVICE_RESET
&& SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) {
&& SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) {
/*
* We're active on the bus, so assert ATN
@ -2214,9 +2209,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
pending_scb->flags |= SCB_RECOVERY_SCB|flag;
ahd_outb(ahd, MSG_OUT, HOST_MSG);
ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
ahd_name(ahd), cmd->device->channel,
cmd->device->id, cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
wait = TRUE;
} else if (disconnected) {
@ -2277,9 +2270,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
printf("Device is disconnected, re-queuing SCB\n");
wait = TRUE;
} else {
printf("%s:%d:%d:%d: Unable to deliver message\n",
ahd_name(ahd), cmd->device->channel,
cmd->device->id, cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
retval = FAILED;
goto done;
}

View File

@ -641,7 +641,7 @@ ahc_linux_slave_configure(struct scsi_device *sdev)
ahc = *((struct ahc_softc **)sdev->host->hostdata);
if (bootverbose)
printf("%s: Slave Configure %d\n", ahc_name(ahc), sdev->id);
sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
ahc_linux_device_queue_depth(sdev);
@ -686,7 +686,7 @@ ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
u_int channel;
ahc = *((struct ahc_softc **)sdev->host->hostdata);
channel = sdev->channel;
channel = sdev_channel(sdev);
bh = scsi_bios_ptable(bdev);
if (bh) {
@ -759,7 +759,7 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd)
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
ahc_lock(ahc, &flags);
found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
found = ahc_reset_channel(ahc, scmd_channel(cmd) + 'A',
/*initiate reset*/TRUE);
ahc_unlock(ahc, &flags);
@ -2117,9 +2117,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
wait = FALSE;
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
ahc_name(ahc), cmd->device->channel,
cmd->device->id, cmd->device->lun,
scmd_printk(KERN_INFO, cmd, "Attempting to queue a%s message\n",
flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
printf("CDB:");
@ -2174,8 +2172,8 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
/* Any SCB for this device will do for a target reset */
LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
if (ahc_match_scb(ahc, pending_scb, cmd->device->id,
cmd->device->channel + 'A',
if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
scmd_channel(cmd) + 'A',
CAM_LUN_WILDCARD,
SCB_LIST_NULL, ROLE_INITIATOR) == 0)
break;
@ -2183,9 +2181,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
}
if (pending_scb == NULL) {
printf("%s:%d:%d:%d: Command not found\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Command not found\n");
goto no_cmd;
}
@ -2207,9 +2203,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
paused = TRUE;
if ((pending_scb->flags & SCB_ACTIVE) == 0) {
printf("%s:%d:%d:%d: Command already completed\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Command already completed\n");
goto no_cmd;
}
@ -2266,7 +2260,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
if (last_phase != P_BUSFREE
&& (pending_scb->hscb->tag == active_scb_index
|| (flag == SCB_DEVICE_RESET
&& SCSIID_TARGET(ahc, saved_scsiid) == cmd->device->id))) {
&& SCSIID_TARGET(ahc, saved_scsiid) == scmd_id(cmd)))) {
/*
* We're active on the bus, so assert ATN
@ -2276,9 +2270,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
pending_scb->flags |= SCB_RECOVERY_SCB|flag;
ahc_outb(ahc, MSG_OUT, HOST_MSG);
ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
wait = TRUE;
} else if (disconnected) {
@ -2344,9 +2336,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
printf("Device is disconnected, re-queuing SCB\n");
wait = TRUE;
} else {
printf("%s:%d:%d:%d: Unable to deliver message\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
cmd->device->lun);
scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
retval = FAILED;
goto done;
}

View File

@ -297,11 +297,10 @@ stop_dma:
}
workreq = dev->id[c][target_id].curr_req;
#ifdef ED_DBGP
printk(KERN_DEBUG "Channel = %d ID = %d LUN = %d CDB",c,workreq->device->id,workreq->device->lun);
for(l=0;l<workreq->cmd_len;l++)
{
scmd_printk(KERN_DEBUG, workreq, "CDB");
for (l = 0; l < workreq->cmd_len; l++)
printk(KERN_DEBUG " %x",workreq->cmnd[l]);
}
printk("\n");
#endif
tmport = workport + 0x0f;
@ -622,10 +621,10 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
struct atp_unit *dev;
struct Scsi_Host *host;
c = req_p->device->channel;
c = scmd_channel(req_p);
req_p->sense_buffer[0]=0;
req_p->resid = 0;
if (req_p->device->channel > 1) {
if (scmd_channel(req_p) > 1) {
req_p->result = 0x00040000;
done(req_p);
#ifdef ED_DBGP
@ -640,7 +639,7 @@ static int atp870u_queuecommand(struct scsi_cmnd * req_p,
m = 1;
m = m << req_p->device->id;
m = m << scmd_id(req_p);
/*
* Fake a timeout for missing targets
@ -758,9 +757,9 @@ static void send_s870(struct atp_unit *dev,unsigned char c)
dev->quhd[c] = 0;
}
workreq = dev->quereq[c][dev->quhd[c]];
if (dev->id[c][workreq->device->id].curr_req == 0) {
dev->id[c][workreq->device->id].curr_req = workreq;
dev->last_cmd[c] = workreq->device->id;
if (dev->id[c][scmd_id(workreq)].curr_req == 0) {
dev->id[c][scmd_id(workreq)].curr_req = workreq;
dev->last_cmd[c] = scmd_id(workreq);
goto cmd_subp;
}
dev->quhd[c] = j;
@ -787,16 +786,16 @@ abortsnd:
oktosend:
#ifdef ED_DBGP
printk("OK to Send\n");
printk("CDB");
scmd_printk(KERN_DEBUG, workreq, "CDB");
for(i=0;i<workreq->cmd_len;i++) {
printk(" %x",workreq->cmnd[i]);
}
printk("\nChannel = %d ID = %d LUN = %d\n",c,workreq->device->id,workreq->device->lun);
printk("\n");
#endif
if (dev->dev_id == ATP885_DEVID) {
j = inb(dev->baseport + 0x29) & 0xfe;
outb(j, dev->baseport + 0x29);
dev->r1f[c][workreq->device->id] = 0;
dev->r1f[c][scmd_id(workreq)] = 0;
}
if (workreq->cmnd[0] == READ_CAPACITY) {
@ -810,7 +809,7 @@ oktosend:
tmport = workport + 0x1b;
j = 0;
target_id = workreq->device->id;
target_id = scmd_id(workreq);
/*
* Wide ?
@ -3109,7 +3108,7 @@ static int atp870u_abort(struct scsi_cmnd * SCpnt)
host = SCpnt->device->host;
dev = (struct atp_unit *)&host->hostdata;
c=SCpnt->device->channel;
c = scmd_channel(SCpnt);
printk(" atp870u: abort Channel = %x \n", c);
printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);

View File

@ -940,9 +940,7 @@ static int ch_probe(struct device *dev)
MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
dev, "s%s", ch->name);
printk(KERN_INFO "Attached scsi changer %s "
"at scsi%d, channel %d, id %d, lun %d\n",
ch->name, sd->host->host_no, sd->channel, sd->id, sd->lun);
sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
spin_lock(&ch_devlist_lock);
list_add_tail(&ch->list,&ch_devlist);

View File

@ -1389,10 +1389,7 @@ EXPORT_SYMBOL(scsi_print_msg);
void scsi_print_command(struct scsi_cmnd *cmd)
{
/* Assume appended output (i.e. not at start of line) */
printk("scsi%d : destination target %d, lun %d\n",
cmd->device->host->host_no,
cmd->device->id,
cmd->device->lun);
sdev_printk("", cmd->device, "\n");
printk(KERN_INFO " command: ");
scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0);
}

View File

@ -1,19 +0,0 @@
#ifndef CPQFCTS_H
#define CPQFCTS_H
#include "cpqfcTSstructs.h"
// These functions are required by the Linux SCSI layers
extern int cpqfcTS_detect(Scsi_Host_Template *);
extern int cpqfcTS_release(struct Scsi_Host *);
extern const char * cpqfcTS_info(struct Scsi_Host *);
extern int cpqfcTS_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
extern int cpqfcTS_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
extern int cpqfcTS_abort(Scsi_Cmnd *);
extern int cpqfcTS_reset(Scsi_Cmnd *, unsigned int);
extern int cpqfcTS_eh_abort(Scsi_Cmnd *Cmnd);
extern int cpqfcTS_eh_device_reset(Scsi_Cmnd *);
extern int cpqfcTS_biosparam(struct scsi_device *, struct block_device *,
sector_t, int[]);
extern int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg);
#endif /* CPQFCTS_H */

View File

@ -1,238 +0,0 @@
/* Copyright(c) 2000, Compaq Computer Corporation
* Fibre Channel Host Bus Adapter
* 64-bit, 66MHz PCI
* Originally developed and tested on:
* (front): [chip] Tachyon TS HPFC-5166A/1.2 L2C1090 ...
* SP# P225CXCBFIEL6T, Rev XC
* SP# 161290-001, Rev XD
* (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Written by Don Zimmerman
*/
#ifndef CPQFCTSCHIP_H
#define CPQFCTSCHIP_H
#ifndef TACHYON_CHIP_INC
// FC-PH (Physical) specification levels for Login payloads
// NOTE: These are NOT strictly complied with by any FC vendors
#define FC_PH42 0x08
#define FC_PH43 0x09
#define FC_PH3 0x20
#define TACHLITE_TS_RX_SIZE 1024 // max inbound frame size
// "I" prefix is for Include
#define IVENDID 0x00 // word
#define IDEVID 0x02
#define ITLCFGCMD 0x04
#define IMEMBASE 0x18 // Tachyon
#define ITLMEMBASE 0x1C // Tachlite
#define IIOBASEL 0x10 // Tachyon I/O base address, lower 256 bytes
#define IIOBASEU 0x14 // Tachyon I/O base address, upper 256 bytes
#define ITLIOBASEL 0x14 // TachLite I/O base address, lower 256 bytes
#define ITLIOBASEU 0x18 // TachLite I/O base address, upper 256 bytes
#define ITLRAMBASE 0x20 // TL on-board RAM start
#define ISROMBASE 0x24
#define IROMBASE 0x30
#define ICFGCMD 0x04 // PCI config - PCI config access (word)
#define ICFGSTAT 0x06 // PCI status (R - word)
#define IRCTR_WCTR 0x1F2 // ROM control / pre-fetch wait counter
#define IPCIMCTR 0x1F3 // PCI master control register
#define IINTPEND 0x1FD // Interrupt pending (I/O Upper - Tachyon & TL)
#define IINTEN 0x1FE // Interrupt enable (I/O Upper - Tachyon & TL)
#define IINTSTAT 0x1FF // Interrupt status (I/O Upper - Tachyon & TL)
#define IMQ_BASE 0x80
#define IMQ_LENGTH 0x84
#define IMQ_CONSUMER_INDEX 0x88
#define IMQ_PRODUCER_INDEX 0x8C // Tach copies its INDX to bits 0-7 of value
/*
// IOBASE UPPER
#define SFSBQ_BASE 0x00 // single-frame sequences
#define SFSBQ_LENGTH 0x04
#define SFSBQ_PRODUCER_INDEX 0x08
#define SFSBQ_CONSUMER_INDEX 0x0C // (R)
#define SFS_BUFFER_LENGTH 0X10
// SCSI-FCP hardware assists
#define SEST_BASE 0x40 // SSCI Exchange State Table
#define SEST_LENGTH 0x44
#define SCSI_BUFFER_LENGTH 0x48
#define SEST_LINKED_LIST 0x4C
#define TACHYON_My_ID 0x6C
#define TACHYON_CONFIGURATION 0x84 // (R/W) reset val 2
#define TACHYON_CONTROL 0x88
#define TACHYON_STATUS 0x8C // (R)
#define TACHYON_FLUSH_SEST 0x90 // (R/W)
#define TACHYON_EE_CREDIT_TMR 0x94 // (R)
#define TACHYON_BB_CREDIT_TMR 0x98 // (R)
#define TACHYON_RCV_FRAME_ERR 0x9C // (R)
#define FRAME_MANAGER_CONFIG 0xC0 // (R/W)
#define FRAME_MANAGER_CONTROL 0xC4
#define FRAME_MANAGER_STATUS 0xC8 // (R)
#define FRAME_MANAGER_ED_TOV 0xCC
#define FRAME_MANAGER_LINK_ERR1 0xD0 // (R)
#define FRAME_MANAGER_LINK_ERR2 0xD4 // (R)
#define FRAME_MANAGER_TIMEOUT2 0xD8 // (W)
#define FRAME_MANAGER_BB_CREDIT 0xDC // (R)
#define FRAME_MANAGER_WWN_HI 0xE0 // (R/W)
#define FRAME_MANAGER_WWN_LO 0xE4 // (R/W)
#define FRAME_MANAGER_RCV_AL_PA 0xE8 // (R)
#define FRAME_MANAGER_PRIMITIVE 0xEC // {K28.5} byte1 byte2 byte3
*/
#define TL_MEM_ERQ_BASE 0x0 //ERQ Base
#define TL_IO_ERQ_BASE 0x0 //ERQ base
#define TL_MEM_ERQ_LENGTH 0x4 //ERQ Length
#define TL_IO_ERQ_LENGTH 0x4 //ERQ Length
#define TL_MEM_ERQ_PRODUCER_INDEX 0x8 //ERQ Producer Index register
#define TL_IO_ERQ_PRODUCER_INDEX 0x8 //ERQ Producer Index register
#define TL_MEM_ERQ_CONSUMER_INDEX_ADR 0xC //ERQ Consumer Index address register
#define TL_IO_ERQ_CONSUMER_INDEX_ADR 0xC //ERQ Consumer Index address register
#define TL_MEM_ERQ_CONSUMER_INDEX 0xC //ERQ Consumer Index
#define TL_IO_ERQ_CONSUMER_INDEX 0xC //ERQ Consumer Index
#define TL_MEM_SFQ_BASE 0x50 //SFQ Base
#define TL_IO_SFQ_BASE 0x50 //SFQ base
#define TL_MEM_SFQ_LENGTH 0x54 //SFQ Length
#define TL_IO_SFQ_LENGTH 0x54 //SFQ Length
#define TL_MEM_SFQ_CONSUMER_INDEX 0x58 //SFQ Consumer Index
#define TL_IO_SFQ_CONSUMER_INDEX 0x58 //SFQ Consumer Index
#define TL_MEM_IMQ_BASE 0x80 //IMQ Base
#define TL_IO_IMQ_BASE 0x80 //IMQ base
#define TL_MEM_IMQ_LENGTH 0x84 //IMQ Length
#define TL_IO_IMQ_LENGTH 0x84 //IMQ Length
#define TL_MEM_IMQ_CONSUMER_INDEX 0x88 //IMQ Consumer Index
#define TL_IO_IMQ_CONSUMER_INDEX 0x88 //IMQ Consumer Index
#define TL_MEM_IMQ_PRODUCER_INDEX_ADR 0x8C //IMQ Producer Index address register
#define TL_IO_IMQ_PRODUCER_INDEX_ADR 0x8C //IMQ Producer Index address register
#define TL_MEM_SEST_BASE 0x140 //SFQ Base
#define TL_IO_SEST_BASE 0x40 //SFQ base
#define TL_MEM_SEST_LENGTH 0x144 //SFQ Length
#define TL_IO_SEST_LENGTH 0x44 //SFQ Length
#define TL_MEM_SEST_LINKED_LIST 0x14C
#define TL_MEM_SEST_SG_PAGE 0x168 // Extended Scatter/Gather page size
#define TL_MEM_TACH_My_ID 0x16C
#define TL_IO_TACH_My_ID 0x6C //My AL_PA ID
#define TL_MEM_TACH_CONFIG 0x184 //Tachlite Configuration register
#define TL_IO_CONFIG 0x84 //Tachlite Configuration register
#define TL_MEM_TACH_CONTROL 0x188 //Tachlite Control register
#define TL_IO_CTR 0x88 //Tachlite Control register
#define TL_MEM_TACH_STATUS 0x18C //Tachlite Status register
#define TL_IO_STAT 0x8C //Tachlite Status register
#define TL_MEM_FM_CONFIG 0x1C0 //Frame Manager Configuration register
#define TL_IO_FM_CONFIG 0xC0 //Frame Manager Configuration register
#define TL_MEM_FM_CONTROL 0x1C4 //Frame Manager Control
#define TL_IO_FM_CTL 0xC4 //Frame Manager Control
#define TL_MEM_FM_STATUS 0x1C8 //Frame Manager Status
#define TL_IO_FM_STAT 0xC8 //Frame Manager Status
#define TL_MEM_FM_LINK_STAT1 0x1D0 //Frame Manager Link Status 1
#define TL_IO_FM_LINK_STAT1 0xD0 //Frame Manager Link Status 1
#define TL_MEM_FM_LINK_STAT2 0x1D4 //Frame Manager Link Status 2
#define TL_IO_FM_LINK_STAT2 0xD4 //Frame Manager Link Status 2
#define TL_MEM_FM_TIMEOUT2 0x1D8 // (W)
#define TL_MEM_FM_BB_CREDIT0 0x1DC
#define TL_MEM_FM_WWN_HI 0x1E0 //Frame Manager World Wide Name High
#define TL_IO_FM_WWN_HI 0xE0 //Frame Manager World Wide Name High
#define TL_MEM_FM_WWN_LO 0x1E4 //Frame Manager World Wide Name LOW
#define TL_IO_FM_WWN_LO 0xE4 //Frame Manager World Wide Name Low
#define TL_MEM_FM_RCV_AL_PA 0x1E8 //Frame Manager AL_PA Received register
#define TL_IO_FM_ALPA 0xE8 //Frame Manager AL_PA Received register
#define TL_MEM_FM_ED_TOV 0x1CC
#define TL_IO_ROMCTR 0xFA //TL PCI ROM Control Register
#define TL_IO_PCIMCTR 0xFB //TL PCI Master Control Register
#define TL_IO_SOFTRST 0xFC //Tachlite Configuration register
#define TL_MEM_SOFTRST 0x1FC //Tachlite Configuration register
// completion message types (bit 8 set means Interrupt generated)
// CM_Type
#define OUTBOUND_COMPLETION 0
#define ERROR_IDLE_COMPLETION 0x01
#define OUT_HI_PRI_COMPLETION 0x01
#define INBOUND_MFS_COMPLETION 0x02
#define INBOUND_000_COMPLETION 0x03
#define INBOUND_SFS_COMPLETION 0x04 // Tachyon & TachLite
#define ERQ_FROZEN_COMPLETION 0x06 // TachLite
#define INBOUND_C1_TIMEOUT 0x05
#define INBOUND_BUSIED_FRAME 0x06
#define SFS_BUF_WARN 0x07
#define FCP_FROZEN_COMPLETION 0x07 // TachLite
#define MFS_BUF_WARN 0x08
#define IMQ_BUF_WARN 0x09
#define FRAME_MGR_INTERRUPT 0x0A
#define READ_STATUS 0x0B
#define INBOUND_SCSI_DATA_COMPLETION 0x0C
#define INBOUND_FCP_XCHG_COMPLETION 0x0C // TachLite
#define INBOUND_SCSI_DATA_COMMAND 0x0D
#define BAD_SCSI_FRAME 0x0E
#define INB_SCSI_STATUS_COMPLETION 0x0F
#define BUFFER_PROCESSED_COMPLETION 0x11
// FC-AL (Tachyon) Loop Port State Machine defs
// (loop "Up" states)
#define MONITORING 0x0
#define ARBITRATING 0x1
#define ARBITRAT_WON 0x2
#define OPEN 0x3
#define OPENED 0x4
#define XMITTD_CLOSE 0x5
#define RCVD_CLOSE 0x6
#define TRANSFER 0x7
// (loop "Down" states)
#define INITIALIZING 0x8
#define O_I_INIT 0x9
#define O_I_PROTOCOL 0xa
#define O_I_LIP_RCVD 0xb
#define HOST_CONTROL 0xc
#define LOOP_FAIL 0xd
// (no 0xe)
#define OLD_PORT 0xf
#define TACHYON_CHIP_INC
#endif
#endif /* CPQFCTSCHIP_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,493 +0,0 @@
/* Copyright(c) 2000, Compaq Computer Corporation
* Fibre Channel Host Bus Adapter
* 64-bit, 66MHz PCI
* Originally developed and tested on:
* (front): [chip] Tachyon TS HPFC-5166A/1.2 L2C1090 ...
* SP# P225CXCBFIEL6T, Rev XC
* SP# 161290-001, Rev XD
* (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Written by Don Zimmerman
*/
// These functions control the NVRAM I2C hardware on
// non-intelligent Fibre Host Adapters.
// The primary purpose is to read the HBA's NVRAM to get adapter's
// manufactured WWN to copy into Tachyon chip registers
// Orignal source author unknown
#include <linux/types.h>
enum boolean { FALSE, TRUE } ;
#ifndef UCHAR
typedef __u8 UCHAR;
#endif
#ifndef BOOLEAN
typedef __u8 BOOLEAN;
#endif
#ifndef USHORT
typedef __u16 USHORT;
#endif
#ifndef ULONG
typedef __u32 ULONG;
#endif
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <asm/io.h> // struct pt_regs for IRQ handler & Port I/O
#include "cpqfcTSchip.h"
static void tl_i2c_tx_byte( void* GPIOout, UCHAR data );
/*static BOOLEAN tl_write_i2c_page_portion( void* GPIOin, void* GPIOout,
USHORT startOffset, // e.g. 0x2f for WWN start
USHORT count,
UCHAR *buf );
*/
//
// Tachlite GPIO2, GPIO3 (I2C) DEFINES
// The NVRAM chip NM24C03 defines SCL (serial clock) and SDA (serial data)
// GPIO2 drives SDA, and GPIO3 drives SCL
//
// Since Tachlite inverts the state of the GPIO 0-3 outputs, SET writes 0
// and clear writes 1. The input lines (read in TL status) is NOT inverted
// This really helps confuse the code and debugging.
#define SET_DATA_HI 0x0
#define SET_DATA_LO 0x8
#define SET_CLOCK_HI 0x0
#define SET_CLOCK_LO 0x4
#define SENSE_DATA_HI 0x8
#define SENSE_DATA_LO 0x0
#define SENSE_CLOCK_HI 0x4
#define SENSE_CLOCK_LO 0x0
#define SLAVE_READ_ADDRESS 0xA1
#define SLAVE_WRITE_ADDRESS 0xA0
static void i2c_delay(ULONG mstime);
static void tl_i2c_clock_pulse( UCHAR , void* GPIOout);
static UCHAR tl_read_i2c_data( void* );
//-----------------------------------------------------------------------------
//
// Name: I2C_RX_ACK
//
// This routine receives an acknowledge over the I2C bus.
//
//-----------------------------------------------------------------------------
static unsigned short tl_i2c_rx_ack( void* GPIOin, void* GPIOout )
{
unsigned long value;
// do clock pulse, let data line float high
tl_i2c_clock_pulse( SET_DATA_HI, GPIOout );
// slave must drive data low for acknowledge
value = tl_read_i2c_data( GPIOin);
if (value & SENSE_DATA_HI )
return( FALSE );
return( TRUE );
}
//-----------------------------------------------------------------------------
//
// Name: READ_I2C_REG
//
// This routine reads the I2C control register using the global
// IO address stored in gpioreg.
//
//-----------------------------------------------------------------------------
static UCHAR tl_read_i2c_data( void* gpioreg )
{
return( (UCHAR)(readl( gpioreg ) & 0x08L) ); // GPIO3
}
//-----------------------------------------------------------------------------
//
// Name: WRITE_I2C_REG
//
// This routine writes the I2C control register using the global
// IO address stored in gpioreg.
// In Tachlite, we don't want to modify other bits in TL Control reg.
//
//-----------------------------------------------------------------------------
static void tl_write_i2c_reg( void* gpioregOUT, UCHAR value )
{
ULONG temp;
// First read the register and clear out the old bits
temp = readl( gpioregOUT ) & 0xfffffff3L;
// Now or in the new data and send it back out
writel( temp | value, gpioregOUT);
}
//-----------------------------------------------------------------------------
//
// Name: I2C_TX_START
//
// This routine transmits a start condition over the I2C bus.
// 1. Set SCL (clock, GPIO2) HIGH, set SDA (data, GPIO3) HIGH,
// wait 5us to stabilize.
// 2. With SCL still HIGH, drive SDA low. The low transition marks
// the start condition to NM24Cxx (the chip)
// NOTE! In TL control reg., output 1 means chip sees LOW
//
//-----------------------------------------------------------------------------
static unsigned short tl_i2c_tx_start( void* GPIOin, void* GPIOout )
{
unsigned short i;
ULONG value;
if ( !(tl_read_i2c_data(GPIOin) & SENSE_DATA_HI))
{
// start with clock high, let data float high
tl_write_i2c_reg( GPIOout, SET_DATA_HI | SET_CLOCK_HI );
// keep sending clock pulses if slave is driving data line
for (i = 0; i < 10; i++)
{
tl_i2c_clock_pulse( SET_DATA_HI, GPIOout );
if ( tl_read_i2c_data(GPIOin) & SENSE_DATA_HI )
break;
}
// if he's still driving data low after 10 clocks, abort
value = tl_read_i2c_data( GPIOin ); // read status
if (!(value & 0x08) )
return( FALSE );
}
// To START, bring data low while clock high
tl_write_i2c_reg( GPIOout, SET_CLOCK_HI | SET_DATA_LO );
i2c_delay(0);
return( TRUE ); // TX start successful
}
//-----------------------------------------------------------------------------
//
// Name: I2C_TX_STOP
//
// This routine transmits a stop condition over the I2C bus.
//
//-----------------------------------------------------------------------------
static unsigned short tl_i2c_tx_stop( void* GPIOin, void* GPIOout )
{
int i;
for (i = 0; i < 10; i++)
{
// Send clock pulse, drive data line low
tl_i2c_clock_pulse( SET_DATA_LO, GPIOout );
// To STOP, bring data high while clock high
tl_write_i2c_reg( GPIOout, SET_DATA_HI | SET_CLOCK_HI );
// Give the data line time to float high
i2c_delay(0);
// If slave is driving data line low, there's a problem; retry
if ( tl_read_i2c_data(GPIOin) & SENSE_DATA_HI )
return( TRUE ); // TX STOP successful!
}
return( FALSE ); // error
}
//-----------------------------------------------------------------------------
//
// Name: I2C_TX_uchar
//
// This routine transmits a byte across the I2C bus.
//
//-----------------------------------------------------------------------------
static void tl_i2c_tx_byte( void* GPIOout, UCHAR data )
{
UCHAR bit;
for (bit = 0x80; bit; bit >>= 1)
{
if( data & bit )
tl_i2c_clock_pulse( (UCHAR)SET_DATA_HI, GPIOout);
else
tl_i2c_clock_pulse( (UCHAR)SET_DATA_LO, GPIOout);
}
}
//-----------------------------------------------------------------------------
//
// Name: I2C_RX_uchar
//
// This routine receives a byte across the I2C bus.
//
//-----------------------------------------------------------------------------
static UCHAR tl_i2c_rx_byte( void* GPIOin, void* GPIOout )
{
UCHAR bit;
UCHAR data = 0;
for (bit = 0x80; bit; bit >>= 1) {
// do clock pulse, let data line float high
tl_i2c_clock_pulse( SET_DATA_HI, GPIOout );
// read data line
if ( tl_read_i2c_data( GPIOin) & 0x08 )
data |= bit;
}
return (data);
}
//*****************************************************************************
//*****************************************************************************
// Function: read_i2c_nvram
// Arguments: UCHAR count number of bytes to read
// UCHAR *buf area to store the bytes read
// Returns: 0 - failed
// 1 - success
//*****************************************************************************
//*****************************************************************************
unsigned long cpqfcTS_ReadNVRAM( void* GPIOin, void* GPIOout , USHORT count,
UCHAR *buf )
{
unsigned short i;
if( !( tl_i2c_tx_start(GPIOin, GPIOout) ))
return FALSE;
// Select the NVRAM for "dummy" write, to set the address
tl_i2c_tx_byte( GPIOout , SLAVE_WRITE_ADDRESS );
if ( !tl_i2c_rx_ack(GPIOin, GPIOout ) )
return( FALSE );
// Now send the address where we want to start reading
tl_i2c_tx_byte( GPIOout , 0 );
if ( !tl_i2c_rx_ack(GPIOin, GPIOout ) )
return( FALSE );
// Send a repeated start condition and select the
// slave for reading now.
if( tl_i2c_tx_start(GPIOin, GPIOout) )
tl_i2c_tx_byte( GPIOout, SLAVE_READ_ADDRESS );
if ( !tl_i2c_rx_ack(GPIOin, GPIOout) )
return( FALSE );
// this loop will now read out the data and store it
// in the buffer pointed to by buf
for ( i=0; i<count; i++)
{
*buf++ = tl_i2c_rx_byte(GPIOin, GPIOout);
// Send ACK by holding data line low for 1 clock
if ( i < (count-1) )
tl_i2c_clock_pulse( 0x08, GPIOout );
else {
// Don't send ack for final byte
tl_i2c_clock_pulse( SET_DATA_HI, GPIOout );
}
}
tl_i2c_tx_stop(GPIOin, GPIOout);
return( TRUE );
}
//****************************************************************
//
//
//
// routines to set and clear the data and clock bits
//
//
//
//****************************************************************
static void tl_set_clock(void* gpioreg)
{
ULONG ret_val;
ret_val = readl( gpioreg );
ret_val &= 0xffffffFBL; // clear GPIO2 (SCL)
writel( ret_val, gpioreg);
}
static void tl_clr_clock(void* gpioreg)
{
ULONG ret_val;
ret_val = readl( gpioreg );
ret_val |= SET_CLOCK_LO;
writel( ret_val, gpioreg);
}
//*****************************************************************
//
//
// This routine will advance the clock by one period
//
//
//*****************************************************************
static void tl_i2c_clock_pulse( UCHAR value, void* GPIOout )
{
ULONG ret_val;
// clear the clock bit
tl_clr_clock( GPIOout );
i2c_delay(0);
// read the port to preserve non-I2C bits
ret_val = readl( GPIOout );
// clear the data & clock bits
ret_val &= 0xFFFFFFf3;
// write the value passed in...
// data can only change while clock is LOW!
ret_val |= value; // the data
ret_val |= SET_CLOCK_LO; // the clock
writel( ret_val, GPIOout );
i2c_delay(0);
//set clock bit
tl_set_clock( GPIOout);
}
//*****************************************************************
//
//
// This routine returns the 64-bit WWN
//
//
//*****************************************************************
int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf, UCHAR *buf )
{
ULONG len;
ULONG sub_len;
ULONG ptr_inc;
ULONG i;
ULONG j;
UCHAR *data_ptr;
UCHAR z;
UCHAR name;
UCHAR sub_name;
UCHAR done;
int iReturn=0; // def. 0 offset is failure to find WWN field
data_ptr = (UCHAR *)buf;
done = FALSE;
i = 0;
while ( (i < 128) && (!done) )
{
z = data_ptr[i];\
if ( !(z & 0x80) )
{
len = 1 + (z & 0x07);
name = (z & 0x78) >> 3;
if (name == 0x0F)
done = TRUE;
}
else
{
name = z & 0x7F;
len = 3 + data_ptr[i+1] + (data_ptr[i+2] << 8);
switch (name)
{
case 0x0D:
//
j = i + 3;
//
if ( data_ptr[j] == 0x3b ) {
len = 6;
break;
}
while ( j<(i+len) ) {
sub_name = (data_ptr[j] & 0x3f);
sub_len = data_ptr[j+1] +
(data_ptr[j+2] << 8);
ptr_inc = sub_len + 3;
switch (sub_name)
{
case 0x3C:
memcpy( wwnbuf, &data_ptr[j+3], 8);
iReturn = j+3;
break;
default:
break;
}
j += ptr_inc;
}
break;
default:
break;
}
}
//
i += len;
} // end while
return iReturn;
}
// define a short 5 micro sec delay, and longer (ms) delay
static void i2c_delay(ULONG mstime)
{
ULONG i;
// NOTE: we only expect to use these delays when reading
// our adapter's NVRAM, which happens only during adapter reset.
// Delay technique from "Linux Device Drivers", A. Rubini
// (1st Ed.) pg 137.
// printk(" delay %lx ", mstime);
if( mstime ) // ms delay?
{
// delay technique
for( i=0; i < mstime; i++)
udelay(1000); // 1ms per loop
}
else // 5 micro sec delay
udelay( 5 ); // micro secs
// printk("done\n");
}

File diff suppressed because it is too large Load Diff

View File

@ -1,94 +0,0 @@
// for user apps, make sure data size types are defined
// with
#define CCPQFCTS_IOC_MAGIC 'Z'
typedef struct
{
__u8 bus;
__u8 dev_fn;
__u32 board_id;
} cpqfc_pci_info_struct;
typedef __u32 DriverVer_type;
/*
typedef union
{
struct // Peripheral Unit Device
{
__u8 Bus:6;
__u8 Mode:2; // b00
__u8 Dev;
} PeripDev;
struct // Volume Set Address
{
__u8 DevMSB:6;
__u8 Mode:2; // b01
__u8 DevLSB;
} LogDev;
struct // Logical Unit Device (SCSI-3, SCC-2 defined)
{
__u8 Targ:6;
__u8 Mode:2; // b10
__u8 Dev:5;
__u8 Bus:3;
} LogUnit;
} SCSI3Addr_struct;
typedef struct
{
SCSI3Addr_struct FCP_Nexus;
__u8 cdb[16];
} PassThru_Command_struct;
*/
/* this is nearly duplicated in idashare.h */
typedef struct {
int lc; /* Controller number */
int node; /* Node (box) number */
int ld; /* Logical Drive on this box, if required */
__u32 nexus; /* SCSI Nexus */
void *argp; /* Argument pointer */
} VENDOR_IOCTL_REQ;
typedef struct {
char cdb[16]; /* SCSI CDB for the pass-through */
ushort bus; /* Target bus on the box */
ushort pdrive; /* Physical drive on the box */
int len; /* Length of the data area of the CDB */
int sense_len; /* Length of the sense data */
char sense_data[40]; /* Sense data */
void *bufp; /* Data area for the CDB */
char rw_flag; /* Read CDB or Write CDB */
} cpqfc_passthru_t;
/*
** Defines for the IOCTLS.
*/
#define VENDOR_READ_OPCODE 0x26
#define VENDOR_WRITE_OPCODE 0x27
#define CPQFCTS_GETPCIINFO _IOR( CCPQFCTS_IOC_MAGIC, 1, cpqfc_pci_info_struct)
#define CPQFCTS_GETDRIVVER _IOR( CCPQFCTS_IOC_MAGIC, 9, DriverVer_type)
#define CPQFCTS_SCSI_PASSTHRU _IOWR( CCPQFCTS_IOC_MAGIC,11, VENDOR_IOCTL_REQ)
/* We would rather have equivalent generic, low-level driver agnostic
ioctls that do what CPQFC_IOCTL_FC_TARGET_ADDRESS and
CPQFC_IOCTL_FC_TDR 0x5388 do, but currently, we do not have them,
consequently applications would have to know they are talking to cpqfc. */
/* Used to get Fibre Channel WWN and port_id from device */
// #define CPQFC_IOCTL_FC_TARGET_ADDRESS 0x5387
#define CPQFC_IOCTL_FC_TARGET_ADDRESS \
_IOR( CCPQFCTS_IOC_MAGIC, 13, Scsi_FCTargAddress)
/* Used to invoke Target Defice Reset for Fibre Channel */
// #define CPQFC_IOCTL_FC_TDR 0x5388
#define CPQFC_IOCTL_FC_TDR _IO( CCPQFCTS_IOC_MAGIC, 15)

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
// Routine to trigger Finisar GTA analyzer. Runs of GPIO2
// NOTE: DEBUG ONLY! Could interfere with FCMNGR/Miniport operation
// since it writes directly to the Tachyon board. This function
// developed for Compaq HBA Tachyon TS v1.2 (Rev X5 PCB)
#include "cpqfcTStrigger.h"
#if TRIGGERABLE_HBA
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/io.h>
void TriggerHBA( void* IOBaseUpper, int Print)
{
__u32 long value;
// get initial value in hopes of not modifying any other GPIO line
IOBaseUpper += 0x188; // TachTL/TS Control reg
value = readl( IOBaseUpper);
// set HIGH to trigger external analyzer (tested on Dolche Finisar 1Gb GTA)
// The Finisar anaylzer triggers on low-to-high TTL transition
value |= 0x01; // set bit 0
writel( value, IOBaseUpper);
if( Print)
printk( " -GPIO0 set- ");
}
#endif

View File

@ -1,8 +0,0 @@
// don't do this unless you have the right hardware!
#define TRIGGERABLE_HBA 0
#if TRIGGERABLE_HBA
void TriggerHBA( void*, int);
#else
#define TriggerHBA(x, y)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -976,6 +976,16 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
}
}
static inline void pio_trigger(void)
{
static int feedback_requested;
if (!feedback_requested) {
feedback_requested = 1;
printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> "
"to help improve support for your system.\n", __FILE__);
}
}
/* Prepare SRB for being sent to Device DCB w/ command *cmd */
static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
@ -2320,6 +2330,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
CFG2_WIDEFIFO);
while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) {
u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
pio_trigger();
*(srb->virt_addr)++ = byte;
if (debug_enabled(DBG_PIO))
printk(" %02x", byte);
@ -2331,6 +2342,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
/* Read the last byte ... */
if (srb->total_xfer_length > 0) {
u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
pio_trigger();
*(srb->virt_addr)++ = byte;
srb->total_xfer_length--;
if (debug_enabled(DBG_PIO))
@ -2507,6 +2519,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
if (debug_enabled(DBG_PIO))
printk(" %02x", (unsigned char) *(srb->virt_addr));
pio_trigger();
DC395x_write8(acb, TRM_S1040_SCSI_FIFO,
*(srb->virt_addr)++);

View File

@ -18,7 +18,7 @@
* 20001005 - Initialization fixes for 2.4.0-test9
* Florian Lohoff <flo@rfc822.org>
*
* Copyright (C) 2002, 2003 Maciej W. Rozycki
* Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki
*/
#include <linux/kernel.h>
@ -41,6 +41,7 @@
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/ioasic_ints.h>
#include <asm/dec/machtype.h>
#include <asm/dec/system.h>
#include <asm/dec/tc.h>
#define DEC_SCSI_SREG 0
@ -183,7 +184,8 @@ static int dec_esp_detect(Scsi_Host_Template * tpnt)
esp->dregs = 0;
/* ESP register base */
esp->eregs = (struct ESP_regs *) (system_base + IOASIC_SCSI);
esp->eregs = (void *)CKSEG1ADDR(dec_kn_slot_base +
IOASIC_SCSI);
/* Set the command buffer */
esp->esp_command = (volatile unsigned char *) cmd_buffer;
@ -231,7 +233,8 @@ static int dec_esp_detect(Scsi_Host_Template * tpnt)
esp->slot = CPHYSADDR(mem_start);
esp->dregs = 0;
esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG);
esp->eregs = (void *)CKSEG1ADDR(mem_start +
DEC_SCSI_SREG);
esp->do_pio_cmds = 1;
/* Set the command buffer */
@ -513,14 +516,15 @@ static void dma_advance_sg(struct scsi_cmnd * sp)
static void pmaz_dma_drain(struct NCR_ESP *esp)
{
memcpy(phys_to_virt(esp_virt_buffer),
(void *)KSEG1ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE),
scsi_current_length);
(void *)CKSEG1ADDR(esp->slot + DEC_SCSI_SRAM +
ESP_TGT_DMA_SIZE),
scsi_current_length);
}
static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length)
{
volatile u32 *dmareg =
(volatile u32 *)KSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
(volatile u32 *)CKSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
if (length > ESP_TGT_DMA_SIZE)
length = ESP_TGT_DMA_SIZE;
@ -536,9 +540,10 @@ static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length)
static void pmaz_dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length)
{
volatile u32 *dmareg =
(volatile u32 *)KSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
(volatile u32 *)CKSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
memcpy((void *)KSEG1ADDR(esp->slot + DEC_SCSI_SRAM + ESP_TGT_DMA_SIZE),
memcpy((void *)CKSEG1ADDR(esp->slot + DEC_SCSI_SRAM +
ESP_TGT_DMA_SIZE),
phys_to_virt(vaddress), length);
wmb();

View File

@ -941,8 +941,6 @@ static int eata2x_slave_configure(struct scsi_device *dev)
{
int tqd, utqd;
char *tag_suffix, *link_suffix;
struct Scsi_Host *shost = dev->host;
struct hostdata *ha = (struct hostdata *)shost->hostdata;
utqd = MAX_CMD_PER_LUN;
tqd = max_queue_depth;
@ -973,8 +971,8 @@ static int eata2x_slave_configure(struct scsi_device *dev)
else
link_suffix = "";
printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n",
ha->board_name, shost->host_no, dev->channel, dev->id, dev->lun,
sdev_printk(KERN_INFO, dev,
"cmds/lun %d%s%s.\n",
dev->queue_depth, link_suffix, tag_suffix);
return 0;
@ -1813,9 +1811,8 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
SCpnt->host_scribble = (unsigned char *)&cpp->cpp_index;
if (do_trace)
printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
ha->board_name, i, SCpnt->device->channel, SCpnt->device->id,
SCpnt->device->lun, SCpnt->pid);
scmd_printk(KERN_INFO, SCpnt,
"qcomm, mbox %d, pid %ld.\n", i, SCpnt->pid);
cpp->reqsen = 1;
cpp->dispri = 1;
@ -1847,9 +1844,8 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt,
if (do_dma(shost->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {
unmap_dma(i, ha);
SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
ha->board_name, SCpnt->device->channel, SCpnt->device->id,
SCpnt->device->lun, SCpnt->pid);
scmd_printk(KERN_INFO, SCpnt,
"qcomm, pid %ld, adapter busy.\n", SCpnt->pid);
return 1;
}
@ -1864,16 +1860,14 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
unsigned int i;
if (SCarg->host_scribble == NULL) {
printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
ha->board_name, SCarg->device->channel, SCarg->device->id,
SCarg->device->lun, SCarg->pid);
scmd_printk(KERN_INFO, SCarg,
"abort, pid %ld inactive.\n", SCarg->pid);
return SUCCESS;
}
i = *(unsigned int *)SCarg->host_scribble;
printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
ha->board_name, i, SCarg->device->channel, SCarg->device->id,
SCarg->device->lun, SCarg->pid);
scmd_printk(KERN_WARNING, SCarg,
"abort, mbox %d, pid %ld.\n", i, SCarg->pid);
if (i >= shost->can_queue)
panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name);
@ -1934,9 +1928,8 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
struct Scsi_Host *shost = SCarg->device->host;
struct hostdata *ha = (struct hostdata *)shost->hostdata;
printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n",
ha->board_name, SCarg->device->channel, SCarg->device->id,
SCarg->device->lun, SCarg->pid);
scmd_printk(KERN_INFO, SCarg,
"reset, enter, pid %ld.\n", SCarg->pid);
spin_lock_irq(shost->host_lock);
@ -2253,12 +2246,11 @@ static int reorder(struct hostdata *ha, unsigned long cursec,
k = il[n];
cpp = &ha->cp[k];
SCpnt = cpp->SCpnt;
printk
("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"
scmd_printk(KERN_INFO, SCpnt,
"%s pid %ld mb %d fc %d nr %d sec %ld ns %ld"
" cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n",
(ihdlr ? "ihdlr" : "qcomm"),
SCpnt->device->channel, SCpnt->device->id,
SCpnt->device->lun, SCpnt->pid, k, flushcount,
SCpnt->pid, k, flushcount,
n_ready, SCpnt->request->sector,
SCpnt->request->nr_sectors, cursec, YESNO(s),
YESNO(r), YESNO(rev), YESNO(input_only),
@ -2301,12 +2293,11 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec,
SCpnt = cpp->SCpnt;
if (do_dma(dev->host->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {
printk
("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"
" busy, will abort.\n", ha->board_name,
scmd_printk(KERN_INFO, SCpnt,
"%s, pid %ld, mbox %d, adapter"
" busy, will abort.\n",
(ihdlr ? "ihdlr" : "qcomm"),
SCpnt->device->channel, SCpnt->device->id,
SCpnt->device->lun, SCpnt->pid, k);
SCpnt->pid, k);
ha->cp_stat[k] = ABORTING;
continue;
}
@ -2542,11 +2533,10 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
spp->adapter_status != ASST && ha->iocount <= 1000) ||
do_trace || msg_byte(spp->target_status))
#endif
printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"
" target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
ha->board_name, i, spp->adapter_status, spp->target_status,
SCpnt->device->channel, SCpnt->device->id,
SCpnt->device->lun, SCpnt->pid, reg, ha->iocount);
scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"
" pid %ld, reg 0x%x, count %d.\n",
i, spp->adapter_status, spp->target_status,
SCpnt->pid, reg, ha->iocount);
unmap_dma(i, ha);

View File

@ -384,7 +384,9 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
cp->status = USED; /* claim free slot */
DBG(DBG_QUEUE, printk(KERN_DEBUG "eata_pio_queue pid %ld, target: %x, lun:" " %x, y %d\n", cmd->pid, cmd->device->id, cmd->device->lun, y));
DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
"eata_pio_queue pid %ld, y %d\n",
cmd->pid, y));
cmd->scsi_done = (void *) done;
@ -427,7 +429,9 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) {
cmd->result = DID_BUS_BUSY << 16;
printk(KERN_NOTICE "eata_pio_queue target %d, pid %ld, HBA busy, " "returning DID_BUS_BUSY, done.\n", cmd->device->id, cmd->pid);
scmd_printk(KERN_NOTICE, cmd,
"eata_pio_queue pid %ld, HBA busy, "
"returning DID_BUS_BUSY, done.\n", cmd->pid);
done(cmd);
cp->status = FREE;
return (0);
@ -440,7 +444,9 @@ static int eata_pio_queue(struct scsi_cmnd *cmd,
for (x = 0; x < hd->cppadlen; x++)
outw(0, base + HA_RDATA);
DBG(DBG_QUEUE, printk(KERN_DEBUG "Queued base %#.4lx pid: %ld target: %x " "lun: %x slot %d irq %d\n", (long) sh->base, cmd->pid, cmd->device->id, cmd->device->lun, y, sh->irq));
DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
"Queued base %#.4lx pid: %ld "
"slot %d irq %d\n", (long) sh->base, cmd->pid, y, sh->irq));
return (0);
}
@ -449,8 +455,9 @@ static int eata_pio_abort(struct scsi_cmnd *cmd)
{
uint loop = HZ;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld " "target: %x lun: %x\n", cmd->pid, cmd->device->id, cmd->device->lun));
DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
"eata_pio_abort called pid: %ld\n",
cmd->pid));
while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
if (--loop == 0) {
@ -484,7 +491,9 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
struct scsi_cmnd *sp;
struct Scsi_Host *host = cmd->device->host;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x\n", cmd->pid, cmd->device->id, cmd->device->lun));
DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
"eata_pio_reset called pid:%ld\n",
cmd->pid));
spin_lock_irq(host->host_lock);

View File

@ -671,7 +671,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs)
outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
outb(adapter_mask | (1 << current_SC->device->id), SCSI_Data_NoACK_port);
outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
/* Stop arbitration and enable parity */
outb(0x10 | PARITY_MASK, TMC_Cntl_port);
@ -683,7 +683,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs)
status = inb(SCSI_Status_port);
if (!(status & 0x01)) {
/* Try again, for slow devices */
if (fd_mcs_select(shpnt, current_SC->device->id)) {
if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
#if EVERY_ACCESS
printk(" SFAIL ");
#endif

View File

@ -1154,7 +1154,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id,
outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl);
outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */
outb(adapter_mask | (1 << current_SC->device->id), port_base + SCSI_Data_NoACK);
outb(adapter_mask | (1 << scmd_id(current_SC)), port_base + SCSI_Data_NoACK);
/* Stop arbitration and enable parity */
outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
@ -1166,7 +1166,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id,
status = inb(port_base + SCSI_Status);
if (!(status & 0x01)) {
/* Try again, for slow devices */
if (fdomain_select( current_SC->device->id )) {
if (fdomain_select( scmd_id(current_SC) )) {
#if EVERY_ACCESS
printk( " SFAIL " );
#endif

View File

@ -140,11 +140,11 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
illegal:
SCSI_LOG_ERROR_RECOVERY(1,
dev_printk(KERN_ERR, &shost->shost_gendev,
"Illegal host state transition"
"%s->%s\n",
scsi_host_state_name(oldstate),
scsi_host_state_name(state)));
shost_printk(KERN_ERR, shost,
"Illegal host state transition"
"%s->%s\n",
scsi_host_state_name(oldstate),
scsi_host_state_name(state)));
return -EINVAL;
}
EXPORT_SYMBOL(scsi_host_set_state);

View File

@ -1860,7 +1860,10 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
next_ldn(host_index) = 7;
if (current_ldn == next_ldn(host_index)) { /* One circle done ? */
/* no non-processing ldn found */
printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" " On ldn 7-14 SCSI-commands everywhere in progress.\n" " Reporting DID_NO_CONNECT for device (%d,%d).\n", target, cmd->device->lun);
scmd_printk(KERN_WARNING, cmd,
"IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"
" On ldn 7-14 SCSI-commands everywhere in progress.\n"
" Reporting DID_NO_CONNECT for device.\n");
cmd->result = DID_NO_CONNECT << 16; /* return no connect */
if (done)
done(cmd);

View File

@ -899,7 +899,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
idescsi_pc_t *pc = NULL;
if (!drive) {
printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->device->id);
scmd_printk (KERN_ERR, cmd, "drive not present\n");
goto abort;
}
scsi = drive_to_idescsi(drive);

View File

@ -830,7 +830,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd)
/* Phase 2 - We are now talking to the scsi bus */
case 2:
if (!imm_select(dev, cmd->device->id)) {
if (!imm_select(dev, scmd_id(cmd))) {
imm_fail(dev, DID_NO_CONNECT);
return 0;
}

View File

@ -343,7 +343,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
instance = cmd->device->host;
hostdata = (struct IN2000_hostdata *) instance->hostdata;
DB(DB_QUEUE_COMMAND, printk("Q-%d-%02x-%ld(", cmd->device->id, cmd->cmnd[0], cmd->pid))
DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->pid))
/* Set up a few fields in the Scsi_Cmnd structure for our own use:
* - host_scribble is the pointer to the next cmd in the input queue

View File

@ -1114,9 +1114,8 @@ struct ipr_ucode_image_header {
#define ipr_warn(...) printk(KERN_WARNING IPR_NAME": "__VA_ARGS__)
#define ipr_dbg(...) IPR_DBG_CMD(printk(KERN_INFO IPR_NAME ": "__VA_ARGS__))
#define ipr_sdev_printk(level, sdev, fmt, ...) \
printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, sdev->host->host_no, \
sdev->channel, sdev->id, sdev->lun, ##__VA_ARGS__)
#define ipr_sdev_printk(level, sdev, fmt, args...) \
sdev_printk(level, sdev, fmt, ## args)
#define ipr_sdev_err(sdev, fmt, ...) \
ipr_sdev_printk(KERN_ERR, sdev, fmt, ##__VA_ARGS__)

View File

@ -219,15 +219,12 @@ module_param(ips, charp, 0);
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
#include <linux/blk.h>
#include "sd.h"
#define IPS_SG_ADDRESS(sg) ((sg)->address)
#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
#ifndef __devexit_p
#define __devexit_p(x) x
#endif
#else
#define IPS_SG_ADDRESS(sg) (page_address((sg)->page) ? \
page_address((sg)->page)+(sg)->offset : NULL)
#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
#endif
@ -358,6 +355,9 @@ static int ips_init_phase2(int index);
static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);
static int ips_register_scsi(int index);
static int ips_poll_for_flush_complete(ips_ha_t * ha);
static void ips_flush_and_reset(ips_ha_t *ha);
/*
* global variables
*/
@ -1125,8 +1125,8 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
SC->device->channel, SC->device->id, SC->device->lun);
/* Check for command to initiator IDs */
if ((SC->device->channel > 0)
&& (SC->device->id == ha->ha_id[SC->device->channel])) {
if ((scmd_channel(SC) > 0)
&& (scmd_id(SC) == ha->ha_id[scmd_channel(SC)])) {
SC->result = DID_NO_CONNECT << 16;
done(SC);
@ -1605,6 +1605,8 @@ ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
static int
ips_is_passthru(Scsi_Cmnd * SC)
{
unsigned long flags;
METHOD_TRACE("ips_is_passthru", 1);
if (!SC)
@ -1622,10 +1624,20 @@ ips_is_passthru(Scsi_Cmnd * SC)
return 1;
else if (SC->use_sg) {
struct scatterlist *sg = SC->request_buffer;
char *buffer = IPS_SG_ADDRESS(sg);
char *buffer;
/* kmap_atomic() ensures addressability of the user buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
buffer[2] == 'P' && buffer[3] == 'P')
buffer[2] == 'P' && buffer[3] == 'P') {
kunmap_atomic(buffer - sg->offset, KM_IRQ0);
local_irq_restore(flags);
return 1;
}
kunmap_atomic(buffer - sg->offset, KM_IRQ0);
local_irq_restore(flags);
}
}
return 0;
@ -2830,10 +2842,10 @@ ips_next(ips_ha_t * ha, int intr)
p = ha->scb_waitlist.head;
while ((p) && (scb = ips_getscb(ha))) {
if ((p->device->channel > 0)
if ((scmd_channel(p) > 0)
&& (ha->
dcdb_active[p->device->channel -
1] & (1 << p->device->id))) {
dcdb_active[scmd_channel(p) -
1] & (1 << scmd_id(p)))) {
ips_freescb(ha, scb);
p = (Scsi_Cmnd *) p->host_scribble;
continue;
@ -3656,14 +3668,21 @@ ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data, unsigned
int i;
unsigned int min_cnt, xfer_cnt;
char *cdata = (char *) data;
unsigned char *buffer;
unsigned long flags;
struct scatterlist *sg = scmd->request_buffer;
for (i = 0, xfer_cnt = 0;
(i < scmd->use_sg) && (xfer_cnt < count); i++) {
if (!IPS_SG_ADDRESS(&sg[i]))
return;
min_cnt = min(count - xfer_cnt, sg[i].length);
memcpy(IPS_SG_ADDRESS(&sg[i]), &cdata[xfer_cnt],
min_cnt);
/* kmap_atomic() ensures addressability of the data buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
memcpy(buffer, &cdata[xfer_cnt], min_cnt);
kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
local_irq_restore(flags);
xfer_cnt += min_cnt;
}
@ -3688,14 +3707,21 @@ ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned
int i;
unsigned int min_cnt, xfer_cnt;
char *cdata = (char *) data;
unsigned char *buffer;
unsigned long flags;
struct scatterlist *sg = scmd->request_buffer;
for (i = 0, xfer_cnt = 0;
(i < scmd->use_sg) && (xfer_cnt < count); i++) {
if (!IPS_SG_ADDRESS(&sg[i]))
return;
min_cnt = min(count - xfer_cnt, sg[i].length);
memcpy(&cdata[xfer_cnt], IPS_SG_ADDRESS(&sg[i]),
min_cnt);
/* kmap_atomic() ensures addressability of the data buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
memcpy(&cdata[xfer_cnt], buffer, min_cnt);
kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
local_irq_restore(flags);
xfer_cnt += min_cnt;
}
@ -4807,6 +4833,9 @@ ips_isinit_morpheus(ips_ha_t * ha)
uint32_t bits;
METHOD_TRACE("ips_is_init_morpheus", 1);
if (ips_isintr_morpheus(ha))
ips_flush_and_reset(ha);
post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
bits = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
@ -4819,6 +4848,94 @@ ips_isinit_morpheus(ips_ha_t * ha)
return (1);
}
/****************************************************************************/
/* */
/* Routine Name: ips_flush_and_reset */
/* */
/* Routine Description: */
/* */
/* Perform cleanup ( FLUSH and RESET ) when the adapter is in an unknown */
/* state ( was trying to INIT and an interrupt was already pending ) ... */
/* */
/****************************************************************************/
static void
ips_flush_and_reset(ips_ha_t *ha)
{
ips_scb_t *scb;
int ret;
int time;
int done;
dma_addr_t command_dma;
/* Create a usuable SCB */
scb = pci_alloc_consistent(ha->pcidev, sizeof(ips_scb_t), &command_dma);
if (scb) {
memset(scb, 0, sizeof(ips_scb_t));
ips_init_scb(ha, scb);
scb->scb_busaddr = command_dma;
scb->timeout = ips_cmd_timeout;
scb->cdb[0] = IPS_CMD_FLUSH;
scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
scb->cmd.flush_cache.command_id = IPS_MAX_CMDS; /* Use an ID that would otherwise not exist */
scb->cmd.flush_cache.state = IPS_NORM_STATE;
scb->cmd.flush_cache.reserved = 0;
scb->cmd.flush_cache.reserved2 = 0;
scb->cmd.flush_cache.reserved3 = 0;
scb->cmd.flush_cache.reserved4 = 0;
ret = ips_send_cmd(ha, scb); /* Send the Flush Command */
if (ret == IPS_SUCCESS) {
time = 60 * IPS_ONE_SEC; /* Max Wait time is 60 seconds */
done = 0;
while ((time > 0) && (!done)) {
done = ips_poll_for_flush_complete(ha);
/* This may look evil, but it's only done during extremely rare start-up conditions ! */
udelay(1000);
time--;
}
}
}
/* Now RESET and INIT the adapter */
(*ha->func.reset) (ha);
pci_free_consistent(ha->pcidev, sizeof(ips_scb_t), scb, command_dma);
return;
}
/****************************************************************************/
/* */
/* Routine Name: ips_poll_for_flush_complete */
/* */
/* Routine Description: */
/* */
/* Poll for the Flush Command issued by ips_flush_and_reset() to complete */
/* All other responses are just taken off the queue and ignored */
/* */
/****************************************************************************/
static int
ips_poll_for_flush_complete(ips_ha_t * ha)
{
IPS_STATUS cstatus;
while (TRUE) {
cstatus.value = (*ha->func.statupd) (ha);
if (cstatus.value == 0xffffffff) /* If No Interrupt to process */
break;
/* Success is when we see the Flush Command ID */
if (cstatus.fields.command_id == IPS_MAX_CMDS )
return 1;
}
return 0;
}
/****************************************************************************/
/* */
/* Routine Name: ips_enable_int_copperhead */

3642
drivers/scsi/iscsi_tcp.c Normal file

File diff suppressed because it is too large Load Diff

322
drivers/scsi/iscsi_tcp.h Normal file
View File

@ -0,0 +1,322 @@
/*
* iSCSI Initiator TCP Transport
* Copyright (C) 2004 Dmitry Yusupov
* Copyright (C) 2004 Alex Aizman
* Copyright (C) 2005 Mike Christie
* maintained by open-iscsi@googlegroups.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* See the file COPYING included with this distribution for more details.
*/
#ifndef ISCSI_TCP_H
#define ISCSI_TCP_H
/* Session's states */
#define ISCSI_STATE_FREE 1
#define ISCSI_STATE_LOGGED_IN 2
#define ISCSI_STATE_FAILED 3
#define ISCSI_STATE_TERMINATE 4
/* Connection's states */
#define ISCSI_CONN_INITIAL_STAGE 0
#define ISCSI_CONN_STARTED 1
#define ISCSI_CONN_STOPPED 2
#define ISCSI_CONN_CLEANUP_WAIT 3
/* Connection suspend "bit" */
#define SUSPEND_BIT 1
/* Socket's Receive state machine */
#define IN_PROGRESS_WAIT_HEADER 0x0
#define IN_PROGRESS_HEADER_GATHER 0x1
#define IN_PROGRESS_DATA_RECV 0x2
#define IN_PROGRESS_DDIGEST_RECV 0x3
/* Task Mgmt states */
#define TMABORT_INITIAL 0x0
#define TMABORT_SUCCESS 0x1
#define TMABORT_FAILED 0x2
#define TMABORT_TIMEDOUT 0x3
/* xmit state machine */
#define XMSTATE_IDLE 0x0
#define XMSTATE_R_HDR 0x1
#define XMSTATE_W_HDR 0x2
#define XMSTATE_IMM_HDR 0x4
#define XMSTATE_IMM_DATA 0x8
#define XMSTATE_UNS_INIT 0x10
#define XMSTATE_UNS_HDR 0x20
#define XMSTATE_UNS_DATA 0x40
#define XMSTATE_SOL_HDR 0x80
#define XMSTATE_SOL_DATA 0x100
#define XMSTATE_W_PAD 0x200
#define XMSTATE_DATA_DIGEST 0x400
#define ISCSI_CONN_MAX 1
#define ISCSI_CONN_RCVBUF_MIN 262144
#define ISCSI_CONN_SNDBUF_MIN 262144
#define ISCSI_PAD_LEN 4
#define ISCSI_R2T_MAX 16
#define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */
#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */
#define ISCSI_MGMT_ITT_OFFSET 0xa00
#define ISCSI_SG_TABLESIZE SG_ALL
#define ISCSI_CMD_PER_LUN 128
#define ISCSI_TCP_MAX_CMD_LEN 16
#define ITT_MASK (0xfff)
#define CID_SHIFT 12
#define CID_MASK (0xffff<<CID_SHIFT)
#define AGE_SHIFT 28
#define AGE_MASK (0xf<<AGE_SHIFT)
struct iscsi_queue {
struct kfifo *queue; /* FIFO Queue */
void **pool; /* Pool of elements */
int max; /* Max number of elements */
};
struct iscsi_session;
struct iscsi_cmd_task;
struct iscsi_mgmt_task;
/* Socket connection recieve helper */
struct iscsi_tcp_recv {
struct iscsi_hdr *hdr;
struct sk_buff *skb;
int offset;
int len;
int hdr_offset;
int copy;
int copied;
int padding;
struct iscsi_cmd_task *ctask; /* current cmd in progress */
/* copied and flipped values */
int opcode;
int flags;
int cmd_status;
int ahslen;
int datalen;
uint32_t itt;
int datadgst;
};
struct iscsi_conn {
struct iscsi_hdr hdr; /* header placeholder */
char hdrext[4*sizeof(__u16) +
sizeof(__u32)];
int data_copied;
char *data; /* data placeholder */
struct socket *sock; /* TCP socket */
int data_size; /* actual recv_dlength */
int stop_stage; /* conn_stop() flag: *
* stop to recover, *
* stop to terminate */
/* iSCSI connection-wide sequencing */
uint32_t exp_statsn;
int hdr_size; /* PDU header size */
unsigned long suspend_rx; /* suspend Rx */
struct crypto_tfm *rx_tfm; /* CRC32C (Rx) */
struct crypto_tfm *data_rx_tfm; /* CRC32C (Rx) for data */
/* control data */
int senselen; /* scsi sense length */
int id; /* CID */
struct iscsi_tcp_recv in; /* TCP receive context */
struct iscsi_session *session; /* parent session */
struct list_head item; /* maintains list of conns */
int in_progress; /* connection state machine */
int c_stage; /* connection state */
struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */
struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */
struct iscsi_cmd_task *ctask; /* xmit ctask in progress */
spinlock_t lock; /* FIXME: to be removed */
/* old values for socket callbacks */
void (*old_data_ready)(struct sock *, int);
void (*old_state_change)(struct sock *);
void (*old_write_space)(struct sock *);
/* xmit */
struct crypto_tfm *tx_tfm; /* CRC32C (Tx) */
struct crypto_tfm *data_tx_tfm; /* CRC32C (Tx) for data */
struct kfifo *writequeue; /* write cmds for Data-Outs */
struct kfifo *immqueue; /* immediate xmit queue */
struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */
struct kfifo *xmitqueue; /* data-path cmd queue */
struct work_struct xmitwork; /* per-conn. xmit workqueue */
struct semaphore xmitsema; /* serializes connection xmit,
* access to kfifos: *
* xmitqueue, writequeue, *
* immqueue, mgmtqueue */
unsigned long suspend_tx; /* suspend Tx */
/* abort */
wait_queue_head_t ehwait; /* used in eh_abort() */
struct iscsi_tm tmhdr;
struct timer_list tmabort_timer; /* abort timer */
int tmabort_state; /* see TMABORT_INITIAL, etc.*/
/* negotiated params */
int max_recv_dlength;
int max_xmit_dlength;
int hdrdgst_en;
int datadgst_en;
/* MIB-statistics */
uint64_t txdata_octets;
uint64_t rxdata_octets;
uint32_t scsicmd_pdus_cnt;
uint32_t dataout_pdus_cnt;
uint32_t scsirsp_pdus_cnt;
uint32_t datain_pdus_cnt;
uint32_t r2t_pdus_cnt;
uint32_t tmfcmd_pdus_cnt;
int32_t tmfrsp_pdus_cnt;
/* custom statistics */
uint32_t sendpage_failures_cnt;
uint32_t discontiguous_hdr_cnt;
uint32_t eh_abort_cnt;
};
struct iscsi_session {
/* iSCSI session-wide sequencing */
uint32_t cmdsn;
uint32_t exp_cmdsn;
uint32_t max_cmdsn;
/* configuration */
int initial_r2t_en;
int max_r2t;
int imm_data_en;
int first_burst;
int max_burst;
int time2wait;
int time2retain;
int pdu_inorder_en;
int dataseq_inorder_en;
int erl;
int ifmarker_en;
int ofmarker_en;
/* control data */
struct Scsi_Host *host;
int id;
struct iscsi_conn *leadconn; /* leading connection */
spinlock_t lock; /* protects session state, *
* sequence numbers, *
* session resources: *
* - cmdpool, *
* - mgmtpool, *
* - r2tpool */
int state; /* session state */
struct list_head item;
void *auth_client;
int conn_cnt;
int age; /* counts session re-opens */
struct list_head connections; /* list of connections */
int cmds_max; /* size of cmds array */
struct iscsi_cmd_task **cmds; /* Original Cmds arr */
struct iscsi_queue cmdpool; /* PDU's pool */
int mgmtpool_max; /* size of mgmt array */
struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */
struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */
};
struct iscsi_buf {
struct scatterlist sg;
struct kvec iov;
unsigned int sent;
};
struct iscsi_data_task {
struct iscsi_data hdr; /* PDU */
char hdrext[sizeof(__u32)]; /* Header-Digest */
struct list_head item; /* data queue item */
struct iscsi_buf digestbuf; /* digest buffer */
uint32_t digest; /* data digest */
};
#define ISCSI_DTASK_DEFAULT_MAX ISCSI_SG_TABLESIZE * PAGE_SIZE / 512
struct iscsi_mgmt_task {
struct iscsi_hdr hdr; /* mgmt. PDU */
char hdrext[sizeof(__u32)]; /* Header-Digest */
char *data; /* mgmt payload */
int xmstate; /* mgmt xmit progress */
int data_count; /* counts data to be sent */
struct iscsi_buf headbuf; /* header buffer */
struct iscsi_buf sendbuf; /* in progress buffer */
int sent;
uint32_t itt; /* this ITT */
};
struct iscsi_r2t_info {
__be32 ttt; /* copied from R2T */
__be32 exp_statsn; /* copied from R2T */
uint32_t data_length; /* copied from R2T */
uint32_t data_offset; /* copied from R2T */
struct iscsi_buf headbuf; /* Data-Out Header Buffer */
struct iscsi_buf sendbuf; /* Data-Out in progress buffer*/
int sent; /* R2T sequence progress */
int data_count; /* DATA-Out payload progress */
struct scatterlist *sg; /* per-R2T SG list */
int solicit_datasn;
struct iscsi_data_task *dtask; /* which data task */
};
struct iscsi_cmd_task {
struct iscsi_cmd hdr; /* iSCSI PDU header */
char hdrext[4*sizeof(__u16)+ /* AHS */
sizeof(__u32)]; /* HeaderDigest */
char pad[ISCSI_PAD_LEN];
int itt; /* this ITT */
int datasn; /* DataSN */
struct iscsi_buf headbuf; /* header buf (xmit) */
struct iscsi_buf sendbuf; /* in progress buffer*/
int sent;
struct scatterlist *sg; /* per-cmd SG list */
struct scatterlist *bad_sg; /* assert statement */
int sg_count; /* SG's to process */
uint32_t unsol_datasn;
uint32_t exp_r2tsn;
int xmstate; /* xmit xtate machine */
int imm_count; /* imm-data (bytes) */
int unsol_count; /* unsolicited (bytes)*/
int r2t_data_count; /* R2T Data-Out bytes */
int data_count; /* remaining Data-Out */
int pad_count; /* padded bytes */
struct scsi_cmnd *sc; /* associated SCSI cmd*/
int total_length;
int data_offset;
struct iscsi_conn *conn; /* used connection */
struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */
struct iscsi_r2t_info *r2t; /* in progress R2T */
struct iscsi_queue r2tpool;
struct kfifo *r2tqueue;
struct iscsi_r2t_info **r2ts;
struct list_head dataqueue; /* Data-Out dataqueue */
mempool_t *datapool;
uint32_t datadigest; /* for recover digest */
int digest_count;
uint32_t immdigest; /* for imm data */
struct iscsi_buf immbuf; /* for imm data digest */
struct iscsi_data_task *dtask; /* data task in progress*/
int digest_offset; /* for partial buff digest */
};
#endif /* ISCSI_H */

View File

@ -267,10 +267,6 @@ struct lpfc_hba {
struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
#define LPFC_RPI_HASH_SIZE 64
#define LPFC_RPI_HASH_FUNC(x) ((x) & (0x3f))
/* ptr to active D_ID / RPIs */
struct lpfc_nodelist *fc_nlplookup[LPFC_RPI_HASH_SIZE];
uint32_t wwnn[2];
uint32_t RandomData[7];

View File

@ -200,19 +200,13 @@ lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
}
static ssize_t
lpfc_issue_lip (struct class_device *cdev, const char *buf, size_t count)
static int
lpfc_issue_lip(struct Scsi_Host *host)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0];
int val = 0;
LPFC_MBOXQ_t *pmboxq;
int mbxstatus = MBXERR_ERROR;
if ((sscanf(buf, "%d", &val) != 1) ||
(val != 1))
return -EINVAL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
(phba->hba_state != LPFC_HBA_READY))
return -EPERM;
@ -229,12 +223,12 @@ lpfc_issue_lip (struct class_device *cdev, const char *buf, size_t count)
if (mbxstatus == MBX_TIMEOUT)
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
else
mempool_free( pmboxq, phba->mbox_mem_pool);
mempool_free(pmboxq, phba->mbox_mem_pool);
if (mbxstatus == MBXERR_ERROR)
return -EIO;
return strlen(buf);
return 0;
}
static ssize_t
@ -251,8 +245,6 @@ 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];
if (!phba) return 0;
if (phba->fc_flag & FC_OFFLINE_MODE)
return snprintf(buf, PAGE_SIZE, "0\n");
else
@ -269,7 +261,7 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
int val=0, status=0;
if (sscanf(buf, "%d", &val) != 1)
return 0;
return -EINVAL;
init_completion(&online_compl);
@ -283,7 +275,7 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
if (!status)
return strlen(buf);
else
return 0;
return -EIO;
}
@ -294,47 +286,83 @@ 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];\
int val = 0;\
if (phba){\
val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n",\
phba->cfg_##attr);\
}\
return 0;\
val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%d\n",\
phba->cfg_##attr);\
}
#define lpfc_param_store(attr, minval, maxval) \
#define lpfc_param_hex_show(attr) \
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];\
int val = 0;\
val = phba->cfg_##attr;\
return snprintf(buf, PAGE_SIZE, "%#x\n",\
phba->cfg_##attr);\
}
#define lpfc_param_init(attr, default, minval, maxval) \
static int \
lpfc_##attr##_init(struct lpfc_hba *phba, int val) \
{ \
if (val >= minval && val <= maxval) {\
phba->cfg_##attr = val;\
return 0;\
}\
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
"%d:0449 lpfc_"#attr" attribute cannot be set to %d, "\
"allowed range is ["#minval", "#maxval"]\n", \
phba->brd_no, val); \
phba->cfg_##attr = default;\
return -EINVAL;\
}
#define lpfc_param_set(attr, default, minval, maxval) \
static int \
lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
{ \
if (val >= minval && val <= maxval) {\
phba->cfg_##attr = val;\
return 0;\
}\
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
"%d:0450 lpfc_"#attr" attribute cannot be set to %d, "\
"allowed range is ["#minval", "#maxval"]\n", \
phba->brd_no, val); \
return -EINVAL;\
}
#define lpfc_param_store(attr) \
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];\
int val = 0;\
int val=0;\
if (!isdigit(buf[0]))\
return -EINVAL;\
if (sscanf(buf, "0x%x", &val) != 1)\
if (sscanf(buf, "%d", &val) != 1)\
return -EINVAL;\
if (phba){\
if (val >= minval && val <= maxval) {\
phba->cfg_##attr = val;\
return strlen(buf);\
}\
}\
return 0;\
if (sscanf(buf, "%i", &val) != 1)\
return -EINVAL;\
if (lpfc_##attr##_set(phba, val) == 0) \
return strlen(buf);\
else \
return -EINVAL;\
}
#define LPFC_ATTR_R_NOINIT(name, desc) \
extern int lpfc_##name;\
#define LPFC_ATTR(name, defval, minval, maxval, desc) \
static int lpfc_##name = defval;\
module_param(lpfc_##name, int, 0);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_show(name)\
static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
lpfc_param_init(name, defval, minval, maxval)
#define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
static int lpfc_##name = defval;\
module_param(lpfc_##name, int, 0);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
#define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
@ -342,7 +370,28 @@ static int lpfc_##name = defval;\
module_param(lpfc_##name, int, 0);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_show(name)\
lpfc_param_store(name, minval, maxval)\
lpfc_param_init(name, defval, minval, maxval)\
lpfc_param_set(name, defval, minval, maxval)\
lpfc_param_store(name)\
static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
lpfc_##name##_show, lpfc_##name##_store)
#define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
static int lpfc_##name = defval;\
module_param(lpfc_##name, int, 0);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_hex_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
#define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
static int lpfc_##name = defval;\
module_param(lpfc_##name, int, 0);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_hex_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
lpfc_param_set(name, defval, minval, maxval)\
lpfc_param_store(name)\
static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
lpfc_##name##_show, lpfc_##name##_store)
@ -364,7 +413,6 @@ static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
NULL);
static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
NULL);
static CLASS_DEVICE_ATTR(issue_lip, S_IWUSR, NULL, lpfc_issue_lip);
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
lpfc_board_online_show, lpfc_board_online_store);
@ -388,7 +436,7 @@ static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
# LOG_LIBDFC 0x2000 LIBDFC events
# LOG_ALL_MSG 0xffff LOG all messages
*/
LPFC_ATTR_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask");
LPFC_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask");
/*
# lun_queue_depth: This parameter is used to limit the number of outstanding
@ -419,7 +467,7 @@ LPFC_ATTR_R(scan_down, 1, 0, 1,
/*
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
# until the timer expires. Value range is [0,255]. Default value is 20.
# until the timer expires. Value range is [0,255]. Default value is 30.
# NOTE: this MUST be less then the SCSI Layer command timeout - 1.
*/
LPFC_ATTR_RW(nodev_tmo, 30, 0, 255,
@ -475,14 +523,10 @@ 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.
*/
static int lpfc_cr_delay = 0;
module_param(lpfc_cr_delay, int , 0);
MODULE_PARM_DESC(lpfc_cr_delay, "A count of milliseconds after which an "
LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
"interrupt response is generated");
static int lpfc_cr_count = 1;
module_param(lpfc_cr_count, int, 0);
MODULE_PARM_DESC(lpfc_cr_count, "A count of I/O completions after which an "
LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an"
"interrupt response is generated");
/*
@ -498,9 +542,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.
*/
static int lpfc_discovery_threads = 32;
module_param(lpfc_discovery_threads, int, 0);
MODULE_PARM_DESC(lpfc_discovery_threads, "Maximum number of ELS commands "
LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands"
"during discovery");
/*
@ -537,7 +579,6 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_max_luns,
&class_device_attr_nport_evt_cnt,
&class_device_attr_management_version,
&class_device_attr_issue_lip,
&class_device_attr_board_online,
NULL,
};
@ -992,7 +1033,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
struct fc_host_statistics *hs = &phba->link_stats;
LPFC_MBOXQ_t *pmboxq;
MAILBOX_t *pmb;
int rc=0;
int rc = 0;
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmboxq)
@ -1005,18 +1046,16 @@ lpfc_get_stats(struct Scsi_Host *shost)
pmboxq->context1 = NULL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE))){
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
} else
else
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
if (rc != MBX_SUCCESS) {
if (pmboxq) {
if (rc == MBX_TIMEOUT)
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
else
mempool_free( pmboxq, phba->mbox_mem_pool);
}
if (rc == MBX_TIMEOUT)
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
else
mempool_free(pmboxq, phba->mbox_mem_pool);
return NULL;
}
@ -1027,24 +1066,22 @@ lpfc_get_stats(struct Scsi_Host *shost)
hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256);
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
pmb->mbxCommand = MBX_READ_LNK_STAT;
pmb->mbxOwner = OWN_HOST;
pmboxq->context1 = NULL;
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE))) {
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
} else
else
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
if (rc != MBX_SUCCESS) {
if (pmboxq) {
if (rc == MBX_TIMEOUT)
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
else
mempool_free( pmboxq, phba->mbox_mem_pool);
}
if (rc == MBX_TIMEOUT)
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
else
mempool_free( pmboxq, phba->mbox_mem_pool);
return NULL;
}
@ -1234,25 +1271,27 @@ struct fc_function_template lpfc_transport_functions = {
.get_starget_port_name = lpfc_get_starget_port_name,
.show_starget_port_name = 1,
.issue_fc_host_lip = lpfc_issue_lip,
};
void
lpfc_get_cfgparam(struct lpfc_hba *phba)
{
phba->cfg_log_verbose = lpfc_log_verbose;
phba->cfg_cr_delay = lpfc_cr_delay;
phba->cfg_cr_count = lpfc_cr_count;
phba->cfg_lun_queue_depth = lpfc_lun_queue_depth;
phba->cfg_fcp_class = lpfc_fcp_class;
phba->cfg_use_adisc = lpfc_use_adisc;
phba->cfg_ack0 = lpfc_ack0;
phba->cfg_topology = lpfc_topology;
phba->cfg_scan_down = lpfc_scan_down;
phba->cfg_nodev_tmo = lpfc_nodev_tmo;
phba->cfg_link_speed = lpfc_link_speed;
phba->cfg_fdmi_on = lpfc_fdmi_on;
phba->cfg_discovery_threads = lpfc_discovery_threads;
phba->cfg_max_luns = lpfc_max_luns;
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_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);
lpfc_ack0_init(phba, lpfc_ack0);
lpfc_topology_init(phba, lpfc_topology);
lpfc_scan_down_init(phba, lpfc_scan_down);
lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
lpfc_link_speed_init(phba, lpfc_link_speed);
lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
lpfc_max_luns_init(phba, lpfc_max_luns);
/*
* The total number of segments is the configuration value plus 2

View File

@ -62,10 +62,6 @@ void lpfc_disc_timeout(unsigned long);
void lpfc_scan_timeout(unsigned long);
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
struct lpfc_nodelist *lpfc_findnode_remove_rpi(struct lpfc_hba * phba,
uint16_t rpi);
void lpfc_addnode_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
uint16_t rpi);
int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
int lpfc_do_work(void *);
@ -147,6 +143,9 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *);
void lpfc_mem_free(struct lpfc_hba *);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
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);
@ -182,15 +181,11 @@ struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order,
int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
uint32_t timeout);
int lpfc_sli_issue_iocb_wait_high_priority(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * piocb,
uint32_t flag,
struct lpfc_iocbq * prspiocbq,
uint32_t timeout);
void lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
struct lpfc_iocbq * queue1,
struct lpfc_iocbq * queue2);
int lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * piocb,
struct lpfc_iocbq * prspiocbq,
uint32_t timeout);
void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb);

View File

@ -224,18 +224,16 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
IOCB_t *icmd;
struct lpfc_iocbq *geniocb = NULL;
struct lpfc_iocbq *geniocb;
/* Allocate buffer for command iocb */
spin_lock_irq(phba->host->host_lock);
list_remove_head(lpfc_iocb_list, geniocb, struct lpfc_iocbq, list);
geniocb = lpfc_sli_get_iocbq(phba);
spin_unlock_irq(phba->host->host_lock);
if (geniocb == NULL)
return 1;
memset(geniocb, 0, sizeof (struct lpfc_iocbq));
icmd = &geniocb->iocb;
icmd->un.genreq64.bdl.ulpIoTag32 = 0;
@ -279,7 +277,7 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
spin_lock_irq(phba->host->host_lock);
if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) {
list_add_tail(&geniocb->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, geniocb);
spin_unlock_irq(phba->host->host_lock);
return 1;
}
@ -487,7 +485,7 @@ out:
kfree(inp);
kfree(bmp);
spin_lock_irq(phba->host->host_lock);
list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
@ -526,7 +524,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
kfree(inp);
kfree(bmp);
spin_lock_irq(phba->host->host_lock);
list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
@ -735,7 +733,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
kfree(inp);
kfree(bmp);
spin_lock_irq(phba->host->host_lock);
list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}

View File

@ -70,7 +70,6 @@ struct lpfc_nodelist {
struct timer_list nlp_tmofunc; /* Used for nodev tmo */
struct fc_rport *rport; /* Corresponding FC transport
port structure */
struct lpfc_nodelist *nlp_rpi_hash_next;
struct lpfc_hba *nlp_phba;
struct lpfc_work_evt nodev_timeout_evt;
struct lpfc_work_evt els_retry_evt;

View File

@ -102,9 +102,8 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
uint16_t cmdSize,
uint8_t retry, struct lpfc_nodelist * ndlp, uint32_t elscmd)
{
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *elsiocb = NULL;
struct lpfc_iocbq *elsiocb;
struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
struct ulp_bde64 *bpl;
IOCB_t *icmd;
@ -114,15 +113,13 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
if (phba->hba_state < LPFC_LINK_UP)
return NULL;
/* Allocate buffer for command iocb */
spin_lock_irq(phba->host->host_lock);
list_remove_head(lpfc_iocb_list, elsiocb, struct lpfc_iocbq, list);
elsiocb = lpfc_sli_get_iocbq(phba);
spin_unlock_irq(phba->host->host_lock);
if (elsiocb == NULL)
return NULL;
memset(elsiocb, 0, sizeof (struct lpfc_iocbq));
icmd = &elsiocb->iocb;
/* fill in BDEs for command */
@ -133,7 +130,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
if (pcmd)
kfree(pcmd);
list_add_tail(&elsiocb->list, lpfc_iocb_list);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, elsiocb);
spin_unlock_irq(phba->host->host_lock);
return NULL;
}
@ -150,7 +149,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
kfree(prsp);
lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
kfree(pcmd);
list_add_tail(&elsiocb->list, lpfc_iocb_list);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, elsiocb);
spin_unlock_irq(phba->host->host_lock);
return NULL;
}
INIT_LIST_HEAD(&prsp->list);
@ -164,7 +165,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&pbuflist->phys);
if (pbuflist == 0 || pbuflist->virt == 0) {
list_add_tail(&elsiocb->list, lpfc_iocb_list);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, elsiocb);
spin_unlock_irq(phba->host->host_lock);
lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
kfree(pcmd);
@ -596,10 +599,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba)
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else {
list_add_tail(&iocb->list,
&phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, iocb);
}
}
}
@ -1713,7 +1714,7 @@ lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb)
kfree(buf_ptr);
}
spin_lock_irq(phba->host->host_lock);
list_add_tail(&elsiocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, elsiocb);
spin_unlock_irq(phba->host->host_lock);
return 0;
}
@ -2929,9 +2930,8 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
spin_unlock_irq(phba->host->host_lock);
(piocb->iocb_cmpl) (phba, piocb, piocb);
spin_lock_irq(phba->host->host_lock);
} else {
list_add_tail(&piocb->list, &phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, piocb);
}
if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) {
phba->els_tmofunc.expires = jiffies + HZ * timeout;
@ -2996,7 +2996,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
spin_lock_irq(phba->host->host_lock);
}
else
list_add_tail(&piocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, piocb);
}
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
@ -3033,7 +3033,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
spin_lock_irq(phba->host->host_lock);
}
else
list_add_tail(&piocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, piocb);
}
spin_unlock_irq(phba->host->host_lock);
return;

View File

@ -890,10 +890,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
pmb->context1 = NULL;
if (ndlp->nlp_rpi != 0)
lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
@ -981,10 +978,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
pmb->context1 = NULL;
if (ndlp->nlp_rpi != 0)
lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
@ -1028,6 +1022,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
scsi_block_requests(phba->host);
ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
if (!rport) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,
@ -1044,6 +1039,23 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
}
rdata = rport->dd_data;
rdata->pnode = ndlp;
scsi_unblock_requests(phba->host);
return;
}
static void
lpfc_unregister_remote_port(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp)
{
struct fc_rport *rport = ndlp->rport;
struct lpfc_rport_data *rdata = rport->dd_data;
ndlp->rport = NULL;
rdata->pnode = NULL;
scsi_block_requests(phba->host);
fc_remote_port_delete(rport);
scsi_unblock_requests(phba->host);
return;
}
@ -1260,7 +1272,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
* may have removed the remote port.
*/
if ((rport_del != none) && nlp->rport)
fc_remote_port_block(nlp->rport);
lpfc_unregister_remote_port(phba, nlp);
if (rport_add != none) {
/*
@ -1270,8 +1282,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
*/
if (!nlp->rport)
lpfc_register_remote_port(phba, nlp);
else
fc_remote_port_unblock(nlp->rport);
/*
* if we added to Mapped list, but the remote port
@ -1435,10 +1445,9 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
iocb, iocb);
spin_lock_irq(phba->host->
host_lock);
} else {
list_add_tail(&iocb->list,
&phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba,
iocb);
}
}
spin_unlock_irq(phba->host->host_lock);
@ -1472,7 +1481,6 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
if (rc == MBX_NOT_FINISHED)
mempool_free( mbox, phba->mbox_mem_pool);
}
lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
lpfc_no_rpi(phba, ndlp);
ndlp->nlp_rpi = 0;
return 1;
@ -1490,7 +1498,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
LPFC_MBOXQ_t *mb;
LPFC_MBOXQ_t *nextmb;
struct lpfc_dmabuf *mp;
struct fc_rport *rport;
/* Cleanup node for NPort <nlp_DID> */
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
@ -1507,10 +1514,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
* and flush cache's w/o generating flush errors.
*/
if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
rport = ndlp->rport;
ndlp->rport = NULL;
fc_remote_port_unblock(rport);
fc_remote_port_delete(rport);
lpfc_unregister_remote_port(phba, ndlp);
ndlp->nlp_sid = NLP_NO_SID;
}
@ -2422,10 +2426,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
pmb->context1 = NULL;
if (ndlp->nlp_rpi != 0)
lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
@ -2451,75 +2452,28 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/*
* This routine looks up the ndlp hash
* table for the given RPI. If rpi found
* This routine looks up the ndlp lists
* for the given RPI. If rpi found
* it return the node list pointer
* else return 0.
* else return NULL.
*/
struct lpfc_nodelist *
lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
{
struct lpfc_nodelist *ret;
struct lpfc_nodelist *ndlp;
struct list_head * lists[]={&phba->fc_nlpunmap_list,
&phba->fc_nlpmap_list,
&phba->fc_plogi_list,
&phba->fc_adisc_list,
&phba->fc_reglogin_list};
int i;
ret = phba->fc_nlplookup[LPFC_RPI_HASH_FUNC(rpi)];
while ((ret != 0) && (ret->nlp_rpi != rpi)) {
ret = ret->nlp_rpi_hash_next;
}
return ret;
}
for (i = 0; i < ARRAY_SIZE(lists); i++ )
list_for_each_entry(ndlp, lists[i], nlp_listp)
if (ndlp->nlp_rpi == rpi)
return (ndlp);
/*
* This routine looks up the ndlp hash table for the
* given RPI. If rpi found it return the node list
* pointer else return 0 after deleting the entry
* from hash table.
*/
struct lpfc_nodelist *
lpfc_findnode_remove_rpi(struct lpfc_hba * phba, uint16_t rpi)
{
struct lpfc_nodelist *ret, *temp;;
ret = phba->fc_nlplookup[LPFC_RPI_HASH_FUNC(rpi)];
if (ret == 0)
return NULL;
if (ret->nlp_rpi == rpi) {
phba->fc_nlplookup[LPFC_RPI_HASH_FUNC(rpi)] =
ret->nlp_rpi_hash_next;
ret->nlp_rpi_hash_next = NULL;
return ret;
}
while ((ret->nlp_rpi_hash_next != 0) &&
(ret->nlp_rpi_hash_next->nlp_rpi != rpi)) {
ret = ret->nlp_rpi_hash_next;
}
if (ret->nlp_rpi_hash_next != 0) {
temp = ret->nlp_rpi_hash_next;
ret->nlp_rpi_hash_next = temp->nlp_rpi_hash_next;
temp->nlp_rpi_hash_next = NULL;
return temp;
} else {
return NULL;
}
}
/*
* This routine adds the node list entry to the
* ndlp hash table.
*/
void
lpfc_addnode_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
uint16_t rpi)
{
uint32_t index;
index = LPFC_RPI_HASH_FUNC(rpi);
ndlp->nlp_rpi_hash_next = phba->fc_nlplookup[index];
phba->fc_nlplookup[index] = ndlp;
return;
return NULL;
}
void

View File

@ -537,12 +537,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
lpfc_offline(phba);
/*
* Restart all traffic to this host. Since the fc_transport
* block functions (future) were not called in lpfc_offline,
* don't call them here.
*/
scsi_unblock_requests(phba->host);
}
}
@ -772,10 +766,12 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
{
lpfc_vpd_t *vp;
uint32_t id;
uint8_t hdrtype;
char str[16];
vp = &phba->vpd;
pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id);
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
switch ((id >> 16) & 0xffff) {
case PCI_DEVICE_ID_FIREFLY:
@ -803,7 +799,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
strcpy(str, "LP9802 2");
break;
case PCI_DEVICE_ID_THOR:
strcpy(str, "LP10000 2");
if (hdrtype == 0x80)
strcpy(str, "LP10000DC 2");
else
strcpy(str, "LP10000 2");
break;
case PCI_DEVICE_ID_VIPER:
strcpy(str, "LPX1000 10");
@ -812,10 +811,16 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
strcpy(str, "LP982 2");
break;
case PCI_DEVICE_ID_TFLY:
strcpy(str, "LP1050 2");
if (hdrtype == 0x80)
strcpy(str, "LP1050DC 2");
else
strcpy(str, "LP1050 2");
break;
case PCI_DEVICE_ID_HELIOS:
strcpy(str, "LP11000 4");
if (hdrtype == 0x80)
strcpy(str, "LP11002 4");
else
strcpy(str, "LP11000 4");
break;
case PCI_DEVICE_ID_BMID:
strcpy(str, "LP1150 4");
@ -824,13 +829,16 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
strcpy(str, "LP111 4");
break;
case PCI_DEVICE_ID_ZEPHYR:
strcpy(str, "LP11000e 4");
if (hdrtype == 0x80)
strcpy(str, "LPe11002 4");
else
strcpy(str, "LPe11000 4");
break;
case PCI_DEVICE_ID_ZMID:
strcpy(str, "LP1150e 4");
strcpy(str, "LPe1150 4");
break;
case PCI_DEVICE_ID_ZSMB:
strcpy(str, "LP111e 4");
strcpy(str, "LPe111 4");
break;
case PCI_DEVICE_ID_LP101:
strcpy(str, "LP101 2");
@ -862,8 +870,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
int type)
{
IOCB_t *icmd;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq *iocb = NULL;
struct lpfc_iocbq *iocb;
struct lpfc_dmabuf *mp1, *mp2;
cnt += pring->missbufcnt;
@ -872,13 +879,12 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
while (cnt > 0) {
/* Allocate buffer for command iocb */
spin_lock_irq(phba->host->host_lock);
list_remove_head(lpfc_iocb_list, iocb, struct lpfc_iocbq, list);
iocb = lpfc_sli_get_iocbq(phba);
spin_unlock_irq(phba->host->host_lock);
if (iocb == NULL) {
pring->missbufcnt = cnt;
return cnt;
}
memset(iocb, 0, sizeof (struct lpfc_iocbq));
icmd = &iocb->iocb;
/* 2 buffers can be posted per command */
@ -891,7 +897,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
if (mp1)
kfree(mp1);
spin_lock_irq(phba->host->host_lock);
list_add_tail(&iocb->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, iocb);
spin_unlock_irq(phba->host->host_lock);
pring->missbufcnt = cnt;
return cnt;
@ -910,7 +916,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
kfree(mp1);
spin_lock_irq(phba->host->host_lock);
list_add_tail(&iocb->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, iocb);
spin_unlock_irq(phba->host->host_lock);
pring->missbufcnt = cnt;
return cnt;
@ -947,7 +953,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
kfree(mp2);
cnt++;
}
list_add_tail(&iocb->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, iocb);
pring->missbufcnt = cnt;
spin_unlock_irq(phba->host->host_lock);
return cnt;
@ -1226,12 +1232,6 @@ lpfc_online(struct lpfc_hba * phba)
phba->fc_flag &= ~FC_OFFLINE_MODE;
spin_unlock_irq(phba->host->host_lock);
/*
* Restart all traffic to this host. Since the fc_transport block
* functions (future) were not called in lpfc_offline, don't call them
* here.
*/
scsi_unblock_requests(phba->host);
return 0;
}
@ -1249,13 +1249,6 @@ lpfc_offline(struct lpfc_hba * phba)
if (phba->fc_flag & FC_OFFLINE_MODE)
return 0;
/*
* Don't call the fc_transport block api (future). The device is
* going offline and causing a timer to fire in the midlayer is
* unproductive. Just block all new requests until the driver
* comes back online.
*/
scsi_block_requests(phba->host);
psli = &phba->sli;
pring = &psli->ring[psli->fcp_ring];
@ -1333,6 +1326,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
unsigned long bar0map_len, bar2map_len;
int error = -ENODEV, retval;
int i;
uint16_t iotag;
if (pci_enable_device(pdev))
goto out;
@ -1434,6 +1428,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (!phba->slim2p)
goto out_iounmap;
memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
/* Initialize the SLI Layer to run with lpfc HBAs. */
lpfc_sli_setup(phba);
@ -1456,6 +1451,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
}
memset(iocbq_entry, 0, sizeof(struct lpfc_iocbq));
iotag = lpfc_sli_next_iotag(phba, iocbq_entry);
if (iotag == 0) {
kfree (iocbq_entry);
printk(KERN_ERR "%s: failed to allocate IOTAG. "
"Unloading driver.\n",
__FUNCTION__);
error = -ENOMEM;
goto out_free_iocbq;
}
spin_lock_irq(phba->host->host_lock);
list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
phba->total_iocbq_bufs++;
@ -1702,6 +1706,7 @@ MODULE_DEVICE_TABLE(pci, lpfc_id_table);
static struct pci_driver lpfc_driver = {
.name = LPFC_DRIVER_NAME,
.owner = THIS_MODULE,
.id_table = lpfc_id_table,
.probe = lpfc_pci_probe_one,
.remove = __devexit_p(lpfc_pci_remove_one),

View File

@ -531,6 +531,7 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
size_t offset;
struct lpfc_hgp hgp;
void __iomem *to_slim;
int i;
memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
mb->mbxCommand = MBX_CONFIG_PORT;
@ -587,7 +588,11 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
/* write HGP data to SLIM at the required longword offset */
memset(&hgp, 0, sizeof(struct lpfc_hgp));
to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp));
for (i=0; i < phba->sli.num_rings; i++) {
lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp));
to_slim += sizeof (struct lpfc_hgp);
}
/* Setup Port Group ring pointer */
offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -

View File

@ -187,10 +187,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else {
list_add_tail(&iocb->list,
&phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, iocb);
break;
}
}
@ -232,10 +230,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else {
list_add_tail(&iocb->list,
&phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, iocb);
break;
}
}
@ -1086,11 +1082,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
return (ndlp->nlp_state);
}
if (ndlp->nlp_rpi != 0)
lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
/* Only if we are not a fabric nport do we issue PRLI */
if (!(ndlp->nlp_type & NLP_FABRIC)) {
@ -1593,12 +1585,7 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
pmb = (LPFC_MBOXQ_t *) arg;
mb = &pmb->mb;
/* save rpi */
if (ndlp->nlp_rpi != 0)
lpfc_findnode_remove_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = mb->un.varWords[0];
lpfc_addnode_rpi(phba, ndlp, ndlp->nlp_rpi);
return (ndlp->nlp_state);
}

View File

@ -50,12 +50,13 @@
* and the BPL BDE is setup in the IOCB.
*/
static struct lpfc_scsi_buf *
lpfc_get_scsi_buf(struct lpfc_hba * phba)
lpfc_new_scsi_buf(struct lpfc_hba * phba)
{
struct lpfc_scsi_buf *psb;
struct ulp_bde64 *bpl;
IOCB_t *iocb;
dma_addr_t pdma_phys;
uint16_t iotag;
psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
if (!psb)
@ -79,6 +80,16 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
/* Initialize virtual ptrs to dma_buf region. */
memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
/* Allocate iotag for psb->cur_iocbq. */
iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq);
if (iotag == 0) {
pci_pool_free(phba->lpfc_scsi_dma_buf_pool,
psb->data, psb->dma_handle);
kfree (psb);
return NULL;
}
psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
psb->fcp_cmnd = psb->data;
psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd);
psb->fcp_bpl = psb->data + sizeof(struct fcp_cmnd) +
@ -125,11 +136,19 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
return psb;
}
static void
lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
struct lpfc_scsi_buf*
lpfc_sli_get_scsi_buf(struct lpfc_hba * phba)
{
struct lpfc_hba *phba = psb->scsi_hba;
struct lpfc_scsi_buf * lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
return lpfc_cmd;
}
static void
lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
{
/*
* There are only two special cases to consider. (1) the scsi command
* requested scatter-gather usage or (2) the scsi command allocated
@ -147,6 +166,7 @@ lpfc_free_scsi_buf(struct lpfc_scsi_buf * psb)
}
}
psb->pCmd = NULL;
list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
}
@ -403,14 +423,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
break;
}
if (pnode) {
if (pnode->nlp_state != NLP_STE_MAPPED_NODE)
cmd->result = ScsiResult(DID_BUS_BUSY,
SAM_STAT_BUSY);
}
else {
cmd->result = ScsiResult(DID_NO_CONNECT, 0);
}
if ((pnode == NULL )
|| (pnode->nlp_state != NLP_STE_MAPPED_NODE))
cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
} else {
cmd->result = ScsiResult(DID_OK, 0);
}
@ -426,12 +441,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
*lp, *(lp + 3), cmd->retries, cmd->resid);
}
spin_lock_irqsave(phba->host->host_lock, iflag);
lpfc_free_scsi_buf(lpfc_cmd);
cmd->host_scribble = NULL;
spin_unlock_irqrestore(phba->host->host_lock, iflag);
cmd->scsi_done(cmd);
spin_lock_irqsave(phba->host->host_lock, iflag);
lpfc_release_scsi_buf(phba, lpfc_cmd);
spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
static void
@ -539,7 +553,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
struct lpfc_rport_data *rdata = scsi_dev->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
if ((ndlp == 0) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
return 0;
}
@ -618,8 +632,7 @@ static int
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
{
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *iocbqrsp = NULL;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq *iocbqrsp;
int ret;
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
@ -628,17 +641,14 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
lpfc_cmd->scsi_hba = phba;
iocbq = &lpfc_cmd->cur_iocbq;
list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list);
iocbqrsp = lpfc_sli_get_iocbq(phba);
if (!iocbqrsp)
return FAILED;
memset(iocbqrsp, 0, sizeof (struct lpfc_iocbq));
iocbq->iocb_flag |= LPFC_IO_POLL;
ret = lpfc_sli_issue_iocb_wait_high_priority(phba,
&phba->sli.ring[phba->sli.fcp_ring],
iocbq, SLI_IOCB_HIGH_PRIORITY,
iocbqrsp,
lpfc_cmd->timeout);
ret = lpfc_sli_issue_iocb_wait(phba,
&phba->sli.ring[phba->sli.fcp_ring],
iocbq, iocbqrsp, lpfc_cmd->timeout);
if (ret != IOCB_SUCCESS) {
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
ret = FAILED;
@ -651,45 +661,10 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
}
/*
* All outstanding txcmplq I/Os should have been aborted by the target.
* Unfortunately, some targets do not abide by this forcing the driver
* to double check.
*/
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
lpfc_cmd->pCmd->device->id,
lpfc_cmd->pCmd->device->lun, 0, LPFC_CTX_TGT);
/* Return response IOCB to free list. */
list_add_tail(&iocbqrsp->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, iocbqrsp);
return ret;
}
static void
lpfc_scsi_cmd_iocb_cleanup (struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_iocbq *pIocbOut)
{
unsigned long iflag;
struct lpfc_scsi_buf *lpfc_cmd =
(struct lpfc_scsi_buf *) pIocbIn->context1;
spin_lock_irqsave(phba->host->host_lock, iflag);
lpfc_free_scsi_buf(lpfc_cmd);
spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
static void
lpfc_scsi_cmd_iocb_cmpl_aborted(struct lpfc_hba *phba,
struct lpfc_iocbq *pIocbIn,
struct lpfc_iocbq *pIocbOut)
{
struct scsi_cmnd *ml_cmd =
((struct lpfc_scsi_buf *) pIocbIn->context1)->pCmd;
lpfc_scsi_cmd_iocb_cleanup (phba, pIocbIn, pIocbOut);
ml_cmd->host_scribble = NULL;
}
const char *
lpfc_info(struct Scsi_Host *host)
{
@ -726,43 +701,25 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
struct lpfc_sli *psli = &phba->sli;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
struct lpfc_scsi_buf *lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
int err = 0;
struct lpfc_scsi_buf *lpfc_cmd;
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
int err;
/*
* The target pointer is guaranteed not to be NULL because the driver
* only clears the device->hostdata field in lpfc_slave_destroy. This
* approach guarantees no further IO calls on this target.
*/
if (!ndlp) {
cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
err = fc_remote_port_chkready(rport);
if (err) {
cmnd->result = err;
goto out_fail_command;
}
/*
* A Fibre Channel target is present and functioning only when the node
* state is MAPPED. Any other state is a failure.
* Catch race where our node has transitioned, but the
* transport is still transitioning.
*/
if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) {
if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
(ndlp->nlp_state == NLP_STE_UNUSED_NODE)) {
cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
goto out_fail_command;
}
else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
goto out_fail_command;
}
/*
* The device is most likely recovered and the driver
* needs a bit more time to finish. Ask the midlayer
* to retry.
*/
goto out_host_busy;
if (!ndlp) {
cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
goto out_fail_command;
}
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
if (lpfc_cmd == NULL) {
printk(KERN_WARNING "%s: No buffer available - list empty, "
"total count %d\n", __FUNCTION__, phba->total_scsi_bufs);
@ -792,7 +749,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
return 0;
out_host_busy_free_buf:
lpfc_free_scsi_buf(lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
cmnd->host_scribble = NULL;
out_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
@ -808,119 +765,92 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
struct lpfc_hba *phba =
(struct lpfc_hba *)cmnd->device->host->hostdata[0];
struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
struct lpfc_iocbq *iocb, *next_iocb;
struct lpfc_iocbq *abtsiocb = NULL;
struct lpfc_iocbq *iocb;
struct lpfc_iocbq *abtsiocb;
struct lpfc_scsi_buf *lpfc_cmd;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
IOCB_t *cmd, *icmd;
unsigned long snum;
unsigned int id, lun;
unsigned int loop_count = 0;
int ret = IOCB_SUCCESS;
int ret = SUCCESS;
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
BUG_ON(!lpfc_cmd);
/*
* If the host_scribble data area is NULL, then the driver has already
* completed this command, but the midlayer did not see the completion
* before the eh fired. Just return SUCCESS.
* If pCmd field of the corresponding lpfc_scsi_buf structure
* points to a different SCSI command, then the driver has
* already completed this command, but the midlayer did not
* see the completion before the eh fired. Just return
* SUCCESS.
*/
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
if (!lpfc_cmd)
return SUCCESS;
iocb = &lpfc_cmd->cur_iocbq;
if (lpfc_cmd->pCmd != cmnd)
goto out;
/* save these now since lpfc_cmd can be freed */
id = lpfc_cmd->pCmd->device->id;
lun = lpfc_cmd->pCmd->device->lun;
snum = lpfc_cmd->pCmd->serial_number;
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
cmd = &iocb->iocb;
if (iocb->context1 != lpfc_cmd)
continue;
list_del_init(&iocb->list);
pring->txq_cnt--;
if (!iocb->iocb_cmpl) {
list_add_tail(&iocb->list, lpfc_iocb_list);
}
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
lpfc_scsi_cmd_iocb_cmpl_aborted(phba, iocb, iocb);
}
BUG_ON(iocb->context1 != lpfc_cmd);
abtsiocb = lpfc_sli_get_iocbq(phba);
if (abtsiocb == NULL) {
ret = FAILED;
goto out;
}
list_remove_head(lpfc_iocb_list, abtsiocb, struct lpfc_iocbq, list);
if (abtsiocb == NULL)
return FAILED;
memset(abtsiocb, 0, sizeof (struct lpfc_iocbq));
/*
* The scsi command was not in the txq. Check the txcmplq and if it is
* found, send an abort to the FW.
* The scsi command can not be in txq and it is in flight because the
* pCmd is still pointig at the SCSI command we have to abort. There
* is no need to search the txcmplq. Just send an abort to the FW.
*/
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
if (iocb->context1 != lpfc_cmd)
continue;
iocb->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl_aborted;
cmd = &iocb->iocb;
icmd = &abtsiocb->iocb;
icmd->un.acxri.abortType = ABORT_TYPE_ABTS;
icmd->un.acxri.abortContextTag = cmd->ulpContext;
icmd->un.acxri.abortIoTag = cmd->ulpIoTag;
cmd = &iocb->iocb;
icmd = &abtsiocb->iocb;
icmd->un.acxri.abortType = ABORT_TYPE_ABTS;
icmd->un.acxri.abortContextTag = cmd->ulpContext;
icmd->un.acxri.abortIoTag = cmd->ulpIoTag;
icmd->ulpLe = 1;
icmd->ulpClass = cmd->ulpClass;
if (phba->hba_state >= LPFC_LINK_UP)
icmd->ulpCommand = CMD_ABORT_XRI_CN;
else
icmd->ulpCommand = CMD_CLOSE_XRI_CN;
icmd->ulpLe = 1;
icmd->ulpClass = cmd->ulpClass;
if (phba->hba_state >= LPFC_LINK_UP)
icmd->ulpCommand = CMD_ABORT_XRI_CN;
else
icmd->ulpCommand = CMD_CLOSE_XRI_CN;
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) ==
IOCB_ERROR) {
list_add_tail(&abtsiocb->list, lpfc_iocb_list);
ret = IOCB_ERROR;
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) {
lpfc_sli_release_iocbq(phba, abtsiocb);
ret = FAILED;
goto out;
}
/* Wait for abort to complete */
while (lpfc_cmd->pCmd == cmnd)
{
spin_unlock_irq(phba->host->host_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(LPFC_ABORT_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loop_count
> (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT)
break;
}
}
/* Wait for abort to complete */
while (cmnd->host_scribble)
{
spin_unlock_irq(phba->host->host_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(LPFC_ABORT_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loop_count
> (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT)
break;
}
if(cmnd->host_scribble) {
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0748 abort handler timed "
"out waiting for abort to "
"complete. Data: "
"x%x x%x x%x x%lx\n",
phba->brd_no, ret, id, lun, snum);
cmnd->host_scribble = NULL;
iocb->iocb_cmpl = lpfc_scsi_cmd_iocb_cleanup;
ret = IOCB_ERROR;
}
break;
if (lpfc_cmd->pCmd == cmnd) {
ret = FAILED;
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0748 abort handler timed out waiting for "
"abort to complete: ret %#x, ID %d, LUN %d, "
"snum %#lx\n",
phba->brd_no, ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
}
out:
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
"%d:0749 SCSI layer issued abort device "
"Data: x%x x%x x%x x%lx\n",
phba->brd_no, ret, id, lun, snum);
"%d:0749 SCSI layer issued abort device: ret %#x, "
"ID %d, LUN %d, snum %#lx\n",
phba->brd_no, ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
return ret == IOCB_SUCCESS ? SUCCESS : FAILED;
return ret;
}
static int
@ -938,11 +868,8 @@ __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_sli *psli = &phba->sli;
struct lpfc_scsi_buf *lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq *iocbq, *iocbqrsp = NULL;
struct lpfc_scsi_buf *lpfc_cmd;
struct lpfc_iocbq *iocbq, *iocbqrsp;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *pnode = rdata->pnode;
int ret = FAILED;
@ -966,7 +893,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
break;
}
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
if (lpfc_cmd == NULL)
goto out;
@ -981,18 +908,13 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
iocbq = &lpfc_cmd->cur_iocbq;
/* get a buffer for this IOCB command response */
list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list);
iocbqrsp = lpfc_sli_get_iocbq(phba);
if (iocbqrsp == NULL)
goto out_free_scsi_buf;
memset(iocbqrsp, 0, sizeof (struct lpfc_iocbq));
iocbq->iocb_flag |= LPFC_IO_POLL;
iocbq->iocb_cmpl = lpfc_sli_wake_iocb_high_priority;
ret = lpfc_sli_issue_iocb_wait_high_priority(phba,
&phba->sli.ring[psli->fcp_ring],
iocbq, 0, iocbqrsp, 60);
ret = lpfc_sli_issue_iocb_wait(phba,
&phba->sli.ring[phba->sli.fcp_ring],
iocbq, iocbqrsp, lpfc_cmd->timeout);
if (ret == IOCB_SUCCESS)
ret = SUCCESS;
@ -1027,12 +949,13 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
}
if (cnt) {
lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0719 LUN Reset I/O flush failure: cnt x%x\n",
phba->brd_no, cnt);
ret = FAILED;
}
list_add_tail(&iocbqrsp->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, iocbqrsp);
out_free_scsi_buf:
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
@ -1041,7 +964,7 @@ out_free_scsi_buf:
phba->brd_no, lpfc_cmd->pCmd->device->id,
lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status,
lpfc_cmd->result);
lpfc_free_scsi_buf(lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
out:
return ret;
}
@ -1069,10 +992,9 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
int ret = FAILED, i, err_count = 0;
int cnt, loopcnt;
unsigned int midlayer_id = 0;
struct lpfc_scsi_buf * lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
struct lpfc_scsi_buf * lpfc_cmd;
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
if (lpfc_cmd == NULL)
goto out;
@ -1136,10 +1058,12 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
phba->brd_no, cnt, i);
}
if (!err_count)
if (cnt == 0)
ret = SUCCESS;
else
ret = FAILED;
lpfc_free_scsi_buf(lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
lpfc_printf_log(phba,
KERN_ERR,
LOG_FCP,
@ -1163,66 +1087,47 @@ static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
struct lpfc_nodelist *ndlp = NULL;
int match = 0;
struct lpfc_scsi_buf *scsi_buf = NULL;
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
uint32_t total = 0, i;
uint32_t num_to_alloc = 0;
unsigned long flags;
struct list_head *listp;
struct list_head *node_list[6];
/*
* Store the target pointer in the scsi_device hostdata pointer provided
* the driver has already discovered the target id.
*/
/* Search the nlp lists other than unmap_list for this target ID */
node_list[0] = &phba->fc_npr_list;
node_list[1] = &phba->fc_nlpmap_list;
node_list[2] = &phba->fc_prli_list;
node_list[3] = &phba->fc_reglogin_list;
node_list[4] = &phba->fc_adisc_list;
node_list[5] = &phba->fc_plogi_list;
for (i = 0; i < 6 && !match; i++) {
listp = node_list[i];
if (list_empty(listp))
continue;
list_for_each_entry(ndlp, listp, nlp_listp) {
if ((sdev->id == ndlp->nlp_sid) && ndlp->rport) {
match = 1;
break;
}
}
}
if (!match)
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
sdev->hostdata = ndlp->rport->dd_data;
sdev->hostdata = rport->dd_data;
/*
* Populate the cmds_per_lun count scsi_bufs into this host's globally
* available list of scsi buffers. Don't allocate more than the
* HBA limit conveyed to the midlayer via the host structure. Note
* that this list of scsi bufs exists for the lifetime of the driver.
* HBA limit conveyed to the midlayer via the host structure. The
* formula accounts for the lun_queue_depth + error handlers + 1
* extra. This list of scsi bufs exists for the lifetime of the driver.
*/
total = phba->total_scsi_bufs;
num_to_alloc = LPFC_CMD_PER_LUN;
num_to_alloc = phba->cfg_lun_queue_depth + 2;
if (total >= phba->cfg_hba_queue_depth) {
printk(KERN_WARNING "%s, At config limitation of "
"%d allocated scsi_bufs\n", __FUNCTION__, total);
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
"%d:0704 At limitation of %d preallocated "
"command buffers\n", phba->brd_no, total);
return 0;
} else if (total + num_to_alloc > phba->cfg_hba_queue_depth) {
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
"%d:0705 Allocation request of %d command "
"buffers will exceed max of %d. Reducing "
"allocation request to %d.\n", phba->brd_no,
num_to_alloc, phba->cfg_hba_queue_depth,
(phba->cfg_hba_queue_depth - total));
num_to_alloc = phba->cfg_hba_queue_depth - total;
}
for (i = 0; i < num_to_alloc; i++) {
scsi_buf = lpfc_get_scsi_buf(phba);
scsi_buf = lpfc_new_scsi_buf(phba);
if (!scsi_buf) {
printk(KERN_ERR "%s, failed to allocate "
"scsi_buf\n", __FUNCTION__);
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0706 Failed to allocate command "
"buffer\n", phba->brd_no);
break;
}

View File

@ -65,6 +65,28 @@ typedef enum _lpfc_iocb_type {
LPFC_ABORT_IOCB
} lpfc_iocb_type;
struct lpfc_iocbq *
lpfc_sli_get_iocbq(struct lpfc_hba * phba)
{
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq * iocbq = NULL;
list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list);
return iocbq;
}
void
lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
{
size_t start_clean = (size_t)(&((struct lpfc_iocbq *)NULL)->iocb);
/*
* Clean all volatile data fields, preserve iotag and node struct.
*/
memset((char*)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean);
list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
}
/*
* Translate the iocb command to an iocb command type used to decide the final
* disposition of each completed IOCB.
@ -265,41 +287,69 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return iocb;
}
static uint32_t
lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
uint16_t
lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
{
uint32_t search_start;
struct lpfc_iocbq ** new_arr;
struct lpfc_iocbq ** old_arr;
size_t new_len;
struct lpfc_sli *psli = &phba->sli;
uint16_t iotag;
if (pring->fast_lookup == NULL) {
pring->iotag_ctr++;
if (pring->iotag_ctr >= pring->iotag_max)
pring->iotag_ctr = 1;
return pring->iotag_ctr;
spin_lock_irq(phba->host->host_lock);
iotag = psli->last_iotag;
if(++iotag < psli->iocbq_lookup_len) {
psli->last_iotag = iotag;
psli->iocbq_lookup[iotag] = iocbq;
spin_unlock_irq(phba->host->host_lock);
iocbq->iotag = iotag;
return iotag;
}
else if (psli->iocbq_lookup_len < (0xffff
- LPFC_IOCBQ_LOOKUP_INCREMENT)) {
new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT;
spin_unlock_irq(phba->host->host_lock);
new_arr = kmalloc(new_len * sizeof (struct lpfc_iocbq *),
GFP_KERNEL);
if (new_arr) {
memset((char *)new_arr, 0,
new_len * sizeof (struct lpfc_iocbq *));
spin_lock_irq(phba->host->host_lock);
old_arr = psli->iocbq_lookup;
if (new_len <= psli->iocbq_lookup_len) {
/* highly unprobable case */
kfree(new_arr);
iotag = psli->last_iotag;
if(++iotag < psli->iocbq_lookup_len) {
psli->last_iotag = iotag;
psli->iocbq_lookup[iotag] = iocbq;
spin_unlock_irq(phba->host->host_lock);
iocbq->iotag = iotag;
return iotag;
}
spin_unlock_irq(phba->host->host_lock);
return 0;
}
if (psli->iocbq_lookup)
memcpy(new_arr, old_arr,
((psli->last_iotag + 1) *
sizeof (struct lpfc_iocbq *)));
psli->iocbq_lookup = new_arr;
psli->iocbq_lookup_len = new_len;
psli->last_iotag = iotag;
psli->iocbq_lookup[iotag] = iocbq;
spin_unlock_irq(phba->host->host_lock);
iocbq->iotag = iotag;
kfree(old_arr);
return iotag;
}
}
search_start = pring->iotag_ctr;
lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
"%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
phba->brd_no, psli->last_iotag);
do {
pring->iotag_ctr++;
if (pring->iotag_ctr >= pring->fast_iotag)
pring->iotag_ctr = 1;
if (*(pring->fast_lookup + pring->iotag_ctr) == NULL)
return pring->iotag_ctr;
} while (pring->iotag_ctr != search_start);
/*
* Outstanding I/O count for ring <ringno> is at max <fast_iotag>
*/
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
"%d:0318 Outstanding I/O count for ring %d is at max x%x\n",
phba->brd_no,
pring->ringno,
pring->fast_iotag);
return (0);
return 0;
}
static void
@ -307,10 +357,9 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
IOCB_t *iocb, struct lpfc_iocbq *nextiocb)
{
/*
* Allocate and set up an iotag
* Set up an iotag
*/
nextiocb->iocb.ulpIoTag =
lpfc_sli_next_iotag(phba, &phba->sli.ring[phba->sli.fcp_ring]);
nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0;
/*
* Issue iocb command to adapter
@ -326,16 +375,15 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
*/
if (nextiocb->iocb_cmpl)
lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb);
else {
list_add_tail(&nextiocb->list, &phba->lpfc_iocb_list);
}
else
lpfc_sli_release_iocbq(phba, nextiocb);
/*
* Let the HBA know what IOCB slot will be the next one the
* driver will put a command into.
*/
pring->cmdidx = pring->next_cmdidx;
writeb(pring->cmdidx, phba->MBslimaddr
writel(pring->cmdidx, phba->MBslimaddr
+ (SLIMOFF + (pring->ringno * 2)) * 4);
}
@ -752,80 +800,28 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
static struct lpfc_iocbq *
lpfc_sli_txcmpl_ring_search_slow(struct lpfc_sli_ring * pring,
struct lpfc_iocbq * prspiocb)
lpfc_sli_iocbq_lookup(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * prspiocb)
{
IOCB_t *icmd = NULL;
IOCB_t *irsp = NULL;
struct lpfc_iocbq *cmd_iocb;
struct lpfc_iocbq *iocb, *next_iocb;
uint16_t iotag;
irsp = &prspiocb->iocb;
iotag = irsp->ulpIoTag;
cmd_iocb = NULL;
/* Search through txcmpl from the begining */
list_for_each_entry_safe(iocb, next_iocb, &(pring->txcmplq), list) {
icmd = &iocb->iocb;
if (iotag == icmd->ulpIoTag) {
/* Found a match. */
cmd_iocb = iocb;
list_del(&iocb->list);
pring->txcmplq_cnt--;
break;
}
}
return (cmd_iocb);
}
static struct lpfc_iocbq *
lpfc_sli_txcmpl_ring_iotag_lookup(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * prspiocb)
{
IOCB_t *irsp = NULL;
struct lpfc_iocbq *cmd_iocb = NULL;
uint16_t iotag;
if (unlikely(pring->fast_lookup == NULL))
return NULL;
iotag = prspiocb->iocb.ulpIoTag;
/* Use fast lookup based on iotag for completion */
irsp = &prspiocb->iocb;
iotag = irsp->ulpIoTag;
if (iotag < pring->fast_iotag) {
cmd_iocb = *(pring->fast_lookup + iotag);
*(pring->fast_lookup + iotag) = NULL;
if (cmd_iocb) {
list_del(&cmd_iocb->list);
pring->txcmplq_cnt--;
return cmd_iocb;
} else {
/*
* This is clearly an error. A ring that uses iotags
* should never have a interrupt for a completion that
* is not on the ring. Return NULL and log a error.
*/
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0327 Rsp ring %d error - command "
"completion for iotag x%x not found\n",
phba->brd_no, pring->ringno, iotag);
return NULL;
}
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
cmd_iocb = phba->sli.iocbq_lookup[iotag];
list_del(&cmd_iocb->list);
pring->txcmplq_cnt--;
return cmd_iocb;
}
/*
* Rsp ring <ringno> get: iotag <iotag> greater then
* configured max <fast_iotag> wd0 <irsp>. This is an
* error. Just return NULL.
*/
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0317 Rsp ring %d get: iotag x%x greater then "
"configured max x%x wd0 x%x\n",
phba->brd_no, pring->ringno, iotag, pring->fast_iotag,
*(((uint32_t *) irsp) + 7));
"%d:0317 iotag x%x is out off "
"range: max iotag x%x wd0 x%x\n",
phba->brd_no, iotag,
phba->sli.last_iotag,
*(((uint32_t *) &prspiocb->iocb) + 7));
return NULL;
}
@ -839,7 +835,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
/* Based on the iotag field, get the cmd IOCB from the txcmplq */
spin_lock_irqsave(phba->host->host_lock, iflag);
cmdiocbp = lpfc_sli_txcmpl_ring_search_slow(pring, saveq);
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
if (cmdiocbp) {
if (cmdiocbp->iocb_cmpl) {
/*
@ -853,17 +849,13 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
spin_lock_irqsave(phba->host->host_lock, iflag);
}
else {
if (cmdiocbp->iocb_flag & LPFC_IO_POLL)
rc = 0;
spin_unlock_irqrestore(phba->host->host_lock,
iflag);
(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
spin_lock_irqsave(phba->host->host_lock, iflag);
}
} else {
list_add_tail(&cmdiocbp->list, &phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, cmdiocbp);
} else {
/*
* Unknown initiating command based on the response iotag.
@ -889,6 +881,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
saveq->iocb.ulpContext);
}
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
return rc;
}
@ -953,7 +946,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
* structure. The copy involves a byte-swap since the
* network byte order and pci byte orders are different.
*/
entry = (IOCB_t *) IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb,
sizeof (IOCB_t));
@ -990,9 +983,8 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
break;
}
cmdiocbq = lpfc_sli_txcmpl_ring_iotag_lookup(phba,
pring,
&rspiocbq);
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
spin_unlock_irqrestore(
phba->host->host_lock, iflag);
@ -1033,7 +1025,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
to_slim = phba->MBslimaddr +
(SLIMOFF + (pring->ringno * 2) + 1) * 4;
writeb(pring->rspidx, to_slim);
writel(pring->rspidx, to_slim);
if (pring->rspidx == portRspPut)
portRspPut = le32_to_cpu(pgp->rspPutInx);
@ -1073,7 +1065,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
struct lpfc_iocbq *next_iocb;
struct lpfc_iocbq *cmdiocbp;
struct lpfc_iocbq *saveq;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
uint8_t iocb_cmd_type;
lpfc_iocb_type type;
@ -1115,7 +1106,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
}
rmb();
lpfc_iocb_list = &phba->lpfc_iocb_list;
while (pring->rspidx != portRspPut) {
/*
* Build a completion list and call the appropriate handler.
@ -1131,8 +1121,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
* received.
*/
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
list_remove_head(lpfc_iocb_list, rspiocbp, struct lpfc_iocbq,
list);
rspiocbp = lpfc_sli_get_iocbq(phba);
if (rspiocbp == NULL) {
printk(KERN_ERR "%s: out of buffers! Failing "
"completion.\n", __FUNCTION__);
@ -1147,7 +1136,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
to_slim = phba->MBslimaddr + (SLIMOFF + (pring->ringno * 2)
+ 1) * 4;
writeb(pring->rspidx, to_slim);
writel(pring->rspidx, to_slim);
if (list_empty(&(pring->iocb_continueq))) {
list_add(&rspiocbp->list, &(pring->iocb_continueq));
@ -1213,8 +1202,8 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
} else if (type == LPFC_ABORT_IOCB) {
if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
((cmdiocbp =
lpfc_sli_txcmpl_ring_search_slow(pring,
saveq)))) {
lpfc_sli_iocbq_lookup(phba, pring,
saveq)))) {
/* Call the specified completion
routine */
if (cmdiocbp->iocb_cmpl) {
@ -1226,10 +1215,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
spin_lock_irqsave(
phba->host->host_lock,
iflag);
} else {
list_add_tail(&cmdiocbp->list,
lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba,
cmdiocbp);
}
} else if (type == LPFC_UNKNOWN_IOCB) {
if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
@ -1264,12 +1252,12 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
next_iocb,
&saveq->list,
list) {
list_add_tail(&rspiocbp->list,
lpfc_iocb_list);
lpfc_sli_release_iocbq(phba,
rspiocbp);
}
}
list_add_tail(&saveq->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, saveq);
}
}
@ -1314,7 +1302,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
struct lpfc_iocbq *iocb, *next_iocb;
IOCB_t *icmd = NULL, *cmd = NULL;
int errcnt;
uint16_t iotag;
errcnt = 0;
@ -1331,9 +1318,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else {
list_add_tail(&iocb->list, &phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, iocb);
}
pring->txq_cnt = 0;
INIT_LIST_HEAD(&(pring->txq));
@ -1343,13 +1329,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
cmd = &iocb->iocb;
/*
* Imediate abort of IOCB, clear fast_lookup entry,
* if any, deque and call compl
* Imediate abort of IOCB, deque and call compl
*/
iotag = cmd->ulpIoTag;
if (iotag && pring->fast_lookup &&
(iotag < pring->fast_iotag))
pring->fast_lookup[iotag] = NULL;
list_del_init(&iocb->list);
pring->txcmplq_cnt--;
@ -1360,9 +1341,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
spin_unlock_irq(phba->host->host_lock);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irq(phba->host->host_lock);
} else {
list_add_tail(&iocb->list, &phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, iocb);
}
INIT_LIST_HEAD(&pring->txcmplq);
@ -2147,6 +2127,10 @@ lpfc_sli_setup(struct lpfc_hba *phba)
psli->next_ring = LPFC_FCP_NEXT_RING;
psli->ip_ring = LPFC_IP_RING;
psli->iocbq_lookup = NULL;
psli->iocbq_lookup_len = 0;
psli->last_iotag = 0;
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
switch (i) {
@ -2222,7 +2206,7 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba)
{
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
int i, cnt;
int i;
psli = &phba->sli;
spin_lock_irq(phba->host->host_lock);
@ -2238,19 +2222,6 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba)
INIT_LIST_HEAD(&pring->txcmplq);
INIT_LIST_HEAD(&pring->iocb_continueq);
INIT_LIST_HEAD(&pring->postbufq);
cnt = pring->fast_iotag;
spin_unlock_irq(phba->host->host_lock);
if (cnt) {
pring->fast_lookup =
kmalloc(cnt * sizeof (struct lpfc_iocbq *),
GFP_KERNEL);
if (pring->fast_lookup == 0) {
return (0);
}
memset((char *)pring->fast_lookup, 0,
cnt * sizeof (struct lpfc_iocbq *));
}
spin_lock_irq(phba->host->host_lock);
}
spin_unlock_irq(phba->host->host_lock);
return (1);
@ -2292,10 +2263,8 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
flags);
(iocb->iocb_cmpl) (phba, iocb, iocb);
spin_lock_irqsave(phba->host->host_lock, flags);
} else {
list_add_tail(&iocb->list,
&phba->lpfc_iocb_list);
}
} else
lpfc_sli_release_iocbq(phba, iocb);
}
INIT_LIST_HEAD(&(pring->txq));
@ -2436,7 +2405,7 @@ lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
kfree(buf_ptr);
}
list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, cmdiocb);
return;
}
@ -2445,16 +2414,14 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * cmdiocb)
{
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq *abtsiocbp = NULL;
struct lpfc_iocbq *abtsiocbp;
IOCB_t *icmd = NULL;
IOCB_t *iabt = NULL;
/* issue ABTS for this IOCB based on iotag */
list_remove_head(lpfc_iocb_list, abtsiocbp, struct lpfc_iocbq, list);
abtsiocbp = lpfc_sli_get_iocbq(phba);
if (abtsiocbp == NULL)
return 0;
memset(abtsiocbp, 0, sizeof (struct lpfc_iocbq));
iabt = &abtsiocbp->iocb;
icmd = &cmdiocb->iocb;
@ -2473,7 +2440,7 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl;
break;
default:
list_add_tail(&abtsiocbp->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, abtsiocbp);
return 0;
}
@ -2485,7 +2452,7 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
iabt->ulpCommand = CMD_ABORT_MXRI64_CN;
if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) {
list_add_tail(&abtsiocbp->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, abtsiocbp);
return 0;
}
@ -2493,28 +2460,37 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
}
static int
lpfc_sli_validate_iocb_cmd(struct lpfc_scsi_buf *lpfc_cmd, uint16_t tgt_id,
uint64_t lun_id, struct lpfc_iocbq *iocb,
uint32_t ctx, lpfc_ctx_cmd ctx_cmd)
lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
uint64_t lun_id, uint32_t ctx,
lpfc_ctx_cmd ctx_cmd)
{
struct lpfc_scsi_buf *lpfc_cmd;
struct scsi_cmnd *cmnd;
int rc = 1;
if (lpfc_cmd == NULL)
if (!(iocbq->iocb_flag & LPFC_IO_FCP))
return rc;
lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
cmnd = lpfc_cmd->pCmd;
if (cmnd == NULL)
return rc;
switch (ctx_cmd) {
case LPFC_CTX_LUN:
if ((lpfc_cmd->pCmd->device->id == tgt_id) &&
(lpfc_cmd->pCmd->device->lun == lun_id))
if ((cmnd->device->id == tgt_id) &&
(cmnd->device->lun == lun_id))
rc = 0;
break;
case LPFC_CTX_TGT:
if (lpfc_cmd->pCmd->device->id == tgt_id)
if (cmnd->device->id == tgt_id)
rc = 0;
break;
case LPFC_CTX_CTX:
if (iocb->iocb.ulpContext == ctx)
if (iocbq->iocb.ulpContext == ctx)
rc = 0;
break;
case LPFC_CTX_HOST:
rc = 0;
break;
@ -2531,30 +2507,17 @@ int
lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd)
{
struct lpfc_iocbq *iocb, *next_iocb;
IOCB_t *cmd = NULL;
struct lpfc_scsi_buf *lpfc_cmd;
int sum = 0, ret_val = 0;
struct lpfc_iocbq *iocbq;
int sum, i;
/* Next check the txcmplq */
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
cmd = &iocb->iocb;
for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) {
iocbq = phba->sli.iocbq_lookup[i];
/* Must be a FCP command */
if ((cmd->ulpCommand != CMD_FCP_ICMND64_CR) &&
(cmd->ulpCommand != CMD_FCP_IWRITE64_CR) &&
(cmd->ulpCommand != CMD_FCP_IREAD64_CR)) {
continue;
}
/* context1 MUST be a struct lpfc_scsi_buf */
lpfc_cmd = (struct lpfc_scsi_buf *) (iocb->context1);
ret_val = lpfc_sli_validate_iocb_cmd(lpfc_cmd, tgt_id, lun_id,
NULL, 0, ctx_cmd);
if (ret_val != 0)
continue;
sum++;
if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
0, ctx_cmd) == 0)
sum++;
}
return sum;
}
@ -2563,7 +2526,7 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
{
spin_lock_irq(phba->host->host_lock);
list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
}
@ -2573,39 +2536,27 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, uint32_t ctx,
lpfc_ctx_cmd abort_cmd)
{
struct lpfc_iocbq *iocb, *next_iocb;
struct lpfc_iocbq *abtsiocb = NULL;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *abtsiocb;
IOCB_t *cmd = NULL;
struct lpfc_scsi_buf *lpfc_cmd;
int errcnt = 0, ret_val = 0;
int i;
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
cmd = &iocb->iocb;
for (i = 1; i <= phba->sli.last_iotag; i++) {
iocbq = phba->sli.iocbq_lookup[i];
/* Must be a FCP command */
if ((cmd->ulpCommand != CMD_FCP_ICMND64_CR) &&
(cmd->ulpCommand != CMD_FCP_IWRITE64_CR) &&
(cmd->ulpCommand != CMD_FCP_IREAD64_CR)) {
continue;
}
/* context1 MUST be a struct lpfc_scsi_buf */
lpfc_cmd = (struct lpfc_scsi_buf *) (iocb->context1);
ret_val = lpfc_sli_validate_iocb_cmd(lpfc_cmd, tgt_id, lun_id,
iocb, ctx, abort_cmd);
if (ret_val != 0)
if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
0, abort_cmd) != 0)
continue;
/* issue ABTS for this IOCB based on iotag */
list_remove_head(lpfc_iocb_list, abtsiocb, struct lpfc_iocbq,
list);
abtsiocb = lpfc_sli_get_iocbq(phba);
if (abtsiocb == NULL) {
errcnt++;
continue;
}
memset(abtsiocb, 0, sizeof (struct lpfc_iocbq));
cmd = &iocbq->iocb;
abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS;
abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext;
abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag;
@ -2621,7 +2572,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
ret_val = lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0);
if (ret_val == IOCB_ERROR) {
list_add_tail(&abtsiocb->list, lpfc_iocb_list);
lpfc_sli_release_iocbq(phba, abtsiocb);
errcnt++;
continue;
}
@ -2630,83 +2581,99 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return errcnt;
}
void
lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
struct lpfc_iocbq * queue1,
struct lpfc_iocbq * queue2)
static void
lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
struct lpfc_iocbq *rspiocbq)
{
if (queue1->context2 && queue2)
memcpy(queue1->context2, queue2, sizeof (struct lpfc_iocbq));
wait_queue_head_t *pdone_q;
unsigned long iflags;
/* The waiter is looking for LPFC_IO_HIPRI bit to be set
as a signal to wake up */
queue1->iocb_flag |= LPFC_IO_HIPRI;
spin_lock_irqsave(phba->host->host_lock, iflags);
cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
if (cmdiocbq->context2 && rspiocbq)
memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
&rspiocbq->iocb, sizeof(IOCB_t));
pdone_q = cmdiocbq->context_un.wait_queue;
spin_unlock_irqrestore(phba->host->host_lock, iflags);
if (pdone_q)
wake_up(pdone_q);
return;
}
/*
* Issue the caller's iocb and wait for its completion, but no longer than the
* caller's timeout. Note that iocb_flags is cleared before the
* lpfc_sli_issue_call since the wake routine sets a unique value and by
* definition this is a wait function.
*/
int
lpfc_sli_issue_iocb_wait_high_priority(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * piocb,
uint32_t flag,
struct lpfc_iocbq * prspiocbq,
uint32_t timeout)
lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring,
struct lpfc_iocbq * piocb,
struct lpfc_iocbq * prspiocbq,
uint32_t timeout)
{
int j, delay_time, retval = IOCB_ERROR;
/* The caller must left context1 empty. */
if (piocb->context_un.hipri_wait_queue != 0) {
return IOCB_ERROR;
}
DECLARE_WAIT_QUEUE_HEAD(done_q);
long timeleft, timeout_req = 0;
int retval = IOCB_SUCCESS;
/*
* If the caller has provided a response iocbq buffer, context2 must
* be NULL or its an error.
* If the caller has provided a response iocbq buffer, then context2
* is NULL or its an error.
*/
if (prspiocbq && piocb->context2) {
return IOCB_ERROR;
if (prspiocbq) {
if (piocb->context2)
return IOCB_ERROR;
piocb->context2 = prspiocbq;
}
piocb->context2 = prspiocbq;
piocb->iocb_cmpl = lpfc_sli_wake_iocb_wait;
piocb->context_un.wait_queue = &done_q;
piocb->iocb_flag &= ~LPFC_IO_WAKE;
/* Setup callback routine and issue the command. */
piocb->iocb_cmpl = lpfc_sli_wake_iocb_high_priority;
retval = lpfc_sli_issue_iocb(phba, pring, piocb,
flag | SLI_IOCB_HIGH_PRIORITY);
if (retval != IOCB_SUCCESS) {
piocb->context2 = NULL;
return IOCB_ERROR;
}
retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
if (retval == IOCB_SUCCESS) {
timeout_req = timeout * HZ;
spin_unlock_irq(phba->host->host_lock);
timeleft = wait_event_timeout(done_q,
piocb->iocb_flag & LPFC_IO_WAKE,
timeout_req);
spin_lock_irq(phba->host->host_lock);
/*
* This high-priority iocb was sent out-of-band. Poll for its
* completion rather than wait for a signal. Note that the host_lock
* is held by the midlayer and must be released here to allow the
* interrupt handlers to complete the IO and signal this routine via
* the iocb_flag.
* Also, the delay_time is computed to be one second longer than
* the scsi command timeout to give the FW time to abort on
* timeout rather than the driver just giving up. Typically,
* the midlayer does not specify a time for this command so the
* driver is free to enforce its own timeout.
*/
delay_time = ((timeout + 1) * 1000) >> 6;
retval = IOCB_ERROR;
spin_unlock_irq(phba->host->host_lock);
for (j = 0; j < 64; j++) {
msleep(delay_time);
if (piocb->iocb_flag & LPFC_IO_HIPRI) {
piocb->iocb_flag &= ~LPFC_IO_HIPRI;
retval = IOCB_SUCCESS;
break;
if (timeleft == 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0329 IOCB wait timeout error - no "
"wake response Data x%x\n",
phba->brd_no, timeout);
retval = IOCB_TIMEDOUT;
} else if (!(piocb->iocb_flag & LPFC_IO_WAKE)) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0330 IOCB wake NOT set, "
"Data x%x x%lx\n", phba->brd_no,
timeout, (timeleft / jiffies));
retval = IOCB_TIMEDOUT;
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"%d:0331 IOCB wake signaled\n",
phba->brd_no);
}
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"%d:0332 IOCB wait issue failed, Data x%x\n",
phba->brd_no, retval);
retval = IOCB_ERROR;
}
spin_lock_irq(phba->host->host_lock);
piocb->context2 = NULL;
if (prspiocbq)
piocb->context2 = NULL;
piocb->context_un.wait_queue = NULL;
piocb->iocb_cmpl = NULL;
return retval;
}
int
lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
uint32_t timeout)

View File

@ -33,13 +33,15 @@ typedef enum _lpfc_ctx_cmd {
struct lpfc_iocbq {
/* lpfc_iocbqs are used in double linked lists */
struct list_head list;
uint16_t iotag; /* pre-assigned IO tag */
uint16_t rsvd1;
IOCB_t iocb; /* IOCB cmd */
uint8_t retry; /* retry counter for IOCB cmd - if needed */
uint8_t iocb_flag;
#define LPFC_IO_POLL 1 /* Polling mode iocb */
#define LPFC_IO_LIBDFC 2 /* libdfc iocb */
#define LPFC_IO_WAIT 4
#define LPFC_IO_HIPRI 8 /* High Priority Queue signal flag */
#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */
#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
uint8_t abort_count;
uint8_t rsvd2;
@ -48,8 +50,7 @@ struct lpfc_iocbq {
void *context2; /* caller context information */
void *context3; /* caller context information */
union {
wait_queue_head_t *hipri_wait_queue; /* High Priority Queue wait
queue */
wait_queue_head_t *wait_queue;
struct lpfc_iocbq *rsp_iocb;
struct lpfcMboxq *mbox;
} context_un;
@ -125,10 +126,10 @@ struct lpfc_sli_ring {
uint32_t local_getidx; /* last available cmd index (from cmdGetInx) */
uint32_t next_cmdidx; /* next_cmd index */
uint32_t rspidx; /* current index in response ring */
uint32_t cmdidx; /* current index in command ring */
uint8_t rsvd;
uint8_t ringno; /* ring number */
uint8_t rspidx; /* current index in response ring */
uint8_t cmdidx; /* current index in command ring */
uint16_t numCiocb; /* number of command iocb's per ring */
uint16_t numRiocb; /* number of rsp iocb's per ring */
@ -200,6 +201,11 @@ struct lpfc_sli {
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 */
uint16_t last_iotag; /* last allocated IOTAG */
};
/* Given a pointer to the start of the ring, and the slot number of

View File

@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "8.0.30"
#define LPFC_DRIVER_VERSION "8.1.0"
#define LPFC_DRIVER_NAME "lpfc"

View File

@ -758,9 +758,8 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
instance = (struct megasas_instance *)scmd->device->host->hostdata;
printk(KERN_NOTICE "megasas: RESET -%ld cmd=%x <c=%d t=%d l=%d>\n",
scmd->serial_number, scmd->cmnd[0], scmd->device->channel,
scmd->device->id, scmd->device->lun);
scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x\n",
scmd->serial_number, scmd->cmnd[0]);
if (instance->hw_crit_error) {
printk(KERN_ERR "megasas: cannot recover from previous reset "

View File

@ -3481,8 +3481,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**----------------------------------------------------
*/
if (np->settle_time && cmd->timeout_per_command >= HZ) {
u_long tlimit = ktime_get(cmd->timeout_per_command - HZ);
if (ktime_dif(np->settle_time, tlimit) > 0)
u_long tlimit = jiffies + cmd->timeout_per_command - HZ;
if (time_after(np->settle_time, tlimit))
np->settle_time = tlimit;
}
@ -3516,7 +3516,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
** Force ordered tag if necessary to avoid timeouts
** and to preserve interactivity.
*/
if (lp && ktime_exp(lp->tags_stime)) {
if (lp && time_after(jiffies, lp->tags_stime)) {
if (lp->tags_smap) {
order = M_ORDERED_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
@ -3524,7 +3524,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
"ordered tag forced.\n");
}
}
lp->tags_stime = ktime_get(3*HZ);
lp->tags_stime = jiffies + 3*HZ;
lp->tags_smap = lp->tags_umap;
}
@ -3669,7 +3669,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
/*
** select
*/
cp->phys.select.sel_id = sdev->id;
cp->phys.select.sel_id = sdev_id(sdev);
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
/*
@ -3792,7 +3792,7 @@ static int ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay)
u32 term;
int retv = 0;
np->settle_time = ktime_get(settle_delay * HZ);
np->settle_time = jiffies + settle_delay * HZ;
if (bootverbose > 1)
printk("%s: resetting, "
@ -4820,7 +4820,7 @@ static void ncr_set_sync_wide_status (struct ncb *np, u_char target)
*/
for (cp = np->ccb; cp; cp = cp->link_ccb) {
if (!cp->cmd) continue;
if (cp->cmd->device->id != target) continue;
if (scmd_id(cp->cmd) != target) continue;
#if 0
cp->sync_status = tp->sval;
cp->wide_status = tp->wval;
@ -4844,7 +4844,7 @@ static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char s
u_char target = INB (nc_sdid) & 0x0f;
u_char idiv;
BUG_ON(target != (cmd->device->id & 0xf));
BUG_ON(target != (scmd_id(cmd) & 0xf));
tp = &np->target[target];
@ -4902,7 +4902,7 @@ static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack
u_char scntl3;
u_char sxfer;
BUG_ON(target != (cmd->device->id & 0xf));
BUG_ON(target != (scmd_id(cmd) & 0xf));
tp = &np->target[target];
tp->widedone = wide+1;
@ -5044,7 +5044,7 @@ static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev)
static void ncr_timeout (struct ncb *np)
{
u_long thistime = ktime_get(0);
u_long thistime = jiffies;
/*
** If release process in progress, let's go
@ -5057,7 +5057,7 @@ static void ncr_timeout (struct ncb *np)
return;
}
np->timer.expires = ktime_get(SCSI_NCR_TIMER_INTERVAL);
np->timer.expires = jiffies + SCSI_NCR_TIMER_INTERVAL;
add_timer(&np->timer);
/*
@ -5336,8 +5336,8 @@ void ncr_exception (struct ncb *np)
**=========================================================
*/
if (ktime_exp(np->regtime)) {
np->regtime = ktime_get(10*HZ);
if (time_after(jiffies, np->regtime)) {
np->regtime = jiffies + 10*HZ;
for (i = 0; i<sizeof(np->regdump); i++)
((char*)&np->regdump)[i] = INB_OFF(i);
np->regdump.nc_dstat = dstat;
@ -5453,7 +5453,7 @@ static int ncr_int_sbmc (struct ncb *np)
** Suspend command processing for 1 second and
** reinitialize all except the chip.
*/
np->settle_time = ktime_get(1*HZ);
np->settle_time = jiffies + HZ;
ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET);
return 1;
}
@ -6923,7 +6923,7 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev)
for (i = 0 ; i < MAX_TAGS ; i++)
lp->cb_tags[i] = i;
lp->maxnxs = MAX_TAGS;
lp->tags_stime = ktime_get(3*HZ);
lp->tags_stime = jiffies + 3*HZ;
ncr_setup_tags (np, sdev);
}

View File

@ -481,7 +481,7 @@ static int nsp32_selection_autopara(struct scsi_cmnd *SCpnt)
nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
unsigned int base = SCpnt->device->host->io_port;
unsigned int host_id = SCpnt->device->host->this_id;
unsigned char target = SCpnt->device->id;
unsigned char target = scmd_id(SCpnt);
nsp32_autoparam *param = data->autoparam;
unsigned char phase;
int i, ret;
@ -612,7 +612,7 @@ static int nsp32_selection_autoscsi(struct scsi_cmnd *SCpnt)
nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
unsigned int base = SCpnt->device->host->io_port;
unsigned int host_id = SCpnt->device->host->this_id;
unsigned char target = SCpnt->device->id;
unsigned char target = scmd_id(SCpnt);
unsigned char phase;
int status;
unsigned short command = 0;
@ -973,7 +973,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
}
/* check target ID is not same as this initiator ID */
if (SCpnt->device->id == SCpnt->device->host->this_id) {
if (scmd_id(SCpnt) == SCpnt->device->host->this_id) {
nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "terget==host???");
SCpnt->result = DID_BAD_TARGET << 16;
done(SCpnt);
@ -1028,7 +1028,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
* (target don't have SDTR_DONE and SDTR_INITIATOR), sync
* message SDTR is needed to do synchronous transfer.
*/
target = &data->target[SCpnt->device->id];
target = &data->target[scmd_id(SCpnt)];
data->cur_target = target;
if (!(target->sync_flag & (SDTR_DONE | SDTR_INITIATOR | SDTR_TARGET))) {

View File

@ -5819,9 +5819,9 @@ static int osst_probe(struct device *dev)
}
drive->number = devfs_register_tape(SDp->devfs_name);
printk(KERN_INFO
"osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
sdev_printk(KERN_INFO, SDp,
"osst :I: Attached OnStream %.5s tape as %s\n",
SDp->model, tape_name(tpnt));
return 0;

View File

@ -201,7 +201,7 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
#ifdef NSP_DEBUG
/*unsigned int host_id = SCpnt->device->host->this_id;*/
/*unsigned int base = SCpnt->device->host->io_port;*/
unsigned char target = SCpnt->device->id;
unsigned char target = scmd_id(SCpnt);
#endif
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
@ -373,7 +373,7 @@ static int nsphw_start_selection(Scsi_Cmnd *SCpnt)
{
unsigned int host_id = SCpnt->device->host->this_id;
unsigned int base = SCpnt->device->host->io_port;
unsigned char target = SCpnt->device->id;
unsigned char target = scmd_id(SCpnt);
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
int time_out;
unsigned char phase, arbit;
@ -452,7 +452,7 @@ static struct nsp_sync_table nsp_sync_table_20M[] = {
*/
static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt)
{
unsigned char target = SCpnt->device->id;
unsigned char target = scmd_id(SCpnt);
// unsigned char lun = SCpnt->device->lun;
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
sync_data *sync = &(data->Sync[target]);
@ -677,7 +677,7 @@ static int nsp_reselected(Scsi_Cmnd *SCpnt)
target++;
}
if (SCpnt->device->id != target) {
if (scmd_id(SCpnt) != target) {
nsp_msg(KERN_ERR, "XXX: reselect ID must be %d in this implementation.", target);
}
@ -912,7 +912,7 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt)
static int nsp_nexus(Scsi_Cmnd *SCpnt)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned char target = SCpnt->device->id;
unsigned char target = scmd_id(SCpnt);
// unsigned char lun = SCpnt->device->lun;
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
sync_data *sync = &(data->Sync[target]);

View File

@ -610,7 +610,7 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* We are locked here already by the mid layer */
REG0(port_base);
outb(SCpnt->device->id, port_base + DEST_ID); /* set destination */
outb(scmd_id(SCpnt), port_base + DEST_ID); /* set destination */
outb(FLUSH_FIFO, port_base + CMD_REG); /* reset the fifos */
for (i = 0; i < SCpnt->cmd_len; i++) {

View File

@ -740,7 +740,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd)
}
case 2: /* Phase 2 - We are now talking to the scsi bus */
if (!ppa_select(dev, cmd->device->id)) {
if (!ppa_select(dev, scmd_id(cmd))) {
ppa_fail(dev, DID_NO_CONNECT);
return 0;
}

View File

@ -659,7 +659,7 @@ static int Psi240i_BiosParam (struct scsi_device *sdev, struct block_device *dev
{
POUR_DEVICE pdev;
pdev = &(HOSTDATA(sdev->host)->device[sdev->id]);
pdev = &(HOSTDATA(sdev->host)->device[sdev_id(sdev)]);
geom[0] = pdev->heads;
geom[1] = pdev->sectors;

View File

@ -1,11 +1,10 @@
/*
* QLogic ISP2100 device driver for Linux 2.6.x
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
* QLogic Fibre Channel HBA Driver
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (c) 2003-2005 QLogic Corporation
*
* Released under GPL v2.
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>

View File

@ -1,21 +1,9 @@
/******************************************************************************
* QLOGIC LINUX SOFTWARE
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*************************************************************************/
* See LICENSE.qla2xxx for copyright and licensing details.
*/
/*
* Firmware Version 1.19.25 (13:12 Dec 10, 2003)

View File

@ -1,11 +1,10 @@
/*
* QLogic ISP2200 device driver for Linux 2.6.x
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
* QLogic Fibre Channel HBA Driver
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (c) 2003-2005 QLogic Corporation
*
* Released under GPL v2.
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>

View File

@ -1,21 +1,9 @@
/******************************************************************************
* QLOGIC LINUX SOFTWARE
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*************************************************************************/
* See LICENSE.qla2xxx for copyright and licensing details.
*/
/*
* Firmware Version 2.02.08 (17:06 Mar 22, 2005)

View File

@ -1,11 +1,10 @@
/*
* QLogic ISP2300 device driver for Linux 2.6.x
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
* QLogic Fibre Channel HBA Driver
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (c) 2003-2005 QLogic Corporation
*
* Released under GPL v2.
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
/*
* QLogic ISP2322 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* Released under GPL v2.
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
/*
* QLogic ISP6312 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* Released under GPL v2.
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,8 @@
/*
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@ -319,6 +307,83 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
return len;
}
static ssize_t
qla2x00_zio_show(struct class_device *cdev, char *buf)
{
scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
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;
case QLA_ZIO_DISABLED:
len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
break;
}
return len;
}
static ssize_t
qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
{
scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
int val = 0;
uint16_t zio_mode;
if (sscanf(buf, "%d", &val) != 1)
return -EINVAL;
switch (val) {
case 1:
zio_mode = QLA_ZIO_MODE_5;
break;
case 2:
zio_mode = QLA_ZIO_MODE_6;
break;
default:
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) {
ha->zio_mode = zio_mode;
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
}
return strlen(buf);
}
static ssize_t
qla2x00_zio_timer_show(struct class_device *cdev, char *buf)
{
scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
}
static ssize_t
qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
size_t count)
{
scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
int val = 0;
uint16_t zio_timer;
if (sscanf(buf, "%d", &val) != 1)
return -EINVAL;
if (val > 25500 || val < 100)
return -ERANGE;
zio_timer = (uint16_t)(val / 100);
ha->zio_timer = zio_timer;
return strlen(buf);
}
static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
NULL);
static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@ -329,6 +394,10 @@ static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
qla2x00_zio_store);
static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
qla2x00_zio_timer_store);
struct class_device_attribute *qla2x00_host_attrs[] = {
&class_device_attr_driver_version,
@ -340,6 +409,8 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
&class_device_attr_model_desc,
&class_device_attr_pci_info,
&class_device_attr_state,
&class_device_attr_zio,
&class_device_attr_zio_timer,
NULL,
};
@ -432,6 +503,15 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
rport->dev_loss_tmo = ha->port_down_retry_count + 5;
}
static int
qla2x00_issue_lip(struct Scsi_Host *shost)
{
scsi_qla_host_t *ha = to_qla_host(shost);
set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags);
return 0;
}
struct fc_function_template qla2xxx_transport_functions = {
.show_host_node_name = 1,
@ -455,6 +535,7 @@ struct fc_function_template qla2xxx_transport_functions = {
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
};
void

View File

@ -1,20 +1,8 @@
/*
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"

View File

@ -1,22 +1,9 @@
/******************************************************************************
* QLOGIC LINUX SOFTWARE
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
******************************************************************************/
* See LICENSE.qla2xxx for copyright and licensing details.
*/
/*
* Driver debug definitions.
*/

View File

@ -1,22 +1,9 @@
/********************************************************************************
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
**
******************************************************************************/
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_DEF_H
#define __QLA_DEF_H
@ -34,6 +21,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <asm/semaphore.h>
#include <scsi/scsi.h>
@ -823,6 +811,11 @@ 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
/*
* ISP Initialization Control Block.
* Little endian except where noted.
@ -1673,6 +1666,8 @@ typedef struct fc_port {
struct fc_rport *rport;
u32 supported_classes;
struct work_struct rport_add_work;
struct work_struct rport_del_work;
} fc_port_t;
/*
@ -2470,6 +2465,9 @@ typedef struct scsi_qla_host {
/* Needed for BEACON */
uint16_t beacon_blink_led;
uint16_t beacon_green_on;
uint16_t zio_mode;
uint16_t zio_timer;
} scsi_qla_host_t;

View File

@ -1,23 +1,9 @@
/********************************************************************************
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
**
******************************************************************************/
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_FW_H
#define __QLA_FW_H
@ -394,7 +380,7 @@ struct cmd_type_6 {
uint16_t fcp_rsp_dsd_len; /* FCP_RSP DSD length. */
uint8_t lun[8]; /* FCP LUN (BE). */
struct scsi_lun lun; /* FCP LUN (BE). */
uint16_t control_flags; /* Control flags. */
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
@ -432,7 +418,7 @@ struct cmd_type_7 {
uint16_t dseg_count; /* Data segment count. */
uint16_t reserved_1;
uint8_t lun[8]; /* FCP LUN (BE). */
struct scsi_lun lun; /* FCP LUN (BE). */
uint16_t task_mgmt_flags; /* Task management flags. */
#define TMF_CLEAR_ACA BIT_14

View File

@ -1,25 +1,9 @@
/********************************************************************************
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
******************************************************************************
* Global include file.
******************************************************************************/
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_GBL_H
#define __QLA_GBL_H
@ -76,8 +60,6 @@ extern char qla2x00_version_str[];
extern int ql2xlogintimeout;
extern int qlport_down_retry;
extern int ql2xplogiabsentdevice;
extern int ql2xenablezio;
extern int ql2xintrdelaytimer;
extern int ql2xloginretrycount;
extern int ql2xfdmienable;
@ -223,6 +205,7 @@ extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *);
extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *);
extern irqreturn_t qla24xx_intr_handler(int, void *, struct pt_regs *);
extern void qla2x00_process_response_queue(struct scsi_qla_host *);
extern void qla24xx_process_response_queue(struct scsi_qla_host *);
/*
* Global Function Prototypes in qla_sup.c source file.

View File

@ -1,20 +1,8 @@
/*
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"

View File

@ -1,20 +1,8 @@
/*
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@ -1372,7 +1360,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
nvram_t *nv = (nvram_t *)ha->request_ring;
uint8_t *ptr = (uint8_t *)ha->request_ring;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint8_t timer_mode;
rval = QLA_SUCCESS;
@ -1650,22 +1637,26 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
ha->flags.process_response_queue = 1;
} else {
/* Enable ZIO -- Support mode 5 only. */
timer_mode = icb->add_firmware_options[0] &
(BIT_3 | BIT_2 | BIT_1 | BIT_0);
/* Enable ZIO. */
if (!ha->flags.init_done) {
ha->zio_mode = icb->add_firmware_options[0] &
(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->zio_timer = icb->interrupt_delay_timer ?
icb->interrupt_delay_timer: 2;
}
icb->add_firmware_options[0] &=
~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
if (ql2xenablezio)
timer_mode = BIT_2 | BIT_0;
if (timer_mode == (BIT_2 | BIT_0)) {
DEBUG2(printk("scsi(%ld): ZIO enabled; timer delay "
"(%d).\n", ha->host_no, ql2xintrdelaytimer));
ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) {
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
"delay (%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100));
qla_printk(KERN_INFO, ha,
"ZIO enabled; timer delay (%d).\n",
ql2xintrdelaytimer);
"ZIO mode %d enabled; timer delay (%d us).\n",
ha->zio_mode, ha->zio_timer * 100);
icb->add_firmware_options[0] |= timer_mode;
icb->interrupt_delay_timer = ql2xintrdelaytimer;
icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode;
icb->interrupt_delay_timer = (uint8_t)ha->zio_timer;
ha->flags.process_response_queue = 1;
}
}
@ -1677,6 +1668,24 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
return (rval);
}
static void
qla2x00_rport_add(void *data)
{
fc_port_t *fcport = data;
qla2x00_reg_remote_port(fcport->ha, fcport);
}
static void
qla2x00_rport_del(void *data)
{
fc_port_t *fcport = data;
if (fcport->rport)
fc_remote_port_delete(fcport->rport);
fcport->rport = NULL;
}
/**
* qla2x00_alloc_fcport() - Allocate a generic fcport.
* @ha: HA context
@ -1702,6 +1711,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
return (fcport);
}
@ -2065,8 +2076,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
struct fc_rport *rport;
if (fcport->rport) {
fc_remote_port_unblock(fcport->rport);
return;
fc_remote_port_delete(fcport->rport);
fcport->rport = NULL;
}
rport_ids.node_name = wwn_to_u64(fcport->node_name);
@ -2080,7 +2091,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
"Unable to allocate fc remote port!\n");
return;
}
rport->dd_data = fcport;
*((fc_port_t **)rport->dd_data) = fcport;
rport->supported_classes = fcport->supported_classes;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@ -2858,7 +2869,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa);
fcport->loop_id = FC_NO_LOOP_ID;
atomic_set(&fcport->state, FCS_DEVICE_DEAD);
fcport->login_retry = 0;
rval = 3;
break;
@ -3442,6 +3453,30 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
if (ql2xloginretrycount)
ha->login_retry_count = ql2xloginretrycount;
/* Enable ZIO. */
if (!ha->flags.init_done) {
ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
le16_to_cpu(icb->interrupt_delay_timer): 2;
}
icb->firmware_options_2 &= __constant_cpu_to_le32(
~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) {
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
"(%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100));
qla_printk(KERN_INFO, ha,
"ZIO mode %d enabled; timer delay (%d us).\n",
ha->zio_mode, ha->zio_timer * 100);
icb->firmware_options_2 |= cpu_to_le32(
(uint32_t)ha->zio_mode);
icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
ha->flags.process_response_queue = 1;
}
if (rval) {
DEBUG2_3(printk(KERN_WARNING
"scsi(%ld): NVRAM configuration failed!\n", ha->host_no));

View File

@ -1,23 +1,10 @@
/*
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *);
/*
* qla2x00_debounce_register

View File

@ -1,22 +1,9 @@
/******************************************************************************
* QLOGIC LINUX SOFTWARE
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
******************************************************************************/
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include <linux/blkdev.h>
@ -316,7 +303,6 @@ qla2x00_start_scsi(srb_t *sp)
uint16_t req_cnt;
uint16_t tot_dsds;
struct device_reg_2xxx __iomem *reg;
char tag[2];
/* Setup device pointers. */
ret = 0;
@ -401,18 +387,6 @@ qla2x00_start_scsi(srb_t *sp)
/* Update tagged queuing modifier */
cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
if (scsi_populate_tag_msg(cmd, tag)) {
switch (tag[0]) {
case MSG_HEAD_TAG:
cmd_pkt->control_flags =
__constant_cpu_to_le16(CF_HEAD_TAG);
break;
case MSG_ORDERED_TAG:
cmd_pkt->control_flags =
__constant_cpu_to_le16(CF_ORDERED_TAG);
break;
}
}
/* Load SCSI command packet. */
memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
@ -440,6 +414,11 @@ qla2x00_start_scsi(srb_t *sp)
WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index);
RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (ha->flags.process_response_queue &&
ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
qla2x00_process_response_queue(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return (QLA_SUCCESS);
@ -749,7 +728,6 @@ qla24xx_start_scsi(srb_t *sp)
uint16_t req_cnt;
uint16_t tot_dsds;
struct device_reg_24xx __iomem *reg;
char tag[2];
/* Setup device pointers. */
ret = 0;
@ -824,6 +802,7 @@ qla24xx_start_scsi(srb_t *sp)
cmd_pkt->handle = handle;
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0). */
clr_ptr = (uint32_t *)cmd_pkt + 2;
memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
@ -834,20 +813,7 @@ qla24xx_start_scsi(srb_t *sp)
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
cmd_pkt->lun[1] = LSB(sp->cmd->device->lun);
cmd_pkt->lun[2] = MSB(sp->cmd->device->lun);
/* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
if (scsi_populate_tag_msg(cmd, tag)) {
switch (tag[0]) {
case MSG_HEAD_TAG:
cmd_pkt->task = TSK_HEAD_OF_QUEUE;
break;
case MSG_ORDERED_TAG:
cmd_pkt->task = TSK_ORDERED;
break;
}
}
int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
/* Load SCSI command packet. */
memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
@ -877,6 +843,11 @@ qla24xx_start_scsi(srb_t *sp)
WRT_REG_DWORD(&reg->req_q_in, ha->req_ring_index);
RD_REG_DWORD_RELAXED(&reg->req_q_in); /* PCI Posting. */
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (ha->flags.process_response_queue &&
ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
qla24xx_process_response_queue(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;

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