提交 c70b5296 编写于 作者: L Linus Torvalds

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: (84 commits)
  [SCSI] be2iscsi: SGE Len == 64K
  [SCSI] be2iscsi: Remove premature free of cid
  [SCSI] be2iscsi: More time for FW
  [SCSI] libsas: fix bug for vacant phy
  [SCSI] sd: Fix overflow with big physical blocks
  [SCSI] st: add MTWEOFI to write filemarks without flushing drive buffer
  [SCSI] libsas: Don't issue commands to devices that have been hot-removed
  [SCSI] megaraid_sas: Add Online Controller Reset to MegaRAID SAS drive
  [SCSI] lpfc 8.3.17: Update lpfc driver version to 8.3.17
  [SCSI] lpfc 8.3.17: Replace function reset methodology
  [SCSI] lpfc 8.3.17: SCSI fixes
  [SCSI] lpfc 8.3.17: BSG fixes
  [SCSI] lpfc 8.3.17: SLI Additions and Fixes
  [SCSI] lpfc 8.3.17: Code Cleanup and Locking fixes
  [SCSI] zfcp: Remove scsi_cmnd->serial_number from debug traces
  [SCSI] ipr: fix array error logging
  [SCSI] aha152x: enable PCMCIA on 64bit
  [SCSI] scsi_dh_alua: Handle all states correctly
  [SCSI] cxgb4i: connection and ddp setting update
  [SCSI] cxgb3i: fixed connection over vlan
  ...
......@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai Mäkisara (email
Kai.Makisara@kolumbus.fi)
Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
Last modified: Sun Aug 29 18:25:47 2010 by kai.makisara
BASICS
......@@ -85,6 +85,17 @@ writing and the last operation has been a write. Two filemarks can be
optionally written. In both cases end of data is signified by
returning zero bytes for two consecutive reads.
Writing filemarks without the immediate bit set in the SCSI command block acts
as a synchronization point, i.e., all remaining data form the drive buffers is
written to tape before the command returns. This makes sure that write errors
are caught at that point, but this takes time. In some applications, several
consecutive files must be written fast. The MTWEOFI operation can be used to
write the filemarks without flushing the drive buffer. Writing filemark at
close() is always flushing the drive buffers. However, if the previous
operation is MTWEOFI, close() does not write a filemark. This can be used if
the program wants to close/open the tape device between files and wants to
skip waiting.
If rewind, offline, bsf, or seek is done and previous tape operation was
write, a filemark is written before moving tape.
......@@ -301,6 +312,8 @@ MTBSR Space backward over count records.
MTFSS Space forward over count setmarks.
MTBSS Space backward over count setmarks.
MTWEOF Write count filemarks.
MTWEOFI Write count filemarks with immediate bit set (i.e., does not
wait until data is on tape)
MTWSM Write count setmarks.
MTREW Rewind tape.
MTOFFL Set device off line (often rewind plus eject).
......
......@@ -5945,8 +5945,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
goto out;
mem = kmalloc(iocpage2sz, GFP_KERNEL);
if (!mem)
if (!mem) {
rc = -ENOMEM;
goto out;
}
memcpy(mem, (u8 *)pIoc2, iocpage2sz);
ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
......
......@@ -2,7 +2,8 @@
# Makefile for the S/390 specific device drivers
#
zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
zfcp_fsf.o zfcp_dbf.o zfcp_sysfs.o zfcp_fc.o zfcp_cfdc.o
zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_cfdc.o zfcp_dbf.o zfcp_erp.o \
zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \
zfcp_unit.o
obj-$(CONFIG_ZFCP) += zfcp.o
......@@ -56,7 +56,6 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
struct ccw_device *cdev;
struct zfcp_adapter *adapter;
struct zfcp_port *port;
struct zfcp_unit *unit;
cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
if (!cdev)
......@@ -72,17 +71,11 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
port = zfcp_get_port_by_wwpn(adapter, wwpn);
if (!port)
goto out_port;
flush_work(&port->rport_work);
unit = zfcp_unit_enqueue(port, lun);
if (IS_ERR(unit))
goto out_unit;
zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
zfcp_erp_wait(adapter);
flush_work(&unit->scsi_work);
out_unit:
zfcp_unit_add(port, lun);
put_device(&port->dev);
out_port:
zfcp_ccw_adapter_put(adapter);
out_ccw_device:
......@@ -158,6 +151,9 @@ static int __init zfcp_module_init(void)
fc_attach_transport(&zfcp_transport_functions);
if (!zfcp_data.scsi_transport_template)
goto out_transport;
scsi_transport_reserve_device(zfcp_data.scsi_transport_template,
sizeof(struct zfcp_scsi_dev));
retval = misc_register(&zfcp_cfdc_misc);
if (retval) {
......@@ -210,30 +206,6 @@ static void __exit zfcp_module_exit(void)
module_exit(zfcp_module_exit);
/**
* zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
* @port: pointer to port to search for unit
* @fcp_lun: FCP LUN to search for
*
* Returns: pointer to zfcp_unit or NULL
*/
struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
{
unsigned long flags;
struct zfcp_unit *unit;
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->dev))
unit = NULL;
read_unlock_irqrestore(&port->unit_list_lock, flags);
return unit;
}
read_unlock_irqrestore(&port->unit_list_lock, flags);
return NULL;
}
/**
* zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
* @adapter: pointer to adapter to search for port
......@@ -259,92 +231,6 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
return NULL;
}
/**
* zfcp_unit_release - dequeue unit
* @dev: pointer to device
*
* waits until all work is done on unit and removes it then from the unit->list
* of the associated port.
*/
static void zfcp_unit_release(struct device *dev)
{
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
put_device(&unit->port->dev);
kfree(unit);
}
/**
* zfcp_unit_enqueue - enqueue unit to unit list of a port.
* @port: pointer to port where unit is added
* @fcp_lun: FCP LUN of unit to be enqueued
* Returns: pointer to enqueued unit on success, ERR_PTR on error
*
* Sets up some unit internal structures and creates sysfs entry.
*/
struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
int retval = -ENOMEM;
get_device(&port->dev);
unit = zfcp_get_unit_by_lun(port, fcp_lun);
if (unit) {
put_device(&unit->dev);
retval = -EEXIST;
goto err_out;
}
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
if (!unit)
goto err_out;
unit->port = port;
unit->fcp_lun = fcp_lun;
unit->dev.parent = &port->dev;
unit->dev.release = zfcp_unit_release;
if (dev_set_name(&unit->dev, "0x%016llx",
(unsigned long long) fcp_lun)) {
kfree(unit);
goto err_out;
}
retval = -EINVAL;
INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work);
spin_lock_init(&unit->latencies.lock);
unit->latencies.write.channel.min = 0xFFFFFFFF;
unit->latencies.write.fabric.min = 0xFFFFFFFF;
unit->latencies.read.channel.min = 0xFFFFFFFF;
unit->latencies.read.fabric.min = 0xFFFFFFFF;
unit->latencies.cmd.channel.min = 0xFFFFFFFF;
unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
if (device_register(&unit->dev)) {
put_device(&unit->dev);
goto err_out;
}
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs))
goto err_out_put;
write_lock_irq(&port->unit_list_lock);
list_add_tail(&unit->list, &port->unit_list);
write_unlock_irq(&port->unit_list_lock);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
return unit;
err_out_put:
device_unregister(&unit->dev);
err_out:
put_device(&port->dev);
return ERR_PTR(retval);
}
static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
adapter->pool.erp_req =
......
......@@ -46,8 +46,7 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
if (!adapter)
return 0;
zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"ccresu2", NULL);
zfcp_erp_wait(adapter);
......@@ -164,14 +163,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
adapter->req_no = 0;
zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"ccsonl2", NULL);
zfcp_erp_wait(adapter);
flush_work(&adapter->scan_work);
zfcp_ccw_activate(cdev);
zfcp_ccw_adapter_put(adapter);
return 0;
}
......@@ -224,9 +216,8 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
break;
case CIO_OPER:
dev_info(&cdev->dev, "The FCP device is operational again\n");
zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
ZFCP_STATUS_COMMON_RUNNING,
ZFCP_SET);
zfcp_erp_set_adapter_status(adapter,
ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"ccnoti4", NULL);
break;
......
......@@ -2,9 +2,10 @@
* zfcp device driver
*
* Userspace interface for accessing the
* Access Control Lists / Control File Data Channel
* Access Control Lists / Control File Data Channel;
* handling of response code and states for ports and LUNs.
*
* Copyright IBM Corporation 2008, 2009
* Copyright IBM Corporation 2008, 2010
*/
#define KMSG_COMPONENT "zfcp"
......@@ -261,3 +262,184 @@ struct miscdevice zfcp_cfdc_misc = {
.name = "zfcp_cfdc",
.fops = &zfcp_cfdc_fops,
};
/**
* zfcp_cfdc_adapter_access_changed - Process change in adapter ACT
* @adapter: Adapter where the Access Control Table (ACT) changed
*
* After a change in the adapter ACT, check if access to any
* previously denied resources is now possible.
*/
void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
{
unsigned long flags;
struct zfcp_port *port;
struct scsi_device *sdev;
struct zfcp_scsi_dev *zfcp_sdev;
int status;
if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
return;
read_lock_irqsave(&adapter->port_list_lock, flags);
list_for_each_entry(port, &adapter->port_list, list) {
status = atomic_read(&port->status);
if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
(status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED,
"cfaac_1", NULL);
}
read_unlock_irqrestore(&adapter->port_list_lock, flags);
shost_for_each_device(sdev, port->adapter->scsi_host) {
zfcp_sdev = sdev_to_zfcp(sdev);
status = atomic_read(&zfcp_sdev->status);
if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
(status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
zfcp_erp_lun_reopen(sdev,
ZFCP_STATUS_COMMON_ERP_FAILED,
"cfaac_2", NULL);
}
}
static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
{
u16 subtable = table >> 16;
u16 rule = table & 0xffff;
const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
if (subtable && subtable < ARRAY_SIZE(act_type))
dev_warn(&adapter->ccw_device->dev,
"Access denied according to ACT rule type %s, "
"rule %d\n", act_type[subtable], rule);
}
/**
* zfcp_cfdc_port_denied - Process "access denied" for port
* @port: The port where the acces has been denied
* @qual: The FSF status qualifier for the access denied FSF status
*/
void zfcp_cfdc_port_denied(struct zfcp_port *port,
union fsf_status_qual *qual)
{
dev_warn(&port->adapter->ccw_device->dev,
"Access denied to port 0x%016Lx\n",
(unsigned long long)port->wwpn);
zfcp_act_eval_err(port->adapter, qual->halfword[0]);
zfcp_act_eval_err(port->adapter, qual->halfword[1]);
zfcp_erp_set_port_status(port,
ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED);
}
/**
* zfcp_cfdc_lun_denied - Process "access denied" for LUN
* @sdev: The SCSI device / LUN where the access has been denied
* @qual: The FSF status qualifier for the access denied FSF status
*/
void zfcp_cfdc_lun_denied(struct scsi_device *sdev,
union fsf_status_qual *qual)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
"Access denied to LUN 0x%016Lx on port 0x%016Lx\n",
zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn);
zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[0]);
zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[1]);
zfcp_erp_set_lun_status(sdev,
ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED);
atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
}
/**
* zfcp_cfdc_lun_shrng_vltn - Evaluate LUN sharing violation status
* @sdev: The LUN / SCSI device where sharing violation occurred
* @qual: The FSF status qualifier from the LUN sharing violation
*/
void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *sdev,
union fsf_status_qual *qual)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
if (qual->word[0])
dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
"LUN 0x%Lx on port 0x%Lx is already in "
"use by CSS%d, MIF Image ID %x\n",
zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn,
qual->fsf_queue_designator.cssid,
qual->fsf_queue_designator.hla);
else
zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->word[2]);
zfcp_erp_set_lun_status(sdev,
ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED);
atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
}
/**
* zfcp_cfdc_open_lun_eval - Eval access ctrl. status for successful "open lun"
* @sdev: The SCSI device / LUN where to evaluate the status
* @bottom: The qtcb bottom with the status from the "open lun"
*
* Returns: 0 if LUN is usable, -EACCES if the access control table
* reports an unsupported configuration.
*/
int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev,
struct fsf_qtcb_bottom_support *bottom)
{
int shared, rw;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
if ((adapter->connection_features & FSF_FEATURE_NPIV_MODE) ||
!(adapter->adapter_features & FSF_FEATURE_LUN_SHARING) ||
zfcp_ccw_priv_sch(adapter))
return 0;
shared = !(bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE);
rw = (bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
if (shared)
atomic_set_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
if (!rw) {
atomic_set_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
dev_info(&adapter->ccw_device->dev, "SCSI device at LUN "
"0x%016Lx on port 0x%016Lx opened read-only\n",
zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn);
}
if (!shared && !rw) {
dev_err(&adapter->ccw_device->dev, "Exclusive read-only access "
"not supported (LUN 0x%016Lx, port 0x%016Lx)\n",
zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn);
zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL);
return -EACCES;
}
if (shared && rw) {
dev_err(&adapter->ccw_device->dev,
"Shared read-write access not supported "
"(LUN 0x%016Lx, port 0x%016Lx)\n",
zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn);
zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL);
return -EACCES;
}
return 0;
}
......@@ -154,7 +154,6 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
if (scsi_cmnd) {
response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
response->u.fcp.serial = scsi_cmnd->serial_number;
response->u.fcp.data_dir =
qtcb->bottom.io.data_direction;
}
......@@ -330,7 +329,6 @@ static void zfcp_dbf_hba_view_response(char **p,
break;
zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir);
zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
*p += sprintf(*p, "\n");
break;
......@@ -482,7 +480,7 @@ static int zfcp_dbf_rec_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun);
zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as);
zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps);
zfcp_dbf_out(&p, "unit_status", "0x%08x", r->u.trigger.us);
zfcp_dbf_out(&p, "lun_status", "0x%08x", r->u.trigger.ls);
break;
case ZFCP_REC_DBF_ID_ACTION:
zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
......@@ -600,19 +598,20 @@ void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port)
}
/**
* zfcp_dbf_rec_unit - trace event for unit state change
* zfcp_dbf_rec_lun - trace event for LUN state change
* @id: identifier for trigger of state change
* @ref: additional reference (e.g. request)
* @unit: unit
* @sdev: SCSI device
*/
void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
void zfcp_dbf_rec_lun(char *id, void *ref, struct scsi_device *sdev)
{
struct zfcp_port *port = unit->port;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_port *port = zfcp_sdev->port;
struct zfcp_dbf *dbf = port->adapter->dbf;
zfcp_dbf_rec_target(id, ref, dbf, &unit->status,
&unit->erp_counter, port->wwpn, port->d_id,
unit->fcp_lun);
zfcp_dbf_rec_target(id, ref, dbf, &zfcp_sdev->status,
&zfcp_sdev->erp_counter, port->wwpn, port->d_id,
zfcp_scsi_dev_lun(sdev));
}
/**
......@@ -624,11 +623,11 @@ void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
* @action: address of error recovery action struct
* @adapter: adapter
* @port: port
* @unit: unit
* @sdev: SCSI device
*/
void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
struct zfcp_adapter *adapter, struct zfcp_port *port,
struct zfcp_unit *unit)
struct scsi_device *sdev)
{
struct zfcp_dbf *dbf = adapter->dbf;
struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
......@@ -647,9 +646,10 @@ 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)
r->u.trigger.us = atomic_read(&unit->status);
r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN;
if (sdev)
r->u.trigger.ls = atomic_read(&sdev_to_zfcp(sdev)->status);
r->u.trigger.fcp_lun = sdev ? zfcp_scsi_dev_lun(sdev) :
ZFCP_DBF_INVALID_LUN;
debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
......@@ -879,7 +879,6 @@ void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
}
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
rec->scsi_serial = scsi_cmnd->serial_number;
memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
......@@ -948,7 +947,6 @@ static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun);
zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result);
zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd);
zfcp_dbf_out(&p, "scsi_serial", "0x%016Lx", r->scsi_serial);
zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE,
0, ZFCP_DBF_SCSI_OPCODE);
zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries);
......
......@@ -60,7 +60,7 @@ struct zfcp_dbf_rec_record_trigger {
u8 need;
u32 as;
u32 ps;
u32 us;
u32 ls;
u64 ref;
u64 action;
u64 wwpn;
......@@ -110,7 +110,6 @@ struct zfcp_dbf_hba_record_response {
union {
struct {
u64 cmnd;
u64 serial;
u32 data_dir;
} fcp;
struct {
......@@ -206,7 +205,6 @@ struct zfcp_dbf_scsi_record {
u32 scsi_lun;
u32 scsi_result;
u64 scsi_cmnd;
u64 scsi_serial;
#define ZFCP_DBF_SCSI_OPCODE 16
u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
u8 scsi_retries;
......@@ -350,16 +348,16 @@ void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf,
/**
* zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset
* @tag: tag indicating success or failure of reset operation
* @scmnd: SCSI command which caused this error recovery
* @flag: indicates type of reset (Target Reset, Logical Unit Reset)
* @unit: unit that needs reset
* @scsi_cmnd: SCSI command which caused this error recovery
*/
static inline
void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
struct scsi_cmnd *scsi_cmnd)
void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0);
}
#endif /* ZFCP_DBF_H */
......@@ -85,8 +85,8 @@ struct zfcp_reqlist;
#define ZFCP_STATUS_PORT_LINK_TEST 0x00000002
/* logical unit status */
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
#define ZFCP_STATUS_LUN_SHARED 0x00000004
#define ZFCP_STATUS_LUN_READONLY 0x00000008
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
......@@ -118,7 +118,7 @@ struct zfcp_erp_action {
int action; /* requested action code */
struct zfcp_adapter *adapter; /* device which should be recovered */
struct zfcp_port *port;
struct zfcp_unit *unit;
struct scsi_device *sdev;
u32 status; /* recovery status */
u32 step; /* active step of this erp action */
unsigned long fsf_req_id;
......@@ -219,20 +219,65 @@ struct zfcp_port {
unsigned int starget_id;
};
/**
* struct zfcp_unit - LUN configured via zfcp sysfs
* @dev: struct device for sysfs representation and reference counting
* @list: entry in LUN/unit list per zfcp_port
* @port: reference to zfcp_port where this LUN is configured
* @fcp_lun: 64 bit LUN value
* @scsi_work: for running scsi_scan_target
*
* This is the representation of a LUN that has been configured for
* usage. The main data here is the 64 bit LUN value, data for
* running I/O and recovery is in struct zfcp_scsi_dev.
*/
struct zfcp_unit {
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 */
u64 fcp_lun; /* own FCP_LUN */
u32 handle; /* handle assigned by FSF */
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
struct zfcp_latencies latencies;
struct device dev;
struct list_head list;
struct zfcp_port *port;
u64 fcp_lun;
struct work_struct scsi_work;
};
/**
* struct zfcp_scsi_dev - zfcp data per SCSI device
* @status: zfcp internal status flags
* @lun_handle: handle from "open lun" for issuing FSF requests
* @erp_action: zfcp erp data for opening and recovering this LUN
* @erp_counter: zfcp erp counter for this LUN
* @latencies: FSF channel and fabric latencies
* @port: zfcp_port where this LUN belongs to
*/
struct zfcp_scsi_dev {
atomic_t status;
u32 lun_handle;
struct zfcp_erp_action erp_action;
atomic_t erp_counter;
struct zfcp_latencies latencies;
struct zfcp_port *port;
};
/**
* sdev_to_zfcp - Access zfcp LUN data for SCSI device
* @sdev: scsi_device where to get the zfcp_scsi_dev pointer
*/
static inline struct zfcp_scsi_dev *sdev_to_zfcp(struct scsi_device *sdev)
{
return scsi_transport_device_data(sdev);
}
/**
* zfcp_scsi_dev_lun - Return SCSI device LUN as 64 bit FCP LUN
* @sdev: SCSI device where to get the LUN from
*/
static inline u64 zfcp_scsi_dev_lun(struct scsi_device *sdev)
{
u64 fcp_lun;
int_to_scsilun(sdev->lun, (struct scsi_lun *)&fcp_lun);
return fcp_lun;
}
/**
* struct zfcp_fsf_req - basic FSF request structure
* @list: list of FSF requests
......@@ -249,7 +294,6 @@ struct zfcp_unit {
* @erp_action: reference to erp action if request issued on behalf of ERP
* @pool: reference to memory pool if used for this request
* @issued: time when request was send (STCK)
* @unit: reference to unit if this request is a SCSI request
* @handler: handler which should be called to process response
*/
struct zfcp_fsf_req {
......@@ -267,7 +311,6 @@ struct zfcp_fsf_req {
struct zfcp_erp_action *erp_action;
mempool_t *pool;
unsigned long long issued;
struct zfcp_unit *unit;
void (*handler)(struct zfcp_fsf_req *);
};
......@@ -282,9 +325,4 @@ struct zfcp_data {
struct kmem_cache *adisc_cache;
};
/********************** ZFCP SPECIFIC DEFINES ********************************/
#define ZFCP_SET 0x00000100
#define ZFCP_CLEAR 0x00000200
#endif /* ZFCP_DEF_H */
此差异已折叠。
......@@ -15,12 +15,10 @@
#include "zfcp_fc.h"
/* zfcp_aux.c */
extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
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 void zfcp_sg_free_table(struct scatterlist *, int);
extern int zfcp_sg_setup_table(struct scatterlist *, int);
extern void zfcp_device_unregister(struct device *,
......@@ -36,6 +34,14 @@ extern void zfcp_ccw_adapter_put(struct zfcp_adapter *);
/* zfcp_cfdc.c */
extern struct miscdevice zfcp_cfdc_misc;
extern void zfcp_cfdc_port_denied(struct zfcp_port *, union fsf_status_qual *);
extern void zfcp_cfdc_lun_denied(struct scsi_device *, union fsf_status_qual *);
extern void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *,
union fsf_status_qual *);
extern int zfcp_cfdc_open_lun_eval(struct scsi_device *,
struct fsf_qtcb_bottom_support *);
extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *);
/* zfcp_dbf.c */
extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
......@@ -44,10 +50,10 @@ extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *);
extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *);
extern void zfcp_dbf_rec_lun(char *, void *, struct scsi_device *);
extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
struct zfcp_adapter *, struct zfcp_port *,
struct zfcp_unit *);
struct scsi_device *);
extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
struct zfcp_dbf *);
......@@ -65,34 +71,26 @@ extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *,
unsigned long);
/* zfcp_erp.c */
extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *,
void *, u32, int);
extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32);
extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *);
extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *,
void *);
extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, char *, void *);
extern void zfcp_erp_modify_port_status(struct zfcp_port *, char *, void *, u32,
int);
extern void zfcp_erp_set_port_status(struct zfcp_port *, u32);
extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32);
extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *);
extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *);
extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *,
void *);
extern void zfcp_erp_port_failed(struct zfcp_port *, char *, void *);
extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32,
int);
extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *);
extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *);
extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *);
extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32);
extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *, void *);
extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *, void *);
extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *);
extern int zfcp_erp_thread_setup(struct zfcp_adapter *);
extern void zfcp_erp_thread_kill(struct zfcp_adapter *);
extern void zfcp_erp_wait(struct zfcp_adapter *);
extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long);
extern void zfcp_erp_port_boxed(struct zfcp_port *, char *, void *);
extern void zfcp_erp_unit_boxed(struct zfcp_unit *, char *, void *);
extern void zfcp_erp_port_access_denied(struct zfcp_port *, char *, void *);
extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
void *);
extern void zfcp_erp_timeout_handler(unsigned long);
/* zfcp_fc.c */
......@@ -118,8 +116,8 @@ extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *);
extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
extern int zfcp_fsf_open_lun(struct zfcp_erp_action *);
extern int zfcp_fsf_close_lun(struct zfcp_erp_action *);
extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *,
struct fsf_qtcb_bottom_config *);
......@@ -135,12 +133,10 @@ extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *,
mempool_t *, unsigned int);
extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
struct zfcp_fsf_ct_els *, unsigned int);
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
struct scsi_cmnd *);
extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
struct zfcp_unit *);
extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *);
extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
/* zfcp_qdio.c */
......@@ -163,8 +159,6 @@ extern void zfcp_scsi_rport_work(struct work_struct *);
extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
extern void zfcp_scsi_scan(struct zfcp_unit *);
extern void zfcp_scsi_scan_work(struct work_struct *);
extern void zfcp_scsi_set_prot(struct zfcp_adapter *);
extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
......@@ -175,4 +169,13 @@ extern struct attribute_group zfcp_sysfs_port_attrs;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
/* zfcp_unit.c */
extern int zfcp_unit_add(struct zfcp_port *, u64);
extern int zfcp_unit_remove(struct zfcp_port *, u64);
extern struct zfcp_unit *zfcp_unit_find(struct zfcp_port *, u64);
extern struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit);
extern void zfcp_unit_scsi_scan(struct zfcp_unit *);
extern void zfcp_unit_queue_scsi_scan(struct zfcp_port *);
extern unsigned int zfcp_unit_sdev_status(struct zfcp_unit *);
#endif /* ZFCP_EXT_H */
......@@ -365,7 +365,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work)
}
if (!port->d_id) {
zfcp_erp_port_failed(port, "fcgpn_2", NULL);
zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
goto out;
}
......
此差异已折叠。
......@@ -60,13 +60,11 @@ static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
unsigned long long now, span;
int used;
spin_lock(&qdio->stat_lock);
now = get_clock_monotonic();
span = (now - qdio->req_q_time) >> 12;
used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
qdio->req_q_util += used * span;
qdio->req_q_time = now;
spin_unlock(&qdio->stat_lock);
}
static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
......@@ -84,7 +82,9 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
/* cleanup all SBALs being program-owned now */
zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
spin_lock_irq(&qdio->stat_lock);
zfcp_qdio_account(qdio);
spin_unlock_irq(&qdio->stat_lock);
atomic_add(count, &qdio->req_q_free);
wake_up(&qdio->req_q_wq);
}
......@@ -201,11 +201,11 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
{
spin_lock_bh(&qdio->req_q_lock);
spin_lock_irq(&qdio->req_q_lock);
if (atomic_read(&qdio->req_q_free) ||
!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return 1;
spin_unlock_bh(&qdio->req_q_lock);
spin_unlock_irq(&qdio->req_q_lock);
return 0;
}
......@@ -223,7 +223,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
{
long ret;
spin_unlock_bh(&qdio->req_q_lock);
spin_unlock_irq(&qdio->req_q_lock);
ret = wait_event_interruptible_timeout(qdio->req_q_wq,
zfcp_qdio_sbal_check(qdio), 5 * HZ);
......@@ -239,7 +239,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
}
spin_lock_bh(&qdio->req_q_lock);
spin_lock_irq(&qdio->req_q_lock);
return -EIO;
}
......@@ -254,7 +254,9 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
int retval;
u8 sbal_number = q_req->sbal_number;
spin_lock(&qdio->stat_lock);
zfcp_qdio_account(qdio);
spin_unlock(&qdio->stat_lock);
retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
q_req->sbal_first, sbal_number);
......@@ -328,9 +330,9 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)
return;
/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
spin_lock_bh(&qdio->req_q_lock);
spin_lock_irq(&qdio->req_q_lock);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
spin_unlock_bh(&qdio->req_q_lock);
spin_unlock_irq(&qdio->req_q_lock);
wake_up(&qdio->req_q_wq);
......
......@@ -49,11 +49,12 @@ static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
return sdev->queue_depth;
}
static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
{
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
unit->device = NULL;
put_device(&unit->dev);
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
put_device(&zfcp_sdev->port->dev);
}
static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
......@@ -78,23 +79,16 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
void (*done) (struct scsi_cmnd *))
{
struct zfcp_unit *unit;
struct zfcp_adapter *adapter;
int status, scsi_result, ret;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
int status, scsi_result, ret;
/* reset the status for this request */
scpnt->result = 0;
scpnt->host_scribble = NULL;
scpnt->scsi_done = done;
/*
* figure out adapter and target device
* (stored there by zfcp_scsi_slave_alloc)
*/
adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
unit = scpnt->device->hostdata;
scsi_result = fc_remote_port_chkready(rport);
if (unlikely(scsi_result)) {
scpnt->result = scsi_result;
......@@ -103,11 +97,11 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return 0;
}
status = atomic_read(&unit->status);
status = atomic_read(&zfcp_sdev->status);
if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
!(atomic_read(&unit->port->status) &
!(atomic_read(&zfcp_sdev->port->status) &
ZFCP_STATUS_COMMON_ERP_FAILED)) {
/* only unit access denied, but port is good
/* only LUN access denied, but port is good
* not covered by FC transport, have to fail here */
zfcp_scsi_command_fail(scpnt, DID_ERROR);
return 0;
......@@ -115,8 +109,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
/* This could be either
* open unit pending: this is temporary, will result in
* open unit or ERP_FAILED, so retry command
* open LUN pending: this is temporary, will result in
* open LUN or ERP_FAILED, so retry command
* call to rport_delete pending: mimic retry from
* fc_remote_port_chkready until rport is BLOCKED
*/
......@@ -124,7 +118,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return 0;
}
ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
ret = zfcp_fsf_fcp_cmnd(scpnt);
if (unlikely(ret == -EBUSY))
return SCSI_MLQUEUE_DEVICE_BUSY;
else if (unlikely(ret < 0))
......@@ -133,45 +127,42 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return ret;
}
static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
unsigned int id, u64 lun)
static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
{
unsigned long flags;
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
struct zfcp_adapter *adapter =
(struct zfcp_adapter *) sdev->host->hostdata[0];
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_port *port;
struct zfcp_unit *unit = NULL;
struct zfcp_unit *unit;
read_lock_irqsave(&adapter->port_list_lock, flags);
list_for_each_entry(port, &adapter->port_list, list) {
if (!port->rport || (id != port->rport->scsi_target_id))
continue;
unit = zfcp_get_unit_by_lun(port, lun);
if (unit)
break;
}
read_unlock_irqrestore(&adapter->port_list_lock, flags);
port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
if (!port)
return -ENXIO;
return unit;
}
unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
if (unit)
put_device(&unit->dev);
static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
{
struct zfcp_adapter *adapter;
struct zfcp_unit *unit;
u64 lun;
if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
put_device(&port->dev);
return -ENXIO;
}
adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
if (!adapter)
goto out;
zfcp_sdev->port = port;
zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
spin_lock_init(&zfcp_sdev->latencies.lock);
int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
unit = zfcp_unit_lookup(adapter, sdp->id, lun);
if (unit) {
sdp->hostdata = unit;
unit->device = sdp;
return 0;
}
out:
return -ENXIO;
zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL);
zfcp_erp_wait(port->adapter);
return 0;
}
static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
......@@ -179,7 +170,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
struct Scsi_Host *scsi_host = scpnt->device->host;
struct zfcp_adapter *adapter =
(struct zfcp_adapter *) scsi_host->hostdata[0];
struct zfcp_unit *unit = scpnt->device->hostdata;
struct zfcp_fsf_req *old_req, *abrt_req;
unsigned long flags;
unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
......@@ -203,7 +193,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
write_unlock_irqrestore(&adapter->abort_lock, flags);
while (retry--) {
abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
if (abrt_req)
break;
......@@ -238,14 +228,14 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
{
struct zfcp_unit *unit = scpnt->device->hostdata;
struct zfcp_adapter *adapter = unit->port->adapter;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
struct zfcp_fsf_req *fsf_req = NULL;
int retval = SUCCESS, ret;
int retry = 3;
while (retry--) {
fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
if (fsf_req)
break;
......@@ -256,7 +246,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING)) {
zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
return SUCCESS;
}
}
......@@ -266,10 +256,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
wait_for_completion(&fsf_req->completion);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
retval = FAILED;
} else
zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
zfcp_fsf_req_free(fsf_req);
return retval;
......@@ -287,8 +277,8 @@ static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
struct zfcp_unit *unit = scpnt->device->hostdata;
struct zfcp_adapter *adapter = unit->port->adapter;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
int ret;
zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
......@@ -319,8 +309,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
}
/* tell the SCSI stack some characteristics of this adapter */
adapter->scsi_host->max_id = 1;
adapter->scsi_host->max_lun = 1;
adapter->scsi_host->max_id = 511;
adapter->scsi_host->max_lun = 0xFFFFFFFF;
adapter->scsi_host->max_channel = 0;
adapter->scsi_host->unique_id = dev_id.devno;
adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
......@@ -534,20 +524,6 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
}
}
static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
{
struct zfcp_unit *unit;
read_lock_irq(&port->unit_list_lock);
list_for_each_entry(unit, &port->unit_list, list) {
get_device(&unit->dev);
if (scsi_queue_work(port->adapter->scsi_host,
&unit->scsi_work) <= 0)
put_device(&unit->dev);
}
read_unlock_irq(&port->unit_list_lock);
}
static void zfcp_scsi_rport_register(struct zfcp_port *port)
{
struct fc_rport_identifiers ids;
......@@ -574,7 +550,7 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
port->rport = rport;
port->starget_id = rport->scsi_target_id;
zfcp_scsi_queue_unit_register(port);
zfcp_unit_queue_scsi_scan(port);
}
static void zfcp_scsi_rport_block(struct zfcp_port *port)
......@@ -637,29 +613,6 @@ void zfcp_scsi_rport_work(struct work_struct *work)
put_device(&port->dev);
}
/**
* zfcp_scsi_scan - Register LUN with SCSI midlayer
* @unit: The LUN/unit to register
*/
void zfcp_scsi_scan(struct zfcp_unit *unit)
{
struct fc_rport *rport = unit->port->rport;
if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
scsilun_to_int((struct scsi_lun *)
&unit->fcp_lun), 0);
}
void zfcp_scsi_scan_work(struct work_struct *work)
{
struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
scsi_work);
zfcp_scsi_scan(unit);
put_device(&unit->dev);
}
/**
* zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
* @adapter: The adapter where to configure DIF/DIX for the SCSI host
......@@ -735,7 +688,6 @@ struct fc_function_template zfcp_transport_functions = {
.show_host_port_type = 1,
.show_host_speed = 1,
.show_host_port_id = 1,
.disable_target_scan = 1,
.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
};
......
......@@ -68,63 +68,96 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
atomic_read(&unit->status));
zfcp_unit_sdev_status(unit));
ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
(atomic_read(&unit->status) &
(zfcp_unit_sdev_status(unit) &
ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
(atomic_read(&unit->status) &
(zfcp_unit_sdev_status(unit) &
ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n",
(atomic_read(&unit->status) &
ZFCP_STATUS_UNIT_SHARED) != 0);
(zfcp_unit_sdev_status(unit) &
ZFCP_STATUS_LUN_SHARED) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n",
(atomic_read(&unit->status) &
ZFCP_STATUS_UNIT_READONLY) != 0);
(zfcp_unit_sdev_status(unit) &
ZFCP_STATUS_LUN_READONLY) != 0);
#define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id) \
static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \
\
if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \
return sprintf(buf, "1\n"); \
else \
return sprintf(buf, "0\n"); \
} \
static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
struct device_attribute *attr,\
const char *buf, size_t count)\
{ \
struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \
unsigned long val; \
int retval = 0; \
\
if (!(_feat && get_device(&_feat->dev))) \
return -EBUSY; \
\
if (strict_strtoul(buf, 0, &val) || val != 0) { \
retval = -EINVAL; \
goto out; \
} \
\
zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL, \
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\
zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED, \
_reopen_id, NULL); \
zfcp_erp_wait(_adapter); \
out: \
put_device(&_feat->dev); \
return retval ? retval : (ssize_t) count; \
} \
static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
zfcp_sysfs_##_feat##_failed_show, \
zfcp_sysfs_##_feat##_failed_store);
static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
return sprintf(buf, "1\n");
return sprintf(buf, "0\n");
}
static ssize_t zfcp_sysfs_port_failed_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
unsigned long val;
if (strict_strtoul(buf, 0, &val) || val != 0)
return -EINVAL;
zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2",
NULL);
zfcp_erp_wait(port->adapter);
ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
return count;
}
static ZFCP_DEV_ATTR(port, failed, S_IWUSR | S_IRUGO,
zfcp_sysfs_port_failed_show,
zfcp_sysfs_port_failed_store);
static ssize_t zfcp_sysfs_unit_failed_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
struct scsi_device *sdev;
unsigned int status, failed = 1;
sdev = zfcp_unit_sdev(unit);
if (sdev) {
status = atomic_read(&sdev_to_zfcp(sdev)->status);
failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
scsi_device_put(sdev);
}
return sprintf(buf, "%d\n", failed);
}
static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
unsigned long val;
struct scsi_device *sdev;
if (strict_strtoul(buf, 0, &val) || val != 0)
return -EINVAL;
sdev = zfcp_unit_sdev(unit);
if (sdev) {
zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
"syufai2", NULL);
zfcp_erp_wait(unit->port->adapter);
} else
zfcp_unit_scsi_scan(unit);
return count;
}
static ZFCP_DEV_ATTR(unit, failed, S_IWUSR | S_IRUGO,
zfcp_sysfs_unit_failed_show,
zfcp_sysfs_unit_failed_store);
static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
struct device_attribute *attr,
......@@ -163,8 +196,7 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev,
goto out;
}
zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"syafai2", NULL);
zfcp_erp_wait(adapter);
......@@ -257,28 +289,15 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
const char *buf, size_t count)
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
struct zfcp_unit *unit;
u64 fcp_lun;
int retval = -EINVAL;
if (!(port && get_device(&port->dev)))
return -EBUSY;
if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
goto out;
return -EINVAL;
unit = zfcp_unit_enqueue(port, fcp_lun);
if (IS_ERR(unit))
goto out;
else
retval = 0;
if (zfcp_unit_add(port, fcp_lun))
return -EINVAL;
zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
zfcp_erp_wait(unit->port->adapter);
zfcp_scsi_scan(unit);
out:
put_device(&port->dev);
return retval ? retval : (ssize_t) count;
return count;
}
static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
......@@ -287,42 +306,15 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
const char *buf, size_t count)
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
struct zfcp_unit *unit;
u64 fcp_lun;
int retval = -EINVAL;
struct scsi_device *sdev;
if (!(port && get_device(&port->dev)))
return -EBUSY;
if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
goto out;
return -EINVAL;
unit = zfcp_get_unit_by_lun(port, fcp_lun);
if (!unit)
goto out;
else
retval = 0;
sdev = scsi_device_lookup(port->adapter->scsi_host, 0,
port->starget_id,
scsilun_to_int((struct scsi_lun *)&fcp_lun));
if (sdev) {
scsi_remove_device(sdev);
scsi_device_put(sdev);
}
write_lock_irq(&port->unit_list_lock);
list_del(&unit->list);
write_unlock_irq(&port->unit_list_lock);
put_device(&unit->dev);
if (zfcp_unit_remove(port, fcp_lun))
return -EINVAL;
zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
out:
put_device(&port->dev);
return retval ? retval : (ssize_t) count;
return count;
}
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
......@@ -363,9 +355,9 @@ zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) { \
struct scsi_device *sdev = to_scsi_device(dev); \
struct zfcp_unit *unit = sdev->hostdata; \
struct zfcp_latencies *lat = &unit->latencies; \
struct zfcp_adapter *adapter = unit->port->adapter; \
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
struct zfcp_latencies *lat = &zfcp_sdev->latencies; \
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; \
unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \
\
spin_lock_bh(&lat->lock); \
......@@ -394,8 +386,8 @@ zfcp_sysfs_unit_##_name##_latency_store(struct device *dev, \
const char *buf, size_t count) \
{ \
struct scsi_device *sdev = to_scsi_device(dev); \
struct zfcp_unit *unit = sdev->hostdata; \
struct zfcp_latencies *lat = &unit->latencies; \
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
struct zfcp_latencies *lat = &zfcp_sdev->latencies; \
unsigned long flags; \
\
spin_lock_irqsave(&lat->lock, flags); \
......@@ -423,19 +415,28 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
struct device_attribute *attr,\
char *buf) \
{ \
struct scsi_device *sdev = to_scsi_device(dev); \
struct zfcp_unit *unit = sdev->hostdata; \
struct scsi_device *sdev = to_scsi_device(dev); \
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
struct zfcp_port *port = zfcp_sdev->port; \
\
return sprintf(buf, _format, _value); \
} \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
dev_name(&unit->port->adapter->ccw_device->dev));
dev_name(&port->adapter->ccw_device->dev));
ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
(unsigned long long) unit->port->wwpn);
ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
(unsigned long long) unit->fcp_lun);
(unsigned long long) port->wwpn);
static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
return sprintf(buf, "0x%016llx\n", zfcp_scsi_dev_lun(sdev));
}
static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
......
/*
* zfcp device driver
*
* Tracking of manually configured LUNs and helper functions to
* register the LUNs with the SCSI midlayer.
*
* Copyright IBM Corporation 2010
*/
#include "zfcp_def.h"
#include "zfcp_ext.h"
/**
* zfcp_unit_scsi_scan - Register LUN with SCSI midlayer
* @unit: The zfcp LUN/unit to register
*
* When the SCSI midlayer is not allowed to automatically scan and
* attach SCSI devices, zfcp has to register the single devices with
* the SCSI midlayer.
*/
void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
{
struct fc_rport *rport = unit->port->rport;
unsigned int lun;
lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1);
}
static void zfcp_unit_scsi_scan_work(struct work_struct *work)
{
struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
scsi_work);
zfcp_unit_scsi_scan(unit);
put_device(&unit->dev);
}
/**
* zfcp_unit_queue_scsi_scan - Register configured units on port
* @port: The zfcp_port where to register units
*
* After opening a port, all units configured on this port have to be
* registered with the SCSI midlayer. This function should be called
* after calling fc_remote_port_add, so that the fc_rport is already
* ONLINE and the call to scsi_scan_target runs the same way as the
* call in the FC transport class.
*/
void zfcp_unit_queue_scsi_scan(struct zfcp_port *port)
{
struct zfcp_unit *unit;
read_lock_irq(&port->unit_list_lock);
list_for_each_entry(unit, &port->unit_list, list) {
get_device(&unit->dev);
if (scsi_queue_work(port->adapter->scsi_host,
&unit->scsi_work) <= 0)
put_device(&unit->dev);
}
read_unlock_irq(&port->unit_list_lock);
}
static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
list_for_each_entry(unit, &port->unit_list, list)
if (unit->fcp_lun == fcp_lun) {
get_device(&unit->dev);
return unit;
}
return NULL;
}
/**
* zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN
* @port: zfcp_port where to look for the unit
* @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit
*
* If zfcp_unit is found, a reference is acquired that has to be
* released later.
*
* Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit
* with the specified FCP LUN.
*/
struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
read_lock_irq(&port->unit_list_lock);
unit = _zfcp_unit_find(port, fcp_lun);
read_unlock_irq(&port->unit_list_lock);
return unit;
}
/**
* zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit.
* @dev: pointer to device in zfcp_unit
*/
static void zfcp_unit_release(struct device *dev)
{
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
put_device(&unit->port->dev);
kfree(unit);
}
/**
* zfcp_unit_enqueue - enqueue unit to unit list of a port.
* @port: pointer to port where unit is added
* @fcp_lun: FCP LUN of unit to be enqueued
* Returns: 0 success
*
* Sets up some unit internal structures and creates sysfs entry.
*/
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
unit = zfcp_unit_find(port, fcp_lun);
if (unit) {
put_device(&unit->dev);
return -EEXIST;
}
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
if (!unit)
return -ENOMEM;
unit->port = port;
unit->fcp_lun = fcp_lun;
unit->dev.parent = &port->dev;
unit->dev.release = zfcp_unit_release;
INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);
if (dev_set_name(&unit->dev, "0x%016llx",
(unsigned long long) fcp_lun)) {
kfree(unit);
return -ENOMEM;
}
if (device_register(&unit->dev)) {
put_device(&unit->dev);
return -ENOMEM;
}
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
device_unregister(&unit->dev);
return -EINVAL;
}
get_device(&port->dev);
write_lock_irq(&port->unit_list_lock);
list_add_tail(&unit->list, &port->unit_list);
write_unlock_irq(&port->unit_list_lock);
zfcp_unit_scsi_scan(unit);
return 0;
}
/**
* zfcp_unit_sdev - Return SCSI device for zfcp_unit
* @unit: The zfcp_unit where to get the SCSI device for
*
* Returns: scsi_device pointer on success, NULL if there is no SCSI
* device for this zfcp_unit
*
* On success, the caller also holds a reference to the SCSI device
* that must be released with scsi_device_put.
*/
struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit)
{
struct Scsi_Host *shost;
struct zfcp_port *port;
unsigned int lun;
lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
port = unit->port;
shost = port->adapter->scsi_host;
return scsi_device_lookup(shost, 0, port->starget_id, lun);
}
/**
* zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device
* @unit: The unit to lookup the SCSI device for
*
* Returns the zfcp LUN status field of the SCSI device if the SCSI device
* for the zfcp_unit exists, 0 otherwise.
*/
unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit)
{
unsigned int status = 0;
struct scsi_device *sdev;
struct zfcp_scsi_dev *zfcp_sdev;
sdev = zfcp_unit_sdev(unit);
if (sdev) {
zfcp_sdev = sdev_to_zfcp(sdev);
status = atomic_read(&zfcp_sdev->status);
scsi_device_put(sdev);
}
return status;
}
/**
* zfcp_unit_remove - Remove entry from list of configured units
* @port: The port where to remove the unit from the configuration
* @fcp_lun: The 64 bit LUN of the unit to remove
*
* Returns: -EINVAL if a unit with the specified LUN does not exist,
* 0 on success.
*/
int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
struct scsi_device *sdev;
write_lock_irq(&port->unit_list_lock);
unit = _zfcp_unit_find(port, fcp_lun);
if (unit)
list_del(&unit->list);
write_unlock_irq(&port->unit_list_lock);
if (!unit)
return -EINVAL;
sdev = zfcp_unit_sdev(unit);
if (sdev) {
scsi_remove_device(sdev);
scsi_device_put(sdev);
}
put_device(&unit->dev);
zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
return 0;
}
......@@ -316,7 +316,8 @@ config SCSI_ISCSI_ATTRS
config SCSI_SAS_ATTRS
tristate "SAS Transport Attributes"
depends on SCSI && BLK_DEV_BSG
depends on SCSI
select BLK_DEV_BSG
help
If you wish to export transport-specific information about
each attached SAS device to sysfs, say Y.
......@@ -378,7 +379,7 @@ config ISCSI_BOOT_SYSFS
via sysfs to userspace. If you wish to export this information,
say Y. Otherwise, say N.
source "drivers/scsi/cxgb3i/Kconfig"
source "drivers/scsi/cxgbi/Kconfig"
source "drivers/scsi/bnx2i/Kconfig"
source "drivers/scsi/be2iscsi/Kconfig"
......
......@@ -133,7 +133,8 @@ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
obj-$(CONFIG_SCSI_MVSAS) += mvsas/
obj-$(CONFIG_PS3_ROM) += ps3rom.o
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
obj-$(CONFIG_SCSI_CXGB4_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/
obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
......
......@@ -190,7 +190,7 @@ static int open_getadapter_fib(struct aac_dev * dev, void __user *arg)
/*
* Initialize the mutex used to wait for the next AIF.
*/
init_MUTEX_LOCKED(&fibctx->wait_sem);
sema_init(&fibctx->wait_sem, 0);
fibctx->wait = 0;
/*
* Initialize the fibs and set the count of fibs on
......
......@@ -124,7 +124,7 @@ int aac_fib_setup(struct aac_dev * dev)
fibptr->hw_fib_va = hw_fib;
fibptr->data = (void *) fibptr->hw_fib_va->data;
fibptr->next = fibptr+1; /* Forward chain the fibs */
init_MUTEX_LOCKED(&fibptr->event_wait);
sema_init(&fibptr->event_wait, 0);
spin_lock_init(&fibptr->event_lock);
hw_fib->header.XferState = cpu_to_le32(0xffffffff);
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
......
......@@ -878,8 +878,8 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb,
if (!error) {
if (acb->devstate[id][lun] == ARECA_RAID_GONE)
acb->devstate[id][lun] = ARECA_RAID_GOOD;
ccb->pcmd->result = DID_OK << 16;
arcmsr_ccb_complete(ccb);
ccb->pcmd->result = DID_OK << 16;
arcmsr_ccb_complete(ccb);
}else{
switch (ccb->arcmsr_cdb.DeviceStatus) {
case ARCMSR_DEV_SELECT_TIMEOUT: {
......
......@@ -335,7 +335,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
if (ready)
break;
if (cnt > 6000000) {
if (cnt > 12000000) {
dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
return -EBUSY;
}
......
......@@ -522,7 +522,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
phba->params.cxns_per_ctrl * 2)) {
SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
goto free_ep;
}
......@@ -559,7 +558,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
" status = %d extd_status = %d\n",
status, extd_status);
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
free_mcc_tag(&phba->ctrl, tag);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
......@@ -574,7 +572,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
beiscsi_ep->cid_vld = 1;
SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
}
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return 0;
......
......@@ -2040,7 +2040,7 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
unsigned int num_sg, struct beiscsi_io_task *io_task)
{
struct iscsi_sge *psgl;
unsigned short sg_len, index;
unsigned int sg_len, index;
unsigned int sge_len = 0;
unsigned long long addr;
struct scatterlist *l_sg;
......
obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o
bfa-y += bfad_debugfs.o
bfa-y += bfa_core.o bfa_ioc.o bfa_ioc_ct.o bfa_ioc_cb.o bfa_iocfc.o bfa_fcxp.o
bfa-y += bfa_lps.o bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o
bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o
bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o
bfa-y += bfa_csdebug.o bfa_sm.o plog.o
bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o
bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o
bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o
bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o
ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna -DBFA_PERF_BUILD
ccflags-y := -DBFA_PERF_BUILD
/*
* Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
* published by the Free Software Foundation
*
* 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.
*/
#ifndef __BFA_H__
#define __BFA_H__
#include "bfa_os_inc.h"
#include "bfa_cs.h"
#include "bfa_plog.h"
#include "bfa_defs_svc.h"
#include "bfi.h"
#include "bfa_ioc.h"
struct bfa_s;
typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
/**
* Interrupt message handlers
*/
void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
/**
* Request and response queue related defines
*/
#define BFA_REQQ_NELEMS_MIN (4)
#define BFA_RSPQ_NELEMS_MIN (4)
#define bfa_reqq_pi(__bfa, __reqq) ((__bfa)->iocfc.req_cq_pi[__reqq])
#define bfa_reqq_ci(__bfa, __reqq) \
(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
#define bfa_reqq_full(__bfa, __reqq) \
(((bfa_reqq_pi(__bfa, __reqq) + 1) & \
((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) == \
bfa_reqq_ci(__bfa, __reqq))
#define bfa_reqq_next(__bfa, __reqq) \
(bfa_reqq_full(__bfa, __reqq) ? NULL : \
((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+ bfa_reqq_pi((__bfa), (__reqq)))))
#define bfa_reqq_produce(__bfa, __reqq) do { \
(__bfa)->iocfc.req_cq_pi[__reqq]++; \
(__bfa)->iocfc.req_cq_pi[__reqq] &= \
((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq], \
(__bfa)->iocfc.req_cq_pi[__reqq]); \
mmiowb(); \
} while (0)
#define bfa_rspq_pi(__bfa, __rspq) \
(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
#define bfa_rspq_ci(__bfa, __rspq) ((__bfa)->iocfc.rsp_cq_ci[__rspq])
#define bfa_rspq_elem(__bfa, __rspq, __ci) \
(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
#define CQ_INCR(__index, __size) do { \
(__index)++; \
(__index) &= ((__size) - 1); \
} while (0)
/**
* Queue element to wait for room in request queue. FIFO order is
* maintained when fullfilling requests.
*/
struct bfa_reqq_wait_s {
struct list_head qe;
void (*qresume) (void *cbarg);
void *cbarg;
};
/**
* Circular queue usage assignments
*/
enum {
BFA_REQQ_IOC = 0, /* all low-priority IOC msgs */
BFA_REQQ_FCXP = 0, /* all FCXP messages */
BFA_REQQ_LPS = 0, /* all lport service msgs */
BFA_REQQ_PORT = 0, /* all port messages */
BFA_REQQ_FLASH = 0, /* for flash module */
BFA_REQQ_DIAG = 0, /* for diag module */
BFA_REQQ_RPORT = 0, /* all port messages */
BFA_REQQ_SBOOT = 0, /* all san boot messages */
BFA_REQQ_QOS_LO = 1, /* all low priority IO */
BFA_REQQ_QOS_MD = 2, /* all medium priority IO */
BFA_REQQ_QOS_HI = 3, /* all high priority IO */
};
static inline void
bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
void *cbarg)
{
wqe->qresume = qresume;
wqe->cbarg = cbarg;
}
#define bfa_reqq(__bfa, __reqq) (&(__bfa)->reqq_waitq[__reqq])
/**
* static inline void
* bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
*/
#define bfa_reqq_wait(__bfa, __reqq, __wqe) do { \
\
struct list_head *waitq = bfa_reqq(__bfa, __reqq); \
\
bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \
bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \
\
list_add_tail(&(__wqe)->qe, waitq); \
} while (0)
#define bfa_reqq_wcancel(__wqe) list_del(&(__wqe)->qe)
/**
* Generic BFA callback element.
*/
struct bfa_cb_qe_s {
struct list_head qe;
bfa_cb_cbfn_t cbfn;
bfa_boolean_t once;
u32 rsvd;
void *cbarg;
};
#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
} while (0)
#define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe)
#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
if (!(__hcb_qe)->once) { \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
(__hcb_qe)->once = BFA_TRUE; \
} \
} while (0)
#define bfa_cb_queue_done(__hcb_qe) do { \
(__hcb_qe)->once = BFA_FALSE; \
} while (0)
/**
* PCI devices supported by the current BFA
*/
struct bfa_pciid_s {
u16 device_id;
u16 vendor_id;
};
extern char bfa_version[];
/**
* BFA memory resources
*/
enum bfa_mem_type {
BFA_MEM_TYPE_KVA = 1, /* Kernel Virtual Memory *(non-dma-able) */
BFA_MEM_TYPE_DMA = 2, /* DMA-able memory */
BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
};
struct bfa_mem_elem_s {
enum bfa_mem_type mem_type; /* see enum bfa_mem_type */
u32 mem_len; /* Total Length in Bytes */
u8 *kva; /* kernel virtual address */
u64 dma; /* dma address if DMA memory */
u8 *kva_curp; /* kva allocation cursor */
u64 dma_curp; /* dma allocation cursor */
};
struct bfa_meminfo_s {
struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
};
#define bfa_meminfo_kva(_m) \
((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
#define bfa_meminfo_dma_virt(_m) \
((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
#define bfa_meminfo_dma_phys(_m) \
((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
struct bfa_iocfc_regs_s {
bfa_os_addr_t intr_status;
bfa_os_addr_t intr_mask;
bfa_os_addr_t cpe_q_pi[BFI_IOC_MAX_CQS];
bfa_os_addr_t cpe_q_ci[BFI_IOC_MAX_CQS];
bfa_os_addr_t cpe_q_depth[BFI_IOC_MAX_CQS];
bfa_os_addr_t cpe_q_ctrl[BFI_IOC_MAX_CQS];
bfa_os_addr_t rme_q_ci[BFI_IOC_MAX_CQS];
bfa_os_addr_t rme_q_pi[BFI_IOC_MAX_CQS];
bfa_os_addr_t rme_q_depth[BFI_IOC_MAX_CQS];
bfa_os_addr_t rme_q_ctrl[BFI_IOC_MAX_CQS];
};
/**
* MSIX vector handlers
*/
#define BFA_MSIX_MAX_VECTORS 22
typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
struct bfa_msix_s {
int nvecs;
bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
};
/**
* Chip specific interfaces
*/
struct bfa_hwif_s {
void (*hw_reginit)(struct bfa_s *bfa);
void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
void (*hw_msix_install)(struct bfa_s *bfa);
void (*hw_msix_uninstall)(struct bfa_s *bfa);
void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
u32 *nvecs, u32 *maxvec);
void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
u32 *end);
};
typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
struct bfa_iocfc_s {
struct bfa_s *bfa;
struct bfa_iocfc_cfg_s cfg;
int action;
u32 req_cq_pi[BFI_IOC_MAX_CQS];
u32 rsp_cq_ci[BFI_IOC_MAX_CQS];
struct bfa_cb_qe_s init_hcb_qe;
struct bfa_cb_qe_s stop_hcb_qe;
struct bfa_cb_qe_s dis_hcb_qe;
struct bfa_cb_qe_s stats_hcb_qe;
bfa_boolean_t cfgdone;
struct bfa_dma_s cfg_info;
struct bfi_iocfc_cfg_s *cfginfo;
struct bfa_dma_s cfgrsp_dma;
struct bfi_iocfc_cfgrsp_s *cfgrsp;
struct bfi_iocfc_cfg_reply_s *cfg_reply;
struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS];
struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS];
struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS];
struct bfa_dma_s rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
struct bfa_iocfc_regs_s bfa_regs; /* BFA device registers */
struct bfa_hwif_s hwif;
bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */
void *updateq_cbarg; /* bios callback arg */
u32 intr_mask;
};
#define bfa_lpuid(__bfa) \
bfa_ioc_portid(&(__bfa)->ioc)
#define bfa_msix_init(__bfa, __nvecs) \
((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
#define bfa_msix_install(__bfa) \
((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
#define bfa_msix_uninstall(__bfa) \
((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
#define bfa_isr_mode_set(__bfa, __msix) \
((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \
((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \
__nvecs, __maxvec))
#define bfa_msix_get_rme_range(__bfa, __start, __end) \
((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
#define bfa_msix(__bfa, __vec) \
((__bfa)->msix.handler[__vec](__bfa, __vec))
/*
* FC specific IOC functions.
*/
void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
u32 *dm_len);
void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
void bfa_iocfc_detach(struct bfa_s *bfa);
void bfa_iocfc_init(struct bfa_s *bfa);
void bfa_iocfc_start(struct bfa_s *bfa);
void bfa_iocfc_stop(struct bfa_s *bfa);
void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
void bfa_iocfc_reset_queues(struct bfa_s *bfa);
void bfa_msix_all(struct bfa_s *bfa, int vec);
void bfa_msix_reqq(struct bfa_s *bfa, int vec);
void bfa_msix_rspq(struct bfa_s *bfa, int vec);
void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
void bfa_hwcb_reginit(struct bfa_s *bfa);
void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
void bfa_hwcb_msix_install(struct bfa_s *bfa);
void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
u32 *maxvec);
void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
u32 *end);
void bfa_hwct_reginit(struct bfa_s *bfa);
void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
void bfa_hwct_msix_install(struct bfa_s *bfa);
void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
u32 *maxvec);
void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
u32 *end);
void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);
void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa);
wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa);
void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
struct bfa_boot_pbc_s *pbcfg);
int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
struct bfi_pbc_vport_s *pbc_vport);
/**
*----------------------------------------------------------------------
* BFA public interfaces
*----------------------------------------------------------------------
*/
#define bfa_stats(_mod, _stats) ((_mod)->stats._stats++)
#define bfa_ioc_get_stats(__bfa, __ioc_stats) \
bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
#define bfa_ioc_clear_stats(__bfa) \
bfa_ioc_clr_stats(&(__bfa)->ioc)
#define bfa_get_nports(__bfa) \
bfa_ioc_get_nports(&(__bfa)->ioc)
#define bfa_get_adapter_manufacturer(__bfa, __manufacturer) \
bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
#define bfa_get_adapter_model(__bfa, __model) \
bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
#define bfa_get_adapter_serial_num(__bfa, __serial_num) \
bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
#define bfa_get_adapter_fw_ver(__bfa, __fw_ver) \
bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver) \
bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
#define bfa_get_pci_chip_rev(__bfa, __chip_rev) \
bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
#define bfa_get_ioc_state(__bfa) \
bfa_ioc_get_state(&(__bfa)->ioc)
#define bfa_get_type(__bfa) \
bfa_ioc_get_type(&(__bfa)->ioc)
#define bfa_get_mac(__bfa) \
bfa_ioc_get_mac(&(__bfa)->ioc)
#define bfa_get_mfg_mac(__bfa) \
bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
#define bfa_get_fw_clock_res(__bfa) \
((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo);
void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
void bfa_detach(struct bfa_s *bfa);
void bfa_init(struct bfa_s *bfa);
void bfa_start(struct bfa_s *bfa);
void bfa_stop(struct bfa_s *bfa);
void bfa_attach_fcs(struct bfa_s *bfa);
void bfa_cb_init(void *bfad, bfa_status_t status);
void bfa_cb_updateq(void *bfad, bfa_status_t status);
bfa_boolean_t bfa_intx(struct bfa_s *bfa);
void bfa_intx_disable(struct bfa_s *bfa);
void bfa_intx_enable(struct bfa_s *bfa);
void bfa_isr_enable(struct bfa_s *bfa);
void bfa_isr_disable(struct bfa_s *bfa);
void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
void bfa_adapter_get_attr(struct bfa_s *bfa,
struct bfa_adapter_attr_s *ad_attr);
u64 bfa_adapter_get_id(struct bfa_s *bfa);
bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
struct bfa_iocfc_intr_attr_s *attr);
void bfa_iocfc_enable(struct bfa_s *bfa);
void bfa_iocfc_disable(struct bfa_s *bfa);
void bfa_chip_reset(struct bfa_s *bfa);
void bfa_timer_tick(struct bfa_s *bfa);
#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
/*
* BFA debug API functions
*/
bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf,
u32 *offset, int *buflen);
void bfa_debug_fwsave_clear(struct bfa_s *bfa);
bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data);
bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa);
#endif /* __BFA_H__ */
/*
* Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
* published by the Free Software Foundation
*
* 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.
*/
#ifndef __BFA_CALLBACK_PRIV_H__
#define __BFA_CALLBACK_PRIV_H__
#include <cs/bfa_q.h>
typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
/**
* Generic BFA callback element.
*/
struct bfa_cb_qe_s {
struct list_head qe;
bfa_cb_cbfn_t cbfn;
bfa_boolean_t once;
u32 rsvd;
void *cbarg;
};
#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
} while (0)
#define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe)
#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
if (!(__hcb_qe)->once) { \
list_add_tail((__hcb_qe), &(__bfa)->comp_q); \
(__hcb_qe)->once = BFA_TRUE; \
} \
} while (0)
#define bfa_cb_queue_done(__hcb_qe) do { \
(__hcb_qe)->once = BFA_FALSE; \
} while (0)
#endif /* __BFA_CALLBACK_PRIV_H__ */
/*
* Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
* Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
......@@ -15,37 +15,25 @@
* General Public License for more details.
*/
/**
* bfa_cb_ioim_macros.h BFA IOIM driver interface macros.
*/
#ifndef __BFA_HCB_IOIM_MACROS_H__
#define __BFA_HCB_IOIM_MACROS_H__
#include <bfa_os_inc.h>
/*
* #include <linux/dma-mapping.h>
*
* #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include
* <scsi/scsi_device.h> #include <scsi/scsi_host.h>
*/
#include "bfad_im_compat.h"
#ifndef __BFA_HCB_IOIM_H__
#define __BFA_HCB_IOIM_H__
#include "bfa_os_inc.h"
/*
* task attribute values in FCP-2 FCP_CMND IU
*/
#define SIMPLE_Q 0
#define HEAD_OF_Q 1
#define ORDERED_Q 2
#define ACA_Q 4
#define ACA_Q 4
#define UNTAGGED 5
static inline lun_t
bfad_int_to_lun(u32 luno)
{
union {
u16 scsi_lun[4];
lun_t bfa_lun;
u16 scsi_lun[4];
lun_t bfa_lun;
} lun;
lun.bfa_lun = 0;
......@@ -141,7 +129,7 @@ static inline u8
bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
{
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
u8 task_attr = UNTAGGED;
u8 task_attr = UNTAGGED;
if (cmnd->device->tagged_supported) {
switch (cmnd->tag) {
......@@ -178,4 +166,4 @@ bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
*/
#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE
#endif /* __BFA_HCB_IOIM_MACROS_H__ */
#endif /* __BFA_HCB_IOIM_H__ */
此差异已折叠。
此差异已折叠。
/*
* Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
* Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
......@@ -14,10 +14,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef __BFA_TRC_H__
#define __BFA_TRC_H__
#include <bfa_os_inc.h>
/**
* bfa_cs.h BFA common services
*/
#ifndef __BFA_CS_H__
#define __BFA_CS_H__
#include "bfa_os_inc.h"
/**
* BFA TRC
*/
#ifndef BFA_TRC_MAX
#define BFA_TRC_MAX (4 * 1024)
......@@ -45,7 +54,6 @@ struct bfa_trc_s {
} data;
};
struct bfa_trc_mod_s {
u32 head;
u32 tail;
......@@ -56,25 +64,11 @@ struct bfa_trc_mod_s {
struct bfa_trc_s trc[BFA_TRC_MAX];
};
enum {
BFA_TRC_FW = 1, /* firmware modules */
BFA_TRC_HAL = 2, /* BFA modules */
BFA_TRC_FCS = 3, /* BFA FCS modules */
BFA_TRC_LDRV = 4, /* Linux driver modules */
BFA_TRC_SDRV = 5, /* Solaris driver modules */
BFA_TRC_VDRV = 6, /* vmware driver modules */
BFA_TRC_WDRV = 7, /* windows driver modules */
BFA_TRC_AEN = 8, /* AEN module */
BFA_TRC_BIOS = 9, /* bios driver modules */
BFA_TRC_EFI = 10, /* EFI driver modules */
BNA_TRC_WDRV = 11, /* BNA windows driver modules */
BNA_TRC_VDRV = 12, /* BNA vmware driver modules */
BNA_TRC_SDRV = 13, /* BNA Solaris driver modules */
BNA_TRC_LDRV = 14, /* BNA Linux driver modules */
BNA_TRC_HAL = 15, /* BNA modules */
BFA_TRC_CNA = 16, /* Common modules */
BNA_TRC_IMDRV = 17 /* BNA windows intermediate driver modules */
BFA_TRC_HAL = 1, /* BFA modules */
BFA_TRC_FCS = 2, /* BFA FCS modules */
BFA_TRC_LDRV = 3, /* Linux driver modules */
BFA_TRC_CNA = 4, /* Common modules */
};
#define BFA_TRC_MOD_SH 10
#define BFA_TRC_MOD(__mod) ((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
......@@ -89,18 +83,8 @@ enum {
#define bfa_trc32(_trcp, _data) \
__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
#ifndef BFA_BOOT_BUILD
#define bfa_trc(_trcp, _data) \
__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
#else
void bfa_boot_trc(struct bfa_trc_mod_s *trcmod, u16 fileno,
u16 line, u32 data);
#define bfa_trc(_trcp, _data) \
bfa_boot_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
#endif
static inline void
bfa_trc_init(struct bfa_trc_mod_s *trcm)
......@@ -109,7 +93,6 @@ bfa_trc_init(struct bfa_trc_mod_s *trcm)
trcm->ntrc = BFA_TRC_MAX;
}
static inline void
bfa_trc_stop(struct bfa_trc_mod_s *trcm)
{
......@@ -127,7 +110,7 @@ static inline void
__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
{
int tail = trcm->tail;
struct bfa_trc_s *trc = &trcm->trc[tail];
struct bfa_trc_s *trc = &trcm->trc[tail];
if (trcm->stopped)
return;
......@@ -172,5 +155,210 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
#define bfa_trc_fp(_trcp, _data)
#endif
#endif /* __BFA_TRC_H__ */
/**
* @ BFA LOG interfaces
*/
#define bfa_assert(__cond) do { \
if (!(__cond)) { \
printk(KERN_ERR "assert(%s) failed at %s:%d\\n", \
#__cond, __FILE__, __LINE__); \
} \
} while (0)
#define bfa_sm_fault(__mod, __event) do { \
bfa_trc(__mod, (((u32)0xDEAD << 16) | __event)); \
printk(KERN_ERR "Assertion failure: %s:%d: %d", \
__FILE__, __LINE__, (__event)); \
} while (0)
#ifndef BFA_PERF_BUILD
#define bfa_assert_fp(__cond) bfa_assert(__cond)
#else
#define bfa_assert_fp(__cond)
#endif
/* BFA queue definitions */
#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
/*
* bfa_q_qe_init - to initialize a queue element
*/
#define bfa_q_qe_init(_qe) { \
bfa_q_next(_qe) = (struct list_head *) NULL; \
bfa_q_prev(_qe) = (struct list_head *) NULL; \
}
/*
* bfa_q_deq - dequeue an element from head of the queue
*/
#define bfa_q_deq(_q, _qe) { \
if (!list_empty(_q)) { \
(*((struct list_head **) (_qe))) = bfa_q_next(_q); \
bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \
(struct list_head *) (_q); \
bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\
BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
}
/*
* bfa_q_deq_tail - dequeue an element from tail of the queue
*/
#define bfa_q_deq_tail(_q, _qe) { \
if (!list_empty(_q)) { \
*((struct list_head **) (_qe)) = bfa_q_prev(_q); \
bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \
(struct list_head *) (_q); \
bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
}
static inline int
bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
{
struct list_head *tqe;
tqe = bfa_q_next(q);
while (tqe != q) {
if (tqe == qe)
return 1;
tqe = bfa_q_next(tqe);
if (tqe == NULL)
break;
}
return 0;
}
/*
* #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
* consistent across modules)
*/
#ifndef BFA_PERF_BUILD
#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
#else
#define BFA_Q_DBG_INIT(_qe)
#endif
#define bfa_q_is_on_q(_q, _qe) \
bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
/**
* @ BFA state machine interfaces
*/
typedef void (*bfa_sm_t)(void *sm, int event);
/**
* oc - object class eg. bfa_ioc
* st - state, eg. reset
* otype - object type, eg. struct bfa_ioc_s
* etype - object type, eg. enum ioc_event
*/
#define bfa_sm_state_decl(oc, st, otype, etype) \
static void oc ## _sm_ ## st(otype * fsm, etype event)
#define bfa_sm_set_state(_sm, _state) ((_sm)->sm = (bfa_sm_t)(_state))
#define bfa_sm_send_event(_sm, _event) ((_sm)->sm((_sm), (_event)))
#define bfa_sm_get_state(_sm) ((_sm)->sm)
#define bfa_sm_cmp_state(_sm, _state) ((_sm)->sm == (bfa_sm_t)(_state))
/**
* For converting from state machine function to state encoding.
*/
struct bfa_sm_table_s {
bfa_sm_t sm; /* state machine function */
int state; /* state machine encoding */
char *name; /* state name for display */
};
#define BFA_SM(_sm) ((bfa_sm_t)(_sm))
/**
* State machine with entry actions.
*/
typedef void (*bfa_fsm_t)(void *fsm, int event);
/**
* oc - object class eg. bfa_ioc
* st - state, eg. reset
* otype - object type, eg. struct bfa_ioc_s
* etype - object type, eg. enum ioc_event
*/
#define bfa_fsm_state_decl(oc, st, otype, etype) \
static void oc ## _sm_ ## st(otype * fsm, etype event); \
static void oc ## _sm_ ## st ## _entry(otype * fsm)
#define bfa_fsm_set_state(_fsm, _state) do { \
(_fsm)->fsm = (bfa_fsm_t)(_state); \
_state ## _entry(_fsm); \
} while (0)
#define bfa_fsm_send_event(_fsm, _event) ((_fsm)->fsm((_fsm), (_event)))
#define bfa_fsm_get_state(_fsm) ((_fsm)->fsm)
#define bfa_fsm_cmp_state(_fsm, _state) \
((_fsm)->fsm == (bfa_fsm_t)(_state))
static inline int
bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
{
int i = 0;
while (smt[i].sm && smt[i].sm != sm)
i++;
return smt[i].state;
}
/**
* @ Generic wait counter.
*/
typedef void (*bfa_wc_resume_t) (void *cbarg);
struct bfa_wc_s {
bfa_wc_resume_t wc_resume;
void *wc_cbarg;
int wc_count;
};
static inline void
bfa_wc_up(struct bfa_wc_s *wc)
{
wc->wc_count++;
}
static inline void
bfa_wc_down(struct bfa_wc_s *wc)
{
wc->wc_count--;
if (wc->wc_count == 0)
wc->wc_resume(wc->wc_cbarg);
}
/**
* Initialize a waiting counter.
*/
static inline void
bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
{
wc->wc_resume = wc_resume;
wc->wc_cbarg = wc_cbarg;
wc->wc_count = 0;
bfa_wc_up(wc);
}
/**
* Wait for counter to reach zero
*/
static inline void
bfa_wc_wait(struct bfa_wc_s *wc)
{
bfa_wc_down(wc);
}
#endif /* __BFA_CS_H__ */
/*
* Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
* published by the Free Software Foundation
*
* 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.
*/
#include <cs/bfa_debug.h>
#include <bfa_os_inc.h>
#include <cs/bfa_q.h>
#include <log/bfa_log_hal.h>
/**
* cs_debug_api
*/
void
bfa_panic(int line, char *file, char *panicstr)
{
bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr);
bfa_os_panic();
}
void
bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
{
bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event);
bfa_os_panic();
}
int
bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
{
struct list_head *tqe;
tqe = bfa_q_next(q);
while (tqe != q) {
if (tqe == qe)
return 1;
tqe = bfa_q_next(tqe);
if (tqe == NULL)
break;
}
return 0;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
* published by the Free Software Foundation
*
* 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.
*/
#ifndef __BFA_FWIMG_PRIV_H__
#define __BFA_FWIMG_PRIV_H__
#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */
#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
/**
* BFI FW image type
*/
enum {
BFI_IMAGE_CB_FC,
BFI_IMAGE_CT_FC,
BFI_IMAGE_CT_CNA,
BFI_IMAGE_MAX,
};
extern u32 *bfi_image_get_chunk(int type, uint32_t off);
extern u32 bfi_image_get_size(int type);
extern u32 bfi_image_ct_fc_size;
extern u32 bfi_image_ct_cna_size;
extern u32 bfi_image_cb_fc_size;
extern u32 *bfi_image_ct_fc;
extern u32 *bfi_image_ct_cna;
extern u32 *bfi_image_cb_fc;
#endif /* __BFA_FWIMG_PRIV_H__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册