mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6
This commit is contained in:
commit
fecb4a0c87
45
Documentation/scsi/LICENSE.qla2xxx
Normal file
45
Documentation/scsi/LICENSE.qla2xxx
Normal 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.
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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)) {
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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++) {
|
||||
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
-------------------------
|
||||
|
@ -1,4 +1,3 @@
|
||||
o Testing
|
||||
o More testing
|
||||
o Drop irq_mask, basically unused
|
||||
o I/O size increase
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
@ -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
@ -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
@ -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
@ -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
|
@ -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
@ -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)++);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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__)
|
||||
|
@ -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
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
322
drivers/scsi/iscsi_tcp.h
Normal 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 */
|
@ -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];
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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 -
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 "
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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))) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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
@ -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
@ -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
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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(®->req_q_in, ha->req_ring_index);
|
||||
RD_REG_DWORD_RELAXED(®->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
Loading…
Reference in New Issue
Block a user