You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (158 commits) [SCSI] Fix printing of failed 32-byte commands [SCSI] Fix printing of variable length commands [SCSI] libsrp: fix bug in ADDITIONAL CDB LENGTH interpretation [SCSI] scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list [SCSI] scsi_dh_alua: add netapp to dev list [SCSI] qla2xxx: Update version number to 8.03.02-k1. [SCSI] qla2xxx: EEH: Restore PCI saved state during pci slot reset. [SCSI] qla2xxx: Add firmware ETS burst support. [SCSI] qla2xxx: Correct loop-resync issues during SNS scans. [SCSI] qla2xxx: Correct use-after-free issue in terminate_rport_io callback. [SCSI] qla2xxx: Correct EH bus-reset handling. [SCSI] qla2xxx: Proper clean-up of BSG requests when request times out. [SCSI] qla2xxx: Initialize payload receive length in failure path of vendor commands [SCSI] fix duplicate removal on error path in scsi_sysfs_add_sdev [SCSI] fix refcounting bug in scsi_get_host_dev [SCSI] fix memory leak in scsi_report_lun_scan [SCSI] lpfc: correct PPC build failure [SCSI] raid_class: add raid1e [SCSI] mpt2sas: Do not call sas_is_tlr_enabled for RAID volumes. [SCSI] zfcp: Introduce header file for qdio structs and inline functions ...
This commit is contained in:
@@ -1,3 +1,19 @@
|
||||
1 Release Date : Thur. Oct 29, 2009 09:12:45 PST 2009 -
|
||||
(emaild-id:megaraidlinux@lsi.com)
|
||||
Bo Yang
|
||||
|
||||
2 Current Version : 00.00.04.17.1-rc1
|
||||
3 Older Version : 00.00.04.12
|
||||
|
||||
1. Add the pad_0 in mfi frame structure to 0 to fix the
|
||||
context value larger than 32bit value issue.
|
||||
|
||||
2. Add the logic drive list to the driver. Driver will
|
||||
keep the logic drive list internal after driver load.
|
||||
|
||||
3. driver fixed the device update issue after get the AEN
|
||||
PD delete/ADD, LD add/delete from FW.
|
||||
|
||||
1 Release Date : Tues. July 28, 2009 10:12:45 PST 2009 -
|
||||
(emaild-id:megaraidlinux@lsi.com)
|
||||
Bo Yang
|
||||
|
||||
+11
@@ -2141,6 +2141,17 @@ S: Supported
|
||||
F: Documentation/fault-injection/
|
||||
F: lib/fault-inject.c
|
||||
|
||||
FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
|
||||
M: Robert Love <robert.w.love@intel.com>
|
||||
L: devel@open-fcoe.org
|
||||
W: www.Open-FCoE.org
|
||||
S: Supported
|
||||
F: drivers/scsi/libfc/
|
||||
F: drivers/scsi/fcoe/
|
||||
F: include/scsi/fc/
|
||||
F: include/scsi/libfc.h
|
||||
F: include/scsi/libfcoe.h
|
||||
|
||||
FILE LOCKING (flock() and fcntl()/lockf())
|
||||
M: Matthew Wilcox <matthew@wil.cx>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
|
||||
@@ -126,8 +126,6 @@ static int mfcounter = 0;
|
||||
* Public data...
|
||||
*/
|
||||
|
||||
static struct proc_dir_entry *mpt_proc_root_dir;
|
||||
|
||||
#define WHOINIT_UNKNOWN 0xAA
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
@@ -146,6 +144,9 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
||||
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
||||
static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static struct proc_dir_entry *mpt_proc_root_dir;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Driver Callback Index's
|
||||
|
||||
@@ -76,8 +76,8 @@
|
||||
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
|
||||
#endif
|
||||
|
||||
#define MPT_LINUX_VERSION_COMMON "3.04.13"
|
||||
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.13"
|
||||
#define MPT_LINUX_VERSION_COMMON "3.04.14"
|
||||
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.14"
|
||||
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
|
||||
|
||||
#define show_mptmod_ver(s,ver) \
|
||||
|
||||
@@ -360,8 +360,8 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
|
||||
u16 iocstatus;
|
||||
|
||||
/* bus reset is only good for SCSI IO, RAID PASSTHRU */
|
||||
if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
|
||||
(function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
|
||||
if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
|
||||
function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
|
||||
dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
|
||||
"TaskMgmt, not SCSI_IO!!\n", ioc->name));
|
||||
return -EPERM;
|
||||
|
||||
@@ -195,29 +195,34 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
|
||||
unsigned long flags;
|
||||
int ready;
|
||||
MPT_ADAPTER *ioc;
|
||||
int loops = 40; /* seconds */
|
||||
|
||||
hd = shost_priv(SCpnt->device->host);
|
||||
ioc = hd->ioc;
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
|
||||
while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
|
||||
|| (loops > 0 && ioc->active == 0)) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
|
||||
"mptfc_block_error_handler.%d: %d:%d, port status is "
|
||||
"DID_IMM_RETRY, deferring %s recovery.\n",
|
||||
"%x, active flag %d, deferring %s recovery.\n",
|
||||
ioc->name, ioc->sh->host_no,
|
||||
SCpnt->device->id, SCpnt->device->lun, caller));
|
||||
SCpnt->device->id, SCpnt->device->lun,
|
||||
ready, ioc->active, caller));
|
||||
msleep(1000);
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
loops --;
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
|
||||
if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
|
||||
|| ioc->active == 0) {
|
||||
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
|
||||
"%s.%d: %d:%d, failing recovery, "
|
||||
"port state %d, vdevice %p.\n", caller,
|
||||
"port state %x, active %d, vdevice %p.\n", caller,
|
||||
ioc->name, ioc->sh->host_no,
|
||||
SCpnt->device->id, SCpnt->device->lun, ready,
|
||||
SCpnt->device->hostdata));
|
||||
ioc->active, SCpnt->device->hostdata));
|
||||
return FAILED;
|
||||
}
|
||||
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
|
||||
|
||||
@@ -1075,6 +1075,19 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
|
||||
{
|
||||
scsi_device_set_state(sdev, SDEV_BLOCK);
|
||||
}
|
||||
|
||||
static void
|
||||
mptsas_block_io_starget(struct scsi_target *starget)
|
||||
{
|
||||
if (starget)
|
||||
starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* mptsas_target_reset_queue
|
||||
*
|
||||
@@ -1098,10 +1111,11 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
|
||||
id = sas_event_data->TargetID;
|
||||
channel = sas_event_data->Bus;
|
||||
|
||||
if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
|
||||
return;
|
||||
|
||||
vtarget->deleted = 1; /* block IO */
|
||||
vtarget = mptsas_find_vtarget(ioc, channel, id);
|
||||
if (vtarget) {
|
||||
mptsas_block_io_starget(vtarget->starget);
|
||||
vtarget->deleted = 1; /* block IO */
|
||||
}
|
||||
|
||||
target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
|
||||
GFP_ATOMIC);
|
||||
@@ -1868,7 +1882,8 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
|
||||
if (ioc->sas_discovery_quiesce_io)
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
||||
// scsi_print_command(SCpnt);
|
||||
if (ioc->debug_level & MPT_DEBUG_SCSI)
|
||||
scsi_print_command(SCpnt);
|
||||
|
||||
return mptscsih_qcmd(SCpnt,done);
|
||||
}
|
||||
@@ -2686,6 +2701,187 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
|
||||
return error;
|
||||
}
|
||||
|
||||
struct rep_manu_request{
|
||||
u8 smp_frame_type;
|
||||
u8 function;
|
||||
u8 reserved;
|
||||
u8 request_length;
|
||||
};
|
||||
|
||||
struct rep_manu_reply{
|
||||
u8 smp_frame_type; /* 0x41 */
|
||||
u8 function; /* 0x01 */
|
||||
u8 function_result;
|
||||
u8 response_length;
|
||||
u16 expander_change_count;
|
||||
u8 reserved0[2];
|
||||
u8 sas_format:1;
|
||||
u8 reserved1:7;
|
||||
u8 reserved2[3];
|
||||
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
|
||||
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
|
||||
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
|
||||
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
|
||||
u16 component_id;
|
||||
u8 component_revision_id;
|
||||
u8 reserved3;
|
||||
u8 vendor_specific[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* mptsas_exp_repmanufacture_info -
|
||||
* @ioc: per adapter object
|
||||
* @sas_address: expander sas address
|
||||
* @edev: the sas_expander_device object
|
||||
*
|
||||
* Fills in the sas_expander_device object when SMP port is created.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
|
||||
u64 sas_address, struct sas_expander_device *edev)
|
||||
{
|
||||
MPT_FRAME_HDR *mf;
|
||||
SmpPassthroughRequest_t *smpreq;
|
||||
SmpPassthroughReply_t *smprep;
|
||||
struct rep_manu_reply *manufacture_reply;
|
||||
struct rep_manu_request *manufacture_request;
|
||||
int ret;
|
||||
int flagsLength;
|
||||
unsigned long timeleft;
|
||||
char *psge;
|
||||
unsigned long flags;
|
||||
void *data_out = NULL;
|
||||
dma_addr_t data_out_dma = 0;
|
||||
u32 sz;
|
||||
|
||||
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
||||
if (ioc->ioc_reset_in_progress) {
|
||||
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
||||
printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
|
||||
__func__, ioc->name);
|
||||
return -EFAULT;
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
||||
|
||||
ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
|
||||
if (!mf) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
smpreq = (SmpPassthroughRequest_t *)mf;
|
||||
memset(smpreq, 0, sizeof(*smpreq));
|
||||
|
||||
sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
|
||||
|
||||
data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
|
||||
if (!data_out) {
|
||||
printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
ret = -ENOMEM;
|
||||
goto put_mf;
|
||||
}
|
||||
|
||||
manufacture_request = data_out;
|
||||
manufacture_request->smp_frame_type = 0x40;
|
||||
manufacture_request->function = 1;
|
||||
manufacture_request->reserved = 0;
|
||||
manufacture_request->request_length = 0;
|
||||
|
||||
smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
|
||||
smpreq->PhysicalPort = 0xFF;
|
||||
*((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
|
||||
smpreq->RequestDataLength = sizeof(struct rep_manu_request);
|
||||
|
||||
psge = (char *)
|
||||
(((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
|
||||
|
||||
flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
||||
MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
||||
MPI_SGE_FLAGS_HOST_TO_IOC |
|
||||
MPI_SGE_FLAGS_END_OF_BUFFER;
|
||||
flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
||||
flagsLength |= sizeof(struct rep_manu_request);
|
||||
|
||||
ioc->add_sge(psge, flagsLength, data_out_dma);
|
||||
psge += ioc->SGE_size;
|
||||
|
||||
flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
||||
MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
||||
MPI_SGE_FLAGS_IOC_TO_HOST |
|
||||
MPI_SGE_FLAGS_END_OF_BUFFER;
|
||||
flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
||||
flagsLength |= sizeof(struct rep_manu_reply);
|
||||
ioc->add_sge(psge, flagsLength, data_out_dma +
|
||||
sizeof(struct rep_manu_request));
|
||||
|
||||
INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
|
||||
mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
|
||||
|
||||
timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
|
||||
if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
||||
ret = -ETIME;
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
mf = NULL;
|
||||
if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
|
||||
goto out_free;
|
||||
if (!timeleft)
|
||||
mpt_HardResetHandler(ioc, CAN_SLEEP);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
mf = NULL;
|
||||
|
||||
if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
|
||||
u8 *tmp;
|
||||
|
||||
smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
|
||||
if (le16_to_cpu(smprep->ResponseDataLength) !=
|
||||
sizeof(struct rep_manu_reply))
|
||||
goto out_free;
|
||||
|
||||
manufacture_reply = data_out + sizeof(struct rep_manu_request);
|
||||
strncpy(edev->vendor_id, manufacture_reply->vendor_id,
|
||||
SAS_EXPANDER_VENDOR_ID_LEN);
|
||||
strncpy(edev->product_id, manufacture_reply->product_id,
|
||||
SAS_EXPANDER_PRODUCT_ID_LEN);
|
||||
strncpy(edev->product_rev, manufacture_reply->product_rev,
|
||||
SAS_EXPANDER_PRODUCT_REV_LEN);
|
||||
edev->level = manufacture_reply->sas_format;
|
||||
if (manufacture_reply->sas_format) {
|
||||
strncpy(edev->component_vendor_id,
|
||||
manufacture_reply->component_vendor_id,
|
||||
SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
|
||||
tmp = (u8 *)&manufacture_reply->component_id;
|
||||
edev->component_id = tmp[0] << 8 | tmp[1];
|
||||
edev->component_revision_id =
|
||||
manufacture_reply->component_revision_id;
|
||||
}
|
||||
} else {
|
||||
printk(MYIOC_s_ERR_FMT
|
||||
"%s: smp passthru reply failed to be returned\n",
|
||||
ioc->name, __func__);
|
||||
ret = -ENXIO;
|
||||
}
|
||||
out_free:
|
||||
if (data_out_dma)
|
||||
pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
|
||||
put_mf:
|
||||
if (mf)
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
out_unlock:
|
||||
CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
|
||||
mutex_unlock(&ioc->sas_mgmt.mutex);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mptsas_parse_device_info(struct sas_identify *identify,
|
||||
struct mptsas_devinfo *device_info)
|
||||
@@ -2967,6 +3163,11 @@ static int mptsas_probe_one_phy(struct device *dev,
|
||||
goto out;
|
||||
}
|
||||
mptsas_set_rphy(ioc, phy_info, rphy);
|
||||
if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
|
||||
identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
|
||||
mptsas_exp_repmanufacture_info(ioc,
|
||||
identify.sas_address,
|
||||
rphy_to_expander_device(rphy));
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -1438,9 +1438,14 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
|
||||
&& (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
|
||||
&& (SCpnt->device->tagged_supported)) {
|
||||
scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
|
||||
} else {
|
||||
if (SCpnt->request && SCpnt->request->ioprio) {
|
||||
if (((SCpnt->request->ioprio & 0x7) == 1) ||
|
||||
!(SCpnt->request->ioprio & 0x7))
|
||||
scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ;
|
||||
}
|
||||
} else
|
||||
scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
|
||||
}
|
||||
|
||||
|
||||
/* Use the above information to set up the message frame
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Module interface and handling of zfcp data structures.
|
||||
*
|
||||
* Copyright IBM Corporation 2002, 2009
|
||||
* Copyright IBM Corporation 2002, 2010
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include "zfcp_ext.h"
|
||||
#include "zfcp_fc.h"
|
||||
#include "zfcp_reqlist.h"
|
||||
|
||||
#define ZFCP_BUS_ID_SIZE 20
|
||||
|
||||
@@ -49,36 +50,6 @@ static struct kmem_cache *zfcp_cache_hw_align(const char *name,
|
||||
return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL);
|
||||
}
|
||||
|
||||
static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
|
||||
{
|
||||
int idx;
|
||||
|
||||
adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
|
||||
GFP_KERNEL);
|
||||
if (!adapter->req_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
|
||||
INIT_LIST_HEAD(&adapter->req_list[idx]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_isempty - is the request list empty
|
||||
* @adapter: pointer to struct zfcp_adapter
|
||||
*
|
||||
* Returns: true if list is empty, false otherwise
|
||||
*/
|
||||
int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
|
||||
if (!list_empty(&adapter->req_list[idx]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
||||
{
|
||||
struct ccw_device *cdev;
|
||||
@@ -110,7 +81,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
||||
flush_work(&unit->scsi_work);
|
||||
|
||||
out_unit:
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
out_port:
|
||||
zfcp_ccw_adapter_put(adapter);
|
||||
out_ccw_device:
|
||||
@@ -255,7 +226,7 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
|
||||
read_lock_irqsave(&port->unit_list_lock, flags);
|
||||
list_for_each_entry(unit, &port->unit_list, list)
|
||||
if (unit->fcp_lun == fcp_lun) {
|
||||
if (!get_device(&unit->sysfs_device))
|
||||
if (!get_device(&unit->dev))
|
||||
unit = NULL;
|
||||
read_unlock_irqrestore(&port->unit_list_lock, flags);
|
||||
return unit;
|
||||
@@ -280,7 +251,7 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
|
||||
read_lock_irqsave(&adapter->port_list_lock, flags);
|
||||
list_for_each_entry(port, &adapter->port_list, list)
|
||||
if (port->wwpn == wwpn) {
|
||||
if (!get_device(&port->sysfs_device))
|
||||
if (!get_device(&port->dev))
|
||||
port = NULL;
|
||||
read_unlock_irqrestore(&adapter->port_list_lock, flags);
|
||||
return port;
|
||||
@@ -298,10 +269,9 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
|
||||
*/
|
||||
static void zfcp_unit_release(struct device *dev)
|
||||
{
|
||||
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit,
|
||||
sysfs_device);
|
||||
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
|
||||
|
||||
put_device(&unit->port->sysfs_device);
|
||||
put_device(&unit->port->dev);
|
||||
kfree(unit);
|
||||
}
|
||||
|
||||
@@ -318,11 +288,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
|
||||
struct zfcp_unit *unit;
|
||||
int retval = -ENOMEM;
|
||||
|
||||
get_device(&port->sysfs_device);
|
||||
get_device(&port->dev);
|
||||
|
||||
unit = zfcp_get_unit_by_lun(port, fcp_lun);
|
||||
if (unit) {
|
||||
put_device(&unit->sysfs_device);
|
||||
put_device(&unit->dev);
|
||||
retval = -EEXIST;
|
||||
goto err_out;
|
||||
}
|
||||
@@ -333,10 +303,10 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
|
||||
|
||||
unit->port = port;
|
||||
unit->fcp_lun = fcp_lun;
|
||||
unit->sysfs_device.parent = &port->sysfs_device;
|
||||
unit->sysfs_device.release = zfcp_unit_release;
|
||||
unit->dev.parent = &port->dev;
|
||||
unit->dev.release = zfcp_unit_release;
|
||||
|
||||
if (dev_set_name(&unit->sysfs_device, "0x%016llx",
|
||||
if (dev_set_name(&unit->dev, "0x%016llx",
|
||||
(unsigned long long) fcp_lun)) {
|
||||
kfree(unit);
|
||||
goto err_out;
|
||||
@@ -353,13 +323,12 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
|
||||
unit->latencies.cmd.channel.min = 0xFFFFFFFF;
|
||||
unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
|
||||
|
||||
if (device_register(&unit->sysfs_device)) {
|
||||
put_device(&unit->sysfs_device);
|
||||
if (device_register(&unit->dev)) {
|
||||
put_device(&unit->dev);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (sysfs_create_group(&unit->sysfs_device.kobj,
|
||||
&zfcp_sysfs_unit_attrs))
|
||||
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs))
|
||||
goto err_out_put;
|
||||
|
||||
write_lock_irq(&port->unit_list_lock);
|
||||
@@ -371,9 +340,9 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
|
||||
return unit;
|
||||
|
||||
err_out_put:
|
||||
device_unregister(&unit->sysfs_device);
|
||||
device_unregister(&unit->dev);
|
||||
err_out:
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
|
||||
@@ -539,7 +508,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
||||
if (zfcp_allocate_low_mem_buffers(adapter))
|
||||
goto failed;
|
||||
|
||||
if (zfcp_reqlist_alloc(adapter))
|
||||
adapter->req_list = zfcp_reqlist_alloc();
|
||||
if (!adapter->req_list)
|
||||
goto failed;
|
||||
|
||||
if (zfcp_dbf_adapter_register(adapter))
|
||||
@@ -560,8 +530,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
||||
INIT_LIST_HEAD(&adapter->erp_ready_head);
|
||||
INIT_LIST_HEAD(&adapter->erp_running_head);
|
||||
|
||||
spin_lock_init(&adapter->req_list_lock);
|
||||
|
||||
rwlock_init(&adapter->erp_lock);
|
||||
rwlock_init(&adapter->abort_lock);
|
||||
|
||||
@@ -640,8 +608,7 @@ void zfcp_device_unregister(struct device *dev,
|
||||
|
||||
static void zfcp_port_release(struct device *dev)
|
||||
{
|
||||
struct zfcp_port *port = container_of(dev, struct zfcp_port,
|
||||
sysfs_device);
|
||||
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
|
||||
|
||||
zfcp_ccw_adapter_put(port->adapter);
|
||||
kfree(port);
|
||||
@@ -669,7 +636,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
||||
|
||||
port = zfcp_get_port_by_wwpn(adapter, wwpn);
|
||||
if (port) {
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
retval = -EEXIST;
|
||||
goto err_out;
|
||||
}
|
||||
@@ -689,22 +656,21 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
||||
port->d_id = d_id;
|
||||
port->wwpn = wwpn;
|
||||
port->rport_task = RPORT_NONE;
|
||||
port->sysfs_device.parent = &adapter->ccw_device->dev;
|
||||
port->sysfs_device.release = zfcp_port_release;
|
||||
port->dev.parent = &adapter->ccw_device->dev;
|
||||
port->dev.release = zfcp_port_release;
|
||||
|
||||
if (dev_set_name(&port->sysfs_device, "0x%016llx",
|
||||
(unsigned long long)wwpn)) {
|
||||
if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
|
||||
kfree(port);
|
||||
goto err_out;
|
||||
}
|
||||
retval = -EINVAL;
|
||||
|
||||
if (device_register(&port->sysfs_device)) {
|
||||
put_device(&port->sysfs_device);
|
||||
if (device_register(&port->dev)) {
|
||||
put_device(&port->dev);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (sysfs_create_group(&port->sysfs_device.kobj,
|
||||
if (sysfs_create_group(&port->dev.kobj,
|
||||
&zfcp_sysfs_port_attrs))
|
||||
goto err_out_put;
|
||||
|
||||
@@ -717,7 +683,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
||||
return port;
|
||||
|
||||
err_out_put:
|
||||
device_unregister(&port->sysfs_device);
|
||||
device_unregister(&port->dev);
|
||||
err_out:
|
||||
zfcp_ccw_adapter_put(adapter);
|
||||
return ERR_PTR(retval);
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
*
|
||||
* Registration and callback for the s390 common I/O layer.
|
||||
*
|
||||
* Copyright IBM Corporation 2002, 2009
|
||||
* Copyright IBM Corporation 2002, 2010
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include "zfcp_ext.h"
|
||||
#include "zfcp_reqlist.h"
|
||||
|
||||
#define ZFCP_MODEL_PRIV 0x4
|
||||
|
||||
@@ -122,12 +123,10 @@ static void zfcp_ccw_remove(struct ccw_device *cdev)
|
||||
zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
|
||||
|
||||
list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
|
||||
zfcp_device_unregister(&unit->sysfs_device,
|
||||
&zfcp_sysfs_unit_attrs);
|
||||
zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
|
||||
|
||||
list_for_each_entry_safe(port, p, &port_remove_lh, list)
|
||||
zfcp_device_unregister(&port->sysfs_device,
|
||||
&zfcp_sysfs_port_attrs);
|
||||
zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
|
||||
|
||||
zfcp_adapter_unregister(adapter);
|
||||
}
|
||||
@@ -162,7 +161,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
|
||||
}
|
||||
|
||||
/* initialize request counter */
|
||||
BUG_ON(!zfcp_reqlist_isempty(adapter));
|
||||
BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
|
||||
adapter->req_no = 0;
|
||||
|
||||
zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
|
||||
|
||||
@@ -140,9 +140,9 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
|
||||
memcpy(response->fsf_status_qual,
|
||||
fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
|
||||
response->fsf_req_status = fsf_req->status;
|
||||
response->sbal_first = fsf_req->queue_req.sbal_first;
|
||||
response->sbal_last = fsf_req->queue_req.sbal_last;
|
||||
response->sbal_response = fsf_req->queue_req.sbal_response;
|
||||
response->sbal_first = fsf_req->qdio_req.sbal_first;
|
||||
response->sbal_last = fsf_req->qdio_req.sbal_last;
|
||||
response->sbal_response = fsf_req->qdio_req.sbal_response;
|
||||
response->pool = fsf_req->pool != NULL;
|
||||
response->erp_action = (unsigned long)fsf_req->erp_action;
|
||||
|
||||
@@ -576,7 +576,8 @@ void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf)
|
||||
struct zfcp_adapter *adapter = dbf->adapter;
|
||||
|
||||
zfcp_dbf_rec_target(id, ref, dbf, &adapter->status,
|
||||
&adapter->erp_counter, 0, 0, 0);
|
||||
&adapter->erp_counter, 0, 0,
|
||||
ZFCP_DBF_INVALID_LUN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,8 +591,8 @@ void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port)
|
||||
struct zfcp_dbf *dbf = port->adapter->dbf;
|
||||
|
||||
zfcp_dbf_rec_target(id, ref, dbf, &port->status,
|
||||
&port->erp_counter, port->wwpn, port->d_id,
|
||||
0);
|
||||
&port->erp_counter, port->wwpn, port->d_id,
|
||||
ZFCP_DBF_INVALID_LUN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -642,10 +643,9 @@ void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
|
||||
r->u.trigger.ps = atomic_read(&port->status);
|
||||
r->u.trigger.wwpn = port->wwpn;
|
||||
}
|
||||
if (unit) {
|
||||
if (unit)
|
||||
r->u.trigger.us = atomic_read(&unit->status);
|
||||
r->u.trigger.fcp_lun = unit->fcp_lun;
|
||||
}
|
||||
r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN;
|
||||
debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
|
||||
spin_unlock_irqrestore(&dbf->rec_lock, flags);
|
||||
}
|
||||
@@ -668,7 +668,7 @@ void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action)
|
||||
r->u.action.action = (unsigned long)erp_action;
|
||||
r->u.action.status = erp_action->status;
|
||||
r->u.action.step = erp_action->step;
|
||||
r->u.action.fsf_req = (unsigned long)erp_action->fsf_req;
|
||||
r->u.action.fsf_req = erp_action->fsf_req_id;
|
||||
debug_event(dbf->rec, 5, r, sizeof(*r));
|
||||
spin_unlock_irqrestore(&dbf->rec_lock, flags);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#define ZFCP_DBF_TAG_SIZE 4
|
||||
#define ZFCP_DBF_ID_SIZE 7
|
||||
|
||||
#define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull
|
||||
|
||||
struct zfcp_dbf_dump {
|
||||
u8 tag[ZFCP_DBF_TAG_SIZE];
|
||||
u32 total_size; /* size of total dump data */
|
||||
@@ -192,10 +194,10 @@ struct zfcp_dbf_san_record {
|
||||
struct zfcp_dbf_san_record_ct_response ct_resp;
|
||||
struct zfcp_dbf_san_record_els els;
|
||||
} u;
|
||||
#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
|
||||
u8 payload[32];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
|
||||
|
||||
struct zfcp_dbf_scsi_record {
|
||||
u8 tag[ZFCP_DBF_TAG_SIZE];
|
||||
u8 tag2[ZFCP_DBF_TAG_SIZE];
|
||||
@@ -301,17 +303,31 @@ void zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
|
||||
|
||||
/**
|
||||
* zfcp_dbf_scsi_result - trace event for SCSI command completion
|
||||
* @tag: tag indicating success or failure of SCSI command
|
||||
* @level: trace level applicable for this event
|
||||
* @adapter: adapter that has been used to issue the SCSI command
|
||||
* @dbf: adapter dbf trace
|
||||
* @scmd: SCSI command pointer
|
||||
* @fsf_req: request used to issue SCSI command (might be NULL)
|
||||
* @req: FSF request used to issue SCSI command
|
||||
*/
|
||||
static inline
|
||||
void zfcp_dbf_scsi_result(const char *tag, int level, struct zfcp_dbf *dbf,
|
||||
struct scsi_cmnd *scmd, struct zfcp_fsf_req *fsf_req)
|
||||
void zfcp_dbf_scsi_result(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd,
|
||||
struct zfcp_fsf_req *req)
|
||||
{
|
||||
zfcp_dbf_scsi("rslt", tag, level, dbf, scmd, fsf_req, 0);
|
||||
if (scmd->result != 0)
|
||||
zfcp_dbf_scsi("rslt", "erro", 3, dbf, scmd, req, 0);
|
||||
else if (scmd->retries > 0)
|
||||
zfcp_dbf_scsi("rslt", "retr", 4, dbf, scmd, req, 0);
|
||||
else
|
||||
zfcp_dbf_scsi("rslt", "norm", 6, dbf, scmd, req, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command
|
||||
* @dbf: adapter dbf trace
|
||||
* @scmd: SCSI command pointer
|
||||
*/
|
||||
static inline
|
||||
void zfcp_dbf_scsi_fail_send(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd)
|
||||
{
|
||||
zfcp_dbf_scsi("rslt", "fail", 4, dbf, scmd, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Global definitions for the zfcp device driver.
|
||||
*
|
||||
* Copyright IBM Corporation 2002, 2009
|
||||
* Copyright IBM Corporation 2002, 2010
|
||||
*/
|
||||
|
||||
#ifndef ZFCP_DEF_H
|
||||
@@ -33,15 +33,13 @@
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/scsi_bsg_fc.h>
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/qdio.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include <asm/sysinfo.h>
|
||||
#include "zfcp_fsf.h"
|
||||
#include "zfcp_qdio.h"
|
||||
|
||||
/********************* GENERAL DEFINES *********************************/
|
||||
|
||||
#define REQUEST_LIST_SIZE 128
|
||||
struct zfcp_reqlist;
|
||||
|
||||
/********************* SCSI SPECIFIC DEFINES *********************************/
|
||||
#define ZFCP_SCSI_ER_TIMEOUT (10*HZ)
|
||||
@@ -129,12 +127,6 @@ struct zfcp_adapter_mempool {
|
||||
mempool_t *qtcb_pool;
|
||||
};
|
||||
|
||||
struct zfcp_qdio_queue {
|
||||
struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
|
||||
u8 first; /* index of next free bfr in queue */
|
||||
atomic_t count; /* number of free buffers in queue */
|
||||
};
|
||||
|
||||
struct zfcp_erp_action {
|
||||
struct list_head list;
|
||||
int action; /* requested action code */
|
||||
@@ -143,8 +135,7 @@ struct zfcp_erp_action {
|
||||
struct zfcp_unit *unit;
|
||||
u32 status; /* recovery status */
|
||||
u32 step; /* active step of this erp action */
|
||||
struct zfcp_fsf_req *fsf_req; /* fsf request currently pending
|
||||
for this action */
|
||||
unsigned long fsf_req_id;
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
@@ -167,29 +158,6 @@ struct zfcp_latencies {
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/** struct zfcp_qdio - basic QDIO data structure
|
||||
* @resp_q: response queue
|
||||
* @req_q: request queue
|
||||
* @stat_lock: lock to protect req_q_util and req_q_time
|
||||
* @req_q_lock; lock to serialize access to request queue
|
||||
* @req_q_time: time of last fill level change
|
||||
* @req_q_util: used for accounting
|
||||
* @req_q_full: queue full incidents
|
||||
* @req_q_wq: used to wait for SBAL availability
|
||||
* @adapter: adapter used in conjunction with this QDIO structure
|
||||
*/
|
||||
struct zfcp_qdio {
|
||||
struct zfcp_qdio_queue resp_q;
|
||||
struct zfcp_qdio_queue req_q;
|
||||
spinlock_t stat_lock;
|
||||
spinlock_t req_q_lock;
|
||||
unsigned long long req_q_time;
|
||||
u64 req_q_util;
|
||||
atomic_t req_q_full;
|
||||
wait_queue_head_t req_q_wq;
|
||||
struct zfcp_adapter *adapter;
|
||||
};
|
||||
|
||||
struct zfcp_adapter {
|
||||
struct kref ref;
|
||||
u64 peer_wwnn; /* P2P peer WWNN */
|
||||
@@ -207,8 +175,7 @@ struct zfcp_adapter {
|
||||
struct list_head port_list; /* remote port list */
|
||||
rwlock_t port_list_lock; /* port list lock */
|
||||
unsigned long req_no; /* unique FSF req number */
|
||||
struct list_head *req_list; /* list of pending reqs */
|
||||
spinlock_t req_list_lock; /* request list lock */
|
||||
struct zfcp_reqlist *req_list;
|
||||
u32 fsf_req_seq_no; /* FSF cmnd seq number */
|
||||
rwlock_t abort_lock; /* Protects against SCSI
|
||||
stack abort/command
|
||||
@@ -241,7 +208,7 @@ struct zfcp_adapter {
|
||||
};
|
||||
|
||||
struct zfcp_port {
|
||||
struct device sysfs_device; /* sysfs device */
|
||||
struct device dev;
|
||||
struct fc_rport *rport; /* rport of fc transport class */
|
||||
struct list_head list; /* list of remote ports */
|
||||
struct zfcp_adapter *adapter; /* adapter used to access port */
|
||||
@@ -263,7 +230,7 @@ struct zfcp_port {
|
||||
};
|
||||
|
||||
struct zfcp_unit {
|
||||
struct device sysfs_device; /* sysfs device */
|
||||
struct device dev;
|
||||
struct list_head list; /* list of logical units */
|
||||
struct zfcp_port *port; /* remote port of unit */
|
||||
atomic_t status; /* status of this logical unit */
|
||||
@@ -276,34 +243,12 @@ struct zfcp_unit {
|
||||
struct work_struct scsi_work;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zfcp_queue_req - queue related values for a request
|
||||
* @sbal_number: number of free SBALs
|
||||
* @sbal_first: first SBAL for this request
|
||||
* @sbal_last: last SBAL for this request
|
||||
* @sbal_limit: last possible SBAL for this request
|
||||
* @sbale_curr: current SBALE at creation of this request
|
||||
* @sbal_response: SBAL used in interrupt
|
||||
* @qdio_outb_usage: usage of outbound queue
|
||||
* @qdio_inb_usage: usage of inbound queue
|
||||
*/
|
||||
struct zfcp_queue_req {
|
||||
u8 sbal_number;
|
||||
u8 sbal_first;
|
||||
u8 sbal_last;
|
||||
u8 sbal_limit;
|
||||
u8 sbale_curr;
|
||||
u8 sbal_response;
|
||||
u16 qdio_outb_usage;
|
||||
u16 qdio_inb_usage;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zfcp_fsf_req - basic FSF request structure
|
||||
* @list: list of FSF requests
|
||||
* @req_id: unique request ID
|
||||
* @adapter: adapter this request belongs to
|
||||
* @queue_req: queue related values
|
||||
* @qdio_req: qdio queue related values
|
||||
* @completion: used to signal the completion of the request
|
||||
* @status: status of the request
|
||||
* @fsf_command: FSF command issued
|
||||
@@ -321,7 +266,7 @@ struct zfcp_fsf_req {
|
||||
struct list_head list;
|
||||
unsigned long req_id;
|
||||
struct zfcp_adapter *adapter;
|
||||
struct zfcp_queue_req queue_req;
|
||||
struct zfcp_qdio_req qdio_req;
|
||||
struct completion completion;
|
||||
u32 status;
|
||||
u32 fsf_command;
|
||||
@@ -352,45 +297,4 @@ struct zfcp_data {
|
||||
#define ZFCP_SET 0x00000100
|
||||
#define ZFCP_CLEAR 0x00000200
|
||||
|
||||
/*
|
||||
* Helper functions for request ID management.
|
||||
*/
|
||||
static inline int zfcp_reqlist_hash(unsigned long req_id)
|
||||
{
|
||||
return req_id % REQUEST_LIST_SIZE;
|
||||
}
|
||||
|
||||
static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter,
|
||||
struct zfcp_fsf_req *fsf_req)
|
||||
{
|
||||
list_del(&fsf_req->list);
|
||||
}
|
||||
|
||||
static inline struct zfcp_fsf_req *
|
||||
zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id)
|
||||
{
|
||||
struct zfcp_fsf_req *request;
|
||||
unsigned int idx;
|
||||
|
||||
idx = zfcp_reqlist_hash(req_id);
|
||||
list_for_each_entry(request, &adapter->req_list[idx], list)
|
||||
if (request->req_id == req_id)
|
||||
return request;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct zfcp_fsf_req *
|
||||
zfcp_reqlist_find_safe(struct zfcp_adapter *adapter, struct zfcp_fsf_req *req)
|
||||
{
|
||||
struct zfcp_fsf_req *request;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) {
|
||||
list_for_each_entry(request, &adapter->req_list[idx], list)
|
||||
if (request == req)
|
||||
return request;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* ZFCP_DEF_H */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Error Recovery Procedures (ERP).
|
||||
*
|
||||
* Copyright IBM Corporation 2002, 2009
|
||||
* Copyright IBM Corporation 2002, 2010
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include "zfcp_ext.h"
|
||||
#include "zfcp_reqlist.h"
|
||||
|
||||
#define ZFCP_MAX_ERPS 3
|
||||
|
||||
@@ -174,7 +175,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
|
||||
|
||||
switch (need) {
|
||||
case ZFCP_ERP_ACTION_REOPEN_UNIT:
|
||||
if (!get_device(&unit->sysfs_device))
|
||||
if (!get_device(&unit->dev))
|
||||
return NULL;
|
||||
atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
|
||||
erp_action = &unit->erp_action;
|
||||
@@ -184,7 +185,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
|
||||
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT:
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
|
||||
if (!get_device(&port->sysfs_device))
|
||||
if (!get_device(&port->dev))
|
||||
return NULL;
|
||||
zfcp_erp_action_dismiss_port(port);
|
||||
atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
|
||||
@@ -478,26 +479,27 @@ static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
|
||||
static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
|
||||
{
|
||||
struct zfcp_adapter *adapter = act->adapter;
|
||||
struct zfcp_fsf_req *req;
|
||||
|
||||
if (!act->fsf_req)
|
||||
if (!act->fsf_req_id)
|
||||
return;
|
||||
|
||||
spin_lock(&adapter->req_list_lock);
|
||||
if (zfcp_reqlist_find_safe(adapter, act->fsf_req) &&
|
||||
act->fsf_req->erp_action == act) {
|
||||
spin_lock(&adapter->req_list->lock);
|
||||
req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id);
|
||||
if (req && req->erp_action == act) {
|
||||
if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
|
||||
ZFCP_STATUS_ERP_TIMEDOUT)) {
|
||||
act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
|
||||
req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
|
||||
zfcp_dbf_rec_action("erscf_1", act);
|
||||
act->fsf_req->erp_action = NULL;
|
||||
req->erp_action = NULL;
|
||||
}
|
||||
if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
|
||||
zfcp_dbf_rec_action("erscf_2", act);
|
||||
if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
|
||||
act->fsf_req = NULL;
|
||||
if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
|
||||
act->fsf_req_id = 0;
|
||||
} else
|
||||
act->fsf_req = NULL;
|
||||
spin_unlock(&adapter->req_list_lock);
|
||||
act->fsf_req_id = 0;
|
||||
spin_unlock(&adapter->req_list->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1179,19 +1181,19 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
|
||||
switch (act->action) {
|
||||
case ZFCP_ERP_ACTION_REOPEN_UNIT:
|
||||
if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
|
||||
get_device(&unit->sysfs_device);
|
||||
get_device(&unit->dev);
|
||||
if (scsi_queue_work(unit->port->adapter->scsi_host,
|
||||
&unit->scsi_work) <= 0)
|
||||
put_device(&unit->sysfs_device);
|
||||
put_device(&unit->dev);
|
||||
}
|
||||
put_device(&unit->sysfs_device);
|
||||
put_device(&unit->dev);
|
||||
break;
|
||||
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT:
|
||||
if (result == ZFCP_ERP_SUCCEEDED)
|
||||
zfcp_scsi_schedule_rport_register(port);
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
break;
|
||||
|
||||
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
|
||||
|
||||
@@ -21,7 +21,6 @@ extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
|
||||
extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
|
||||
u32);
|
||||
extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
|
||||
extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
|
||||
extern void zfcp_sg_free_table(struct scatterlist *, int);
|
||||
extern int zfcp_sg_setup_table(struct scatterlist *, int);
|
||||
extern void zfcp_device_unregister(struct device *,
|
||||
@@ -144,13 +143,9 @@ extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
|
||||
/* zfcp_qdio.c */
|
||||
extern int zfcp_qdio_setup(struct zfcp_adapter *);
|
||||
extern void zfcp_qdio_destroy(struct zfcp_qdio *);
|
||||
extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_queue_req *);
|
||||
extern struct qdio_buffer_element
|
||||
*zfcp_qdio_sbale_req(struct zfcp_qdio *, struct zfcp_queue_req *);
|
||||
extern struct qdio_buffer_element
|
||||
*zfcp_qdio_sbale_curr(struct zfcp_qdio *, struct zfcp_queue_req *);
|
||||
extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_qdio_req *);
|
||||
extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *,
|
||||
struct zfcp_queue_req *, unsigned long,
|
||||
struct zfcp_qdio_req *, unsigned long,
|
||||
struct scatterlist *, int);
|
||||
extern int zfcp_qdio_open(struct zfcp_qdio *);
|
||||
extern void zfcp_qdio_close(struct zfcp_qdio *);
|
||||
|
||||
+11
-12
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Fibre Channel related functions for the zfcp device driver.
|
||||
*
|
||||
* Copyright IBM Corporation 2008, 2009
|
||||
* Copyright IBM Corporation 2008, 2010
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@@ -316,7 +316,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work)
|
||||
|
||||
zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL);
|
||||
out:
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,9 +325,9 @@ out:
|
||||
*/
|
||||
void zfcp_fc_trigger_did_lookup(struct zfcp_port *port)
|
||||
{
|
||||
get_device(&port->sysfs_device);
|
||||
get_device(&port->dev);
|
||||
if (!queue_work(port->adapter->work_queue, &port->gid_pn_work))
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,7 +389,7 @@ static void zfcp_fc_adisc_handler(void *data)
|
||||
zfcp_scsi_schedule_rport_register(port);
|
||||
out:
|
||||
atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
kmem_cache_free(zfcp_data.adisc_cache, adisc);
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ void zfcp_fc_link_test_work(struct work_struct *work)
|
||||
container_of(work, struct zfcp_port, test_link_work);
|
||||
int retval;
|
||||
|
||||
get_device(&port->sysfs_device);
|
||||
get_device(&port->dev);
|
||||
port->rport_task = RPORT_DEL;
|
||||
zfcp_scsi_rport_work(&port->rport_work);
|
||||
|
||||
@@ -455,7 +455,7 @@ void zfcp_fc_link_test_work(struct work_struct *work)
|
||||
zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL);
|
||||
|
||||
out:
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -468,9 +468,9 @@ out:
|
||||
*/
|
||||
void zfcp_fc_test_link(struct zfcp_port *port)
|
||||
{
|
||||
get_device(&port->sysfs_device);
|
||||
get_device(&port->dev);
|
||||
if (!queue_work(port->adapter->work_queue, &port->test_link_work))
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
}
|
||||
|
||||
static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num)
|
||||
@@ -617,8 +617,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
|
||||
|
||||
list_for_each_entry_safe(port, tmp, &remove_lh, list) {
|
||||
zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL);
|
||||
zfcp_device_unregister(&port->sysfs_device,
|
||||
&zfcp_sysfs_port_attrs);
|
||||
zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -731,7 +730,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
|
||||
return -EINVAL;
|
||||
|
||||
d_id = port->d_id;
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
} else
|
||||
d_id = ntoh24(job->request->rqst_data.h_els.port_id);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Implementation of FSF commands.
|
||||
*
|
||||
* Copyright IBM Corporation 2002, 2009
|
||||
* Copyright IBM Corporation 2002, 2010
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "zfcp_ext.h"
|
||||
#include "zfcp_fc.h"
|
||||
#include "zfcp_dbf.h"
|
||||
#include "zfcp_qdio.h"
|
||||
#include "zfcp_reqlist.h"
|
||||
|
||||
static void zfcp_fsf_request_timeout_handler(unsigned long data)
|
||||
{
|
||||
@@ -393,7 +395,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
|
||||
case FSF_PROT_LINK_DOWN:
|
||||
zfcp_fsf_link_down_info_eval(req, "fspse_5",
|
||||
&psq->link_down_info);
|
||||
/* FIXME: reopening adapter now? better wait for link up */
|
||||
/* go through reopen to flush pending requests */
|
||||
zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
|
||||
break;
|
||||
case FSF_PROT_REEST_QUEUE:
|
||||
@@ -457,15 +459,10 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
|
||||
void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
|
||||
{
|
||||
struct zfcp_fsf_req *req, *tmp;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(remove_queue);
|
||||
unsigned int i;
|
||||
|
||||
BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
|
||||
spin_lock_irqsave(&adapter->req_list_lock, flags);
|
||||
for (i = 0; i < REQUEST_LIST_SIZE; i++)
|
||||
list_splice_init(&adapter->req_list[i], &remove_queue);
|
||||
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
|
||||
zfcp_reqlist_move(adapter->req_list, &remove_queue);
|
||||
|
||||
list_for_each_entry_safe(req, tmp, &remove_queue, list) {
|
||||
list_del(&req->list);
|
||||
@@ -495,8 +492,6 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
|
||||
fc_host_port_id(shost) = ntoh24(bottom->s_id);
|
||||
fc_host_speed(shost) = bottom->fc_link_speed;
|
||||
fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
|
||||
fc_host_supported_fc4s(shost)[2] = 1; /* FCP */
|
||||
fc_host_active_fc4s(shost)[2] = 1; /* FCP */
|
||||
|
||||
adapter->hydra_version = bottom->adapter_type;
|
||||
adapter->timer_ticks = bottom->timer_interval;
|
||||
@@ -619,6 +614,10 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
|
||||
fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
|
||||
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
|
||||
fc_host_supported_speeds(shost) = bottom->supported_speed;
|
||||
memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
|
||||
FC_FC4_LIST_SIZE);
|
||||
memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
|
||||
FC_FC4_LIST_SIZE);
|
||||
}
|
||||
|
||||
static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
|
||||
@@ -725,12 +724,12 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
|
||||
req->adapter = adapter;
|
||||
req->fsf_command = fsf_cmd;
|
||||
req->req_id = adapter->req_no;
|
||||
req->queue_req.sbal_number = 1;
|
||||
req->queue_req.sbal_first = req_q->first;
|
||||
req->queue_req.sbal_last = req_q->first;
|
||||
req->queue_req.sbale_curr = 1;
|
||||
req->qdio_req.sbal_number = 1;
|
||||
req->qdio_req.sbal_first = req_q->first;
|
||||
req->qdio_req.sbal_last = req_q->first;
|
||||
req->qdio_req.sbale_curr = 1;
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].addr = (void *) req->req_id;
|
||||
sbale[0].flags |= SBAL_FLAGS0_COMMAND;
|
||||
|
||||
@@ -745,6 +744,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
req->seq_no = adapter->fsf_req_seq_no;
|
||||
req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
|
||||
req->qtcb->prefix.req_id = req->req_id;
|
||||
req->qtcb->prefix.ulp_info = 26;
|
||||
@@ -752,8 +752,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
|
||||
req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION;
|
||||
req->qtcb->header.req_handle = req->req_id;
|
||||
req->qtcb->header.fsf_command = req->fsf_command;
|
||||
req->seq_no = adapter->fsf_req_seq_no;
|
||||
req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
|
||||
sbale[1].addr = (void *) req->qtcb;
|
||||
sbale[1].length = sizeof(struct fsf_qtcb);
|
||||
}
|
||||
@@ -770,25 +768,17 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
|
||||
{
|
||||
struct zfcp_adapter *adapter = req->adapter;
|
||||
struct zfcp_qdio *qdio = adapter->qdio;
|
||||
unsigned long flags;
|
||||
int idx;
|
||||
int with_qtcb = (req->qtcb != NULL);
|
||||
int with_qtcb = (req->qtcb != NULL);
|
||||
int req_id = req->req_id;
|
||||
|
||||
/* put allocated FSF request into hash table */
|
||||
spin_lock_irqsave(&adapter->req_list_lock, flags);
|
||||
idx = zfcp_reqlist_hash(req->req_id);
|
||||
list_add_tail(&req->list, &adapter->req_list[idx]);
|
||||
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
|
||||
zfcp_reqlist_add(adapter->req_list, req);
|
||||
|
||||
req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
|
||||
req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
|
||||
req->issued = get_clock();
|
||||
if (zfcp_qdio_send(qdio, &req->queue_req)) {
|
||||
if (zfcp_qdio_send(qdio, &req->qdio_req)) {
|
||||
del_timer(&req->timer);
|
||||
spin_lock_irqsave(&adapter->req_list_lock, flags);
|
||||
/* lookup request again, list might have changed */
|
||||
if (zfcp_reqlist_find_safe(adapter, req))
|
||||
zfcp_reqlist_remove(adapter, req);
|
||||
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
|
||||
zfcp_reqlist_find_rm(adapter->req_list, req_id);
|
||||
zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
|
||||
return -EIO;
|
||||
}
|
||||
@@ -826,9 +816,9 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
req->queue_req.sbale_curr = 2;
|
||||
req->qdio_req.sbale_curr = 2;
|
||||
|
||||
sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
|
||||
if (!sr_buf) {
|
||||
@@ -837,7 +827,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
|
||||
}
|
||||
memset(sr_buf, 0, sizeof(*sr_buf));
|
||||
req->data = sr_buf;
|
||||
sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_curr(qdio, &req->qdio_req);
|
||||
sbale->addr = (void *) sr_buf;
|
||||
sbale->length = sizeof(*sr_buf);
|
||||
|
||||
@@ -934,7 +924,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
|
||||
ZFCP_STATUS_COMMON_UNBLOCKED)))
|
||||
goto out_error_free;
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1029,7 +1019,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
|
||||
{
|
||||
struct zfcp_adapter *adapter = req->adapter;
|
||||
struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
|
||||
&req->queue_req);
|
||||
&req->qdio_req);
|
||||
u32 feat = adapter->adapter_features;
|
||||
int bytes;
|
||||
|
||||
@@ -1047,15 +1037,15 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
|
||||
bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
|
||||
SBAL_FLAGS0_TYPE_WRITE_READ,
|
||||
sg_req, max_sbals);
|
||||
if (bytes <= 0)
|
||||
return -EIO;
|
||||
req->qtcb->bottom.support.req_buf_length = bytes;
|
||||
req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
|
||||
req->qdio_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
|
||||
|
||||
bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
|
||||
bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
|
||||
SBAL_FLAGS0_TYPE_WRITE_READ,
|
||||
sg_resp, max_sbals);
|
||||
req->qtcb->bottom.support.resp_buf_length = bytes;
|
||||
@@ -1251,7 +1241,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1262,13 +1252,13 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
|
||||
FSF_FEATURE_UPDATE_ALERT;
|
||||
req->erp_action = erp_action;
|
||||
req->handler = zfcp_fsf_exchange_config_data_handler;
|
||||
erp_action->fsf_req = req;
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
|
||||
zfcp_fsf_start_erp_timer(req);
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
erp_action->fsf_req_id = 0;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -1293,7 +1283,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
req->handler = zfcp_fsf_exchange_config_data_handler;
|
||||
@@ -1349,19 +1339,19 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
req->handler = zfcp_fsf_exchange_port_data_handler;
|
||||
req->erp_action = erp_action;
|
||||
erp_action->fsf_req = req;
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
|
||||
zfcp_fsf_start_erp_timer(req);
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
erp_action->fsf_req_id = 0;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -1398,7 +1388,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
|
||||
if (data)
|
||||
req->data = data;
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1484,7 +1474,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
|
||||
}
|
||||
|
||||
out:
|
||||
put_device(&port->sysfs_device);
|
||||
put_device(&port->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1513,7 +1503,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1521,15 +1511,15 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
|
||||
hton24(req->qtcb->bottom.support.d_id, port->d_id);
|
||||
req->data = port;
|
||||
req->erp_action = erp_action;
|
||||
erp_action->fsf_req = req;
|
||||
get_device(&port->sysfs_device);
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
get_device(&port->dev);
|
||||
|
||||
zfcp_fsf_start_erp_timer(req);
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
put_device(&port->sysfs_device);
|
||||
erp_action->fsf_req_id = 0;
|
||||
put_device(&port->dev);
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -1583,7 +1573,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1591,13 +1581,13 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
|
||||
req->data = erp_action->port;
|
||||
req->erp_action = erp_action;
|
||||
req->qtcb->header.port_handle = erp_action->port->handle;
|
||||
erp_action->fsf_req = req;
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
|
||||
zfcp_fsf_start_erp_timer(req);
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
erp_action->fsf_req_id = 0;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -1660,7 +1650,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1715,7 +1705,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1809,7 +1799,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1817,13 +1807,13 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
|
||||
req->qtcb->header.port_handle = erp_action->port->handle;
|
||||
req->erp_action = erp_action;
|
||||
req->handler = zfcp_fsf_close_physical_port_handler;
|
||||
erp_action->fsf_req = req;
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
|
||||
zfcp_fsf_start_erp_timer(req);
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
erp_action->fsf_req_id = 0;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -1982,7 +1972,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -1991,7 +1981,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
|
||||
req->handler = zfcp_fsf_open_unit_handler;
|
||||
req->data = erp_action->unit;
|
||||
req->erp_action = erp_action;
|
||||
erp_action->fsf_req = req;
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
|
||||
if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
|
||||
req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;
|
||||
@@ -2000,7 +1990,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
erp_action->fsf_req_id = 0;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -2068,7 +2058,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -2077,13 +2067,13 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
|
||||
req->handler = zfcp_fsf_close_unit_handler;
|
||||
req->data = erp_action->unit;
|
||||
req->erp_action = erp_action;
|
||||
erp_action->fsf_req = req;
|
||||
erp_action->fsf_req_id = req->req_id;
|
||||
|
||||
zfcp_fsf_start_erp_timer(req);
|
||||
retval = zfcp_fsf_req_send(req);
|
||||
if (retval) {
|
||||
zfcp_fsf_req_free(req);
|
||||
erp_action->fsf_req = NULL;
|
||||
erp_action->fsf_req_id = 0;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&qdio->req_q_lock);
|
||||
@@ -2111,8 +2101,8 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
|
||||
blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
|
||||
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
||||
blktrc.flags |= ZFCP_BLK_REQ_ERROR;
|
||||
blktrc.inb_usage = req->queue_req.qdio_inb_usage;
|
||||
blktrc.outb_usage = req->queue_req.qdio_outb_usage;
|
||||
blktrc.inb_usage = req->qdio_req.qdio_inb_usage;
|
||||
blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
|
||||
|
||||
if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
|
||||
blktrc.flags |= ZFCP_BLK_LAT_VALID;
|
||||
@@ -2169,12 +2159,7 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
|
||||
zfcp_fsf_req_trace(req, scpnt);
|
||||
|
||||
skip_fsfstatus:
|
||||
if (scpnt->result != 0)
|
||||
zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
|
||||
else if (scpnt->retries > 0)
|
||||
zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req);
|
||||
else
|
||||
zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req);
|
||||
zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req);
|
||||
|
||||
scpnt->host_scribble = NULL;
|
||||
(scpnt->scsi_done) (scpnt);
|
||||
@@ -2274,7 +2259,7 @@ skip_fsfstatus:
|
||||
else {
|
||||
zfcp_fsf_send_fcp_command_task_handler(req);
|
||||
req->unit = NULL;
|
||||
put_device(&unit->sysfs_device);
|
||||
put_device(&unit->dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2312,7 +2297,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
get_device(&unit->sysfs_device);
|
||||
get_device(&unit->dev);
|
||||
req->unit = unit;
|
||||
req->data = scsi_cmnd;
|
||||
req->handler = zfcp_fsf_send_fcp_command_handler;
|
||||
@@ -2346,11 +2331,11 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
|
||||
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
|
||||
zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
|
||||
|
||||
real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
|
||||
real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sbtype,
|
||||
scsi_sglist(scsi_cmnd),
|
||||
FSF_MAX_SBALS_PER_REQ);
|
||||
if (unlikely(real_bytes < 0)) {
|
||||
if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
|
||||
if (req->qdio_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
|
||||
dev_err(&adapter->ccw_device->dev,
|
||||
"Oversize data package, unit 0x%016Lx "
|
||||
"on port 0x%016Lx closed\n",
|
||||
@@ -2369,7 +2354,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
|
||||
goto out;
|
||||
|
||||
failed_scsi_cmnd:
|
||||
put_device(&unit->sysfs_device);
|
||||
put_device(&unit->dev);
|
||||
zfcp_fsf_req_free(req);
|
||||
scsi_cmnd->host_scribble = NULL;
|
||||
out:
|
||||
@@ -2415,7 +2400,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
|
||||
req->qtcb->bottom.io.service_class = FSF_CLASS_3;
|
||||
req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
|
||||
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
|
||||
|
||||
@@ -2478,14 +2463,14 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
|
||||
|
||||
req->handler = zfcp_fsf_control_file_handler;
|
||||
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
|
||||
sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
|
||||
sbale[0].flags |= direction;
|
||||
|
||||
bottom = &req->qtcb->bottom.support;
|
||||
bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
|
||||
bottom->option = fsf_cfdc->option;
|
||||
|
||||
bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
|
||||
bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
|
||||
direction, fsf_cfdc->sg,
|
||||
FSF_MAX_SBALS_PER_REQ);
|
||||
if (bytes != ZFCP_CFDC_MAX_SIZE) {
|
||||
@@ -2516,15 +2501,14 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
|
||||
struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
|
||||
struct qdio_buffer_element *sbale;
|
||||
struct zfcp_fsf_req *fsf_req;
|
||||
unsigned long flags, req_id;
|
||||
unsigned long req_id;
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
|
||||
|
||||
sbale = &sbal->element[idx];
|
||||
req_id = (unsigned long) sbale->addr;
|
||||
spin_lock_irqsave(&adapter->req_list_lock, flags);
|
||||
fsf_req = zfcp_reqlist_find(adapter, req_id);
|
||||
fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id);
|
||||
|
||||
if (!fsf_req)
|
||||
/*
|
||||
@@ -2534,11 +2518,8 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
|
||||
panic("error: unknown req_id (%lx) on adapter %s.\n",
|
||||
req_id, dev_name(&adapter->ccw_device->dev));
|
||||
|
||||
list_del(&fsf_req->list);
|
||||
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
|
||||
|
||||
fsf_req->queue_req.sbal_response = sbal_idx;
|
||||
fsf_req->queue_req.qdio_inb_usage =
|
||||
fsf_req->qdio_req.sbal_response = sbal_idx;
|
||||
fsf_req->qdio_req.qdio_inb_usage =
|
||||
atomic_read(&qdio->resp_q.count);
|
||||
zfcp_fsf_req_complete(fsf_req);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include "zfcp_ext.h"
|
||||
#include "zfcp_qdio.h"
|
||||
|
||||
#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
|
||||
|
||||
@@ -28,12 +29,6 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct qdio_buffer_element *
|
||||
zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
|
||||
{
|
||||
return &q->sbal[sbal_idx]->element[sbale_idx];
|
||||
}
|
||||
|
||||
static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id)
|
||||
{
|
||||
struct zfcp_adapter *adapter = qdio->adapter;
|
||||
@@ -106,7 +101,7 @@ static void zfcp_qdio_resp_put_back(struct zfcp_qdio *qdio, int processed)
|
||||
|
||||
if (unlikely(retval)) {
|
||||
atomic_set(&queue->count, count);
|
||||
/* FIXME: Recover this with an adapter reopen? */
|
||||
zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdrpb_1", NULL);
|
||||
} else {
|
||||
queue->first += count;
|
||||
queue->first %= QDIO_MAX_BUFFERS_PER_Q;
|
||||
@@ -145,32 +140,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
|
||||
zfcp_qdio_resp_put_back(qdio, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_qdio_sbale_req - return ptr to SBALE of req_q for a struct zfcp_fsf_req
|
||||
* @qdio: pointer to struct zfcp_qdio
|
||||
* @q_rec: pointer to struct zfcp_queue_rec
|
||||
* Returns: pointer to qdio_buffer_element (SBALE) structure
|
||||
*/
|
||||
struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_qdio *qdio,
|
||||
struct zfcp_queue_req *q_req)
|
||||
{
|
||||
return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_qdio_sbale_curr - return curr SBALE on req_q for a struct zfcp_fsf_req
|
||||
* @fsf_req: pointer to struct fsf_req
|
||||
* Returns: pointer to qdio_buffer_element (SBALE) structure
|
||||
*/
|
||||
struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio,
|
||||
struct zfcp_queue_req *q_req)
|
||||
{
|
||||
return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last,
|
||||
q_req->sbale_curr);
|
||||
}
|
||||
|
||||
static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio,
|
||||
struct zfcp_queue_req *q_req, int max_sbals)
|
||||
struct zfcp_qdio_req *q_req, int max_sbals)
|
||||
{
|
||||
int count = atomic_read(&qdio->req_q.count);
|
||||
count = min(count, max_sbals);
|
||||
@@ -179,7 +150,7 @@ static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio,
|
||||
}
|
||||
|
||||
static struct qdio_buffer_element *
|
||||
zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
|
||||
zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
|
||||
unsigned long sbtype)
|
||||
{
|
||||
struct qdio_buffer_element *sbale;
|
||||
@@ -214,7 +185,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
|
||||
}
|
||||
|
||||
static struct qdio_buffer_element *
|
||||
zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
|
||||
zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
|
||||
unsigned int sbtype)
|
||||
{
|
||||
if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
|
||||
@@ -224,7 +195,7 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
|
||||
}
|
||||
|
||||
static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
|
||||
struct zfcp_queue_req *q_req)
|
||||
struct zfcp_qdio_req *q_req)
|
||||
{
|
||||
struct qdio_buffer **sbal = qdio->req_q.sbal;
|
||||
int first = q_req->sbal_first;
|
||||
@@ -235,7 +206,7 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
|
||||
}
|
||||
|
||||
static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
|
||||
struct zfcp_queue_req *q_req,
|
||||
struct zfcp_qdio_req *q_req,
|
||||
unsigned int sbtype, void *start_addr,
|
||||
unsigned int total_length)
|
||||
{
|
||||
@@ -271,8 +242,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
|
||||
* @max_sbals: upper bound for number of SBALs to be used
|
||||
* Returns: number of bytes, or error (negativ)
|
||||
*/
|
||||
int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio,
|
||||
struct zfcp_queue_req *q_req,
|
||||
int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
|
||||
unsigned long sbtype, struct scatterlist *sg,
|
||||
int max_sbals)
|
||||
{
|
||||
@@ -304,10 +274,10 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio,
|
||||
/**
|
||||
* zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
|
||||
* @qdio: pointer to struct zfcp_qdio
|
||||
* @q_req: pointer to struct zfcp_queue_req
|
||||
* @q_req: pointer to struct zfcp_qdio_req
|
||||
* Returns: 0 on success, error otherwise
|
||||
*/
|
||||
int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req)
|
||||
int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
|
||||
{
|
||||
struct zfcp_qdio_queue *req_q = &qdio->req_q;
|
||||
int first = q_req->sbal_first;
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* zfcp device driver
|
||||
*
|
||||
* Header file for zfcp qdio interface
|
||||
*
|
||||
* Copyright IBM Corporation 2010
|
||||
*/
|
||||
|
||||
#ifndef ZFCP_QDIO_H
|
||||
#define ZFCP_QDIO_H
|
||||
|
||||
#include <asm/qdio.h>
|
||||
|
||||
/**
|
||||
* struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
|
||||
* @sbal: qdio buffers
|
||||
* @first: index of next free buffer in queue
|
||||
* @count: number of free buffers in queue
|
||||
*/
|
||||
struct zfcp_qdio_queue {
|
||||
struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
|
||||
u8 first;
|
||||
atomic_t count;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zfcp_qdio - basic qdio data structure
|
||||
* @resp_q: response queue
|
||||
* @req_q: request queue
|
||||
* @stat_lock: lock to protect req_q_util and req_q_time
|
||||
* @req_q_lock: lock to serialize access to request queue
|
||||
* @req_q_time: time of last fill level change
|
||||
* @req_q_util: used for accounting
|
||||
* @req_q_full: queue full incidents
|
||||
* @req_q_wq: used to wait for SBAL availability
|
||||
* @adapter: adapter used in conjunction with this qdio structure
|
||||
*/
|
||||
struct zfcp_qdio {
|
||||
struct zfcp_qdio_queue resp_q;
|
||||
struct zfcp_qdio_queue req_q;
|
||||
spinlock_t stat_lock;
|
||||
spinlock_t req_q_lock;
|
||||
unsigned long long req_q_time;
|
||||
u64 req_q_util;
|
||||
atomic_t req_q_full;
|
||||
wait_queue_head_t req_q_wq;
|
||||
struct zfcp_adapter *adapter;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zfcp_qdio_req - qdio queue related values for a request
|
||||
* @sbal_number: number of free sbals
|
||||
* @sbal_first: first sbal for this request
|
||||
* @sbal_last: last sbal for this request
|
||||
* @sbal_limit: last possible sbal for this request
|
||||
* @sbale_curr: current sbale at creation of this request
|
||||
* @sbal_response: sbal used in interrupt
|
||||
* @qdio_outb_usage: usage of outbound queue
|
||||
* @qdio_inb_usage: usage of inbound queue
|
||||
*/
|
||||
struct zfcp_qdio_req {
|
||||
u8 sbal_number;
|
||||
u8 sbal_first;
|
||||
u8 sbal_last;
|
||||
u8 sbal_limit;
|
||||
u8 sbale_curr;
|
||||
u8 sbal_response;
|
||||
u16 qdio_outb_usage;
|
||||
u16 qdio_inb_usage;
|
||||
};
|
||||
|
||||
/**
|
||||
* zfcp_qdio_sbale - return pointer to sbale in qdio queue
|
||||
* @q: queue where to find sbal
|
||||
* @sbal_idx: sbal index in queue
|
||||
* @sbale_idx: sbale index in sbal
|
||||
*/
|
||||
static inline struct qdio_buffer_element *
|
||||
zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
|
||||
{
|
||||
return &q->sbal[sbal_idx]->element[sbale_idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_qdio_sbale_req - return pointer to sbale on req_q for a request
|
||||
* @qdio: pointer to struct zfcp_qdio
|
||||
* @q_rec: pointer to struct zfcp_qdio_req
|
||||
* Returns: pointer to qdio_buffer_element (sbale) structure
|
||||
*/
|
||||
static inline struct qdio_buffer_element *
|
||||
zfcp_qdio_sbale_req(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
|
||||
{
|
||||
return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_qdio_sbale_curr - return current sbale on req_q for a request
|
||||
* @qdio: pointer to struct zfcp_qdio
|
||||
* @fsf_req: pointer to struct zfcp_fsf_req
|
||||
* Returns: pointer to qdio_buffer_element (sbale) structure
|
||||
*/
|
||||
static inline struct qdio_buffer_element *
|
||||
zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
|
||||
{
|
||||
return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last,
|
||||
q_req->sbale_curr);
|
||||
}
|
||||
|
||||
#endif /* ZFCP_QDIO_H */
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* zfcp device driver
|
||||
*
|
||||
* Data structure and helper functions for tracking pending FSF
|
||||
* requests.
|
||||
*
|
||||
* Copyright IBM Corporation 2009
|
||||
*/
|
||||
|
||||
#ifndef ZFCP_REQLIST_H
|
||||
#define ZFCP_REQLIST_H
|
||||
|
||||
/* number of hash buckets */
|
||||
#define ZFCP_REQ_LIST_BUCKETS 128
|
||||
|
||||
/**
|
||||
* struct zfcp_reqlist - Container for request list (reqlist)
|
||||
* @lock: Spinlock for protecting the hash list
|
||||
* @list: Array of hashbuckets, each is a list of requests in this bucket
|
||||
*/
|
||||
struct zfcp_reqlist {
|
||||
spinlock_t lock;
|
||||
struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
|
||||
};
|
||||
|
||||
static inline int zfcp_reqlist_hash(unsigned long req_id)
|
||||
{
|
||||
return req_id % ZFCP_REQ_LIST_BUCKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_alloc - Allocate and initialize reqlist
|
||||
*
|
||||
* Returns pointer to allocated reqlist on success, or NULL on
|
||||
* allocation failure.
|
||||
*/
|
||||
static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct zfcp_reqlist *rl;
|
||||
|
||||
rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL);
|
||||
if (!rl)
|
||||
return NULL;
|
||||
|
||||
spin_lock_init(&rl->lock);
|
||||
|
||||
for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
|
||||
INIT_LIST_HEAD(&rl->buckets[i]);
|
||||
|
||||
return rl;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_isempty - Check whether the request list empty
|
||||
* @rl: pointer to reqlist
|
||||
*
|
||||
* Returns: 1 if list is empty, 0 if not
|
||||
*/
|
||||
static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
|
||||
if (!list_empty(&rl->buckets[i]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_free - Free allocated memory for reqlist
|
||||
* @rl: The reqlist where to free memory
|
||||
*/
|
||||
static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl)
|
||||
{
|
||||
/* sanity check */
|
||||
BUG_ON(!zfcp_reqlist_isempty(rl));
|
||||
|
||||
kfree(rl);
|
||||
}
|
||||
|
||||
static inline struct zfcp_fsf_req *
|
||||
_zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
|
||||
{
|
||||
struct zfcp_fsf_req *req;
|
||||
unsigned int i;
|
||||
|
||||
i = zfcp_reqlist_hash(req_id);
|
||||
list_for_each_entry(req, &rl->buckets[i], list)
|
||||
if (req->req_id == req_id)
|
||||
return req;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_find - Lookup FSF request by its request id
|
||||
* @rl: The reqlist where to lookup the FSF request
|
||||
* @req_id: The request id to look for
|
||||
*
|
||||
* Returns a pointer to the FSF request with the specified request id
|
||||
* or NULL if there is no known FSF request with this id.
|
||||
*/
|
||||
static inline struct zfcp_fsf_req *
|
||||
zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct zfcp_fsf_req *req;
|
||||
|
||||
spin_lock_irqsave(&rl->lock, flags);
|
||||
req = _zfcp_reqlist_find(rl, req_id);
|
||||
spin_unlock_irqrestore(&rl->lock, flags);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist
|
||||
* @rl: reqlist where to search and remove entry
|
||||
* @req_id: The request id of the request to look for
|
||||
*
|
||||
* This functions tries to find the FSF request with the specified
|
||||
* id and then removes it from the reqlist. The reqlist lock is held
|
||||
* during both steps of the operation.
|
||||
*
|
||||
* Returns: Pointer to the FSF request if the request has been found,
|
||||
* NULL if it has not been found.
|
||||
*/
|
||||
static inline struct zfcp_fsf_req *
|
||||
zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct zfcp_fsf_req *req;
|
||||
|
||||
spin_lock_irqsave(&rl->lock, flags);
|
||||
req = _zfcp_reqlist_find(rl, req_id);
|
||||
if (req)
|
||||
list_del(&req->list);
|
||||
spin_unlock_irqrestore(&rl->lock, flags);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_add - Add entry to reqlist
|
||||
* @rl: reqlist where to add the entry
|
||||
* @req: The entry to add
|
||||
*
|
||||
* The request id always increases. As an optimization new requests
|
||||
* are added here with list_add_tail at the end of the bucket lists
|
||||
* while old requests are looked up starting at the beginning of the
|
||||
* lists.
|
||||
*/
|
||||
static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl,
|
||||
struct zfcp_fsf_req *req)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long flags;
|
||||
|
||||
i = zfcp_reqlist_hash(req->req_id);
|
||||
|
||||
spin_lock_irqsave(&rl->lock, flags);
|
||||
list_add_tail(&req->list, &rl->buckets[i]);
|
||||
spin_unlock_irqrestore(&rl->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_reqlist_move - Move all entries from reqlist to simple list
|
||||
* @rl: The zfcp_reqlist where to remove all entries
|
||||
* @list: The list where to move all entries
|
||||
*/
|
||||
static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
|
||||
struct list_head *list)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rl->lock, flags);
|
||||
for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
|
||||
list_splice_init(&rl->buckets[i], list);
|
||||
spin_unlock_irqrestore(&rl->lock, flags);
|
||||
}
|
||||
|
||||
#endif /* ZFCP_REQLIST_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user