Commit f9a56f8a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: zfcp fixes (without kfree hack)

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

zfcp host adapter fixes:
 - Reuse freed scsi_ids and scsi_luns for mappings.
 - Order list of ports/units by assigned scsi_id/scsi_lun.
 - Don't update max_id/max_lun in scsi_host anymore.
 - Get rid of all magics.
 - Add owner field to ccw_driver structure.
 - Avoid deadlock on bus->subsys.rwsem.
 - Use a macro for all scsi device sysfs attributes.
 - Change proc_name from "dummy" to "zfcp".
 - Don't wait for scsi_add_device to complete while holding a semaphore.
 - Cleanup include files in zfcp_aux.c & zfcp_def.h.
 - Get rid of zfcp_erp_fsf_req_handler.
 - Proper link up/down handling.
 - Avoid possible NULL pointer dereference in zfcp_erp_schedule_work.
 - Remove module_exit function. Without an external release function for
   the zfcp_port/zfcp_unit objects module unloading is racy.
parent d959cc9f
...@@ -29,43 +29,10 @@ ...@@ -29,43 +29,10 @@
*/ */
/* this drivers version (do not edit !!! generated and updated by cvs) */ /* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_AUX_REVISION "$Revision: 1.98 $" #define ZFCP_AUX_REVISION "$Revision: 1.105 $"
/********************** INCLUDES *********************************************/
#include <linux/init.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/time.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/workqueue.h>
#include <linux/syscalls.h>
#include "zfcp_ext.h" #include "zfcp_ext.h"
#include <asm/semaphore.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/ebcdic.h>
#include <asm/cpcmd.h> /* Debugging only */
#include <asm/processor.h> /* Debugging only */
#include <linux/miscdevice.h>
#include <linux/major.h>
/* accumulated log level (module parameter) */ /* accumulated log level (module parameter) */
static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS; static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS;
static char *device; static char *device;
...@@ -73,7 +40,6 @@ static char *device; ...@@ -73,7 +40,6 @@ static char *device;
/* written against the module interface */ /* written against the module interface */
static int __init zfcp_module_init(void); static int __init zfcp_module_init(void);
static void __exit zfcp_module_exit(void);
int zfcp_reboot_handler(struct notifier_block *, unsigned long, void *); int zfcp_reboot_handler(struct notifier_block *, unsigned long, void *);
...@@ -120,7 +86,6 @@ static struct miscdevice zfcp_cfdc_misc = { ...@@ -120,7 +86,6 @@ static struct miscdevice zfcp_cfdc_misc = {
/* declare driver module init/cleanup functions */ /* declare driver module init/cleanup functions */
module_init(zfcp_module_init); module_init(zfcp_module_init);
module_exit(zfcp_module_exit);
MODULE_AUTHOR("Heiko Carstens <heiko.carstens@de.ibm.com>, " MODULE_AUTHOR("Heiko Carstens <heiko.carstens@de.ibm.com>, "
"Martin Peschke <mpeschke@de.ibm.com>, " "Martin Peschke <mpeschke@de.ibm.com>, "
...@@ -272,7 +237,6 @@ void ...@@ -272,7 +237,6 @@ void
zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
void *add_data, int add_length) void *add_data, int add_length)
{ {
#ifdef ZFCP_DEBUG_COMMANDS
struct zfcp_adapter *adapter = fsf_req->adapter; struct zfcp_adapter *adapter = fsf_req->adapter;
struct scsi_cmnd *scsi_cmnd; struct scsi_cmnd *scsi_cmnd;
int level = 3; int level = 3;
...@@ -299,7 +263,6 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, ...@@ -299,7 +263,6 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
min(ZFCP_CMD_DBF_LENGTH, add_length - i)); min(ZFCP_CMD_DBF_LENGTH, add_length - i));
} }
write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags); write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags);
#endif
} }
/* XXX additionally log unit if available */ /* XXX additionally log unit if available */
...@@ -307,7 +270,6 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, ...@@ -307,7 +270,6 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
void void
zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
{ {
#ifdef ZFCP_DEBUG_COMMANDS
struct zfcp_adapter *adapter; struct zfcp_adapter *adapter;
union zfcp_req_data *req_data; union zfcp_req_data *req_data;
struct zfcp_fsf_req *fsf_req; struct zfcp_fsf_req *fsf_req;
...@@ -335,14 +297,12 @@ zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) ...@@ -335,14 +297,12 @@ zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
debug_text_event(adapter->cmd_dbf, level, ""); debug_text_event(adapter->cmd_dbf, level, "");
} }
write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags); write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags);
#endif
} }
void void
zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text, zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text,
struct fsf_status_read_buffer *status_buffer, int length) struct fsf_status_read_buffer *status_buffer, int length)
{ {
#ifdef ZFCP_DEBUG_INCOMING_ELS
int level = 1; int level = 1;
int i; int i;
...@@ -353,7 +313,6 @@ zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text, ...@@ -353,7 +313,6 @@ zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text,
level, level,
(char *) status_buffer->payload + i, (char *) status_buffer->payload + i,
min(ZFCP_IN_ELS_DBF_LENGTH, length - i)); min(ZFCP_IN_ELS_DBF_LENGTH, length - i));
#endif
} }
/** /**
...@@ -421,8 +380,8 @@ zfcp_init_device_configure(void) ...@@ -421,8 +380,8 @@ zfcp_init_device_configure(void)
goto out_unit; goto out_unit;
up(&zfcp_data.config_sema); up(&zfcp_data.config_sema);
ccw_device_set_online(adapter->ccw_device); ccw_device_set_online(adapter->ccw_device);
down(&zfcp_data.config_sema);
wait_event(unit->scsi_add_wq, atomic_read(&unit->scsi_add_work) == 0); wait_event(unit->scsi_add_wq, atomic_read(&unit->scsi_add_work) == 0);
down(&zfcp_data.config_sema);
zfcp_unit_put(unit); zfcp_unit_put(unit);
out_unit: out_unit:
zfcp_port_put(port); zfcp_port_put(port);
...@@ -518,21 +477,6 @@ zfcp_module_init(void) ...@@ -518,21 +477,6 @@ zfcp_module_init(void)
return retval; return retval;
} }
static void __exit
zfcp_module_exit(void)
{
unregister_reboot_notifier(&zfcp_data.reboot_notifier);
zfcp_ccw_unregister();
misc_deregister(&zfcp_cfdc_misc);
#ifdef CONFIG_S390_SUPPORT
unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd);
#endif
#ifdef ZFCP_STAT_REQSIZES
zfcp_statistics_clear_all();
#endif
ZFCP_LOG_DEBUG("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
}
/* /*
* This function is called automatically by the kernel whenever a reboot or a * This function is called automatically by the kernel whenever a reboot or a
* shut-down is initiated and zfcp is still loaded * shut-down is initiated and zfcp is still loaded
...@@ -784,7 +728,7 @@ static inline int ...@@ -784,7 +728,7 @@ static inline int
zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
{ {
struct scatterlist *sg; struct scatterlist *sg;
int i; unsigned int i;
int retval = 0; int retval = 0;
sg_list->count = size >> PAGE_SHIFT; sg_list->count = size >> PAGE_SHIFT;
...@@ -826,7 +770,7 @@ static inline int ...@@ -826,7 +770,7 @@ static inline int
zfcp_sg_list_free(struct zfcp_sg_list *sg_list) zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
{ {
struct scatterlist *sg; struct scatterlist *sg;
int i; unsigned int i;
int retval = 0; int retval = 0;
BUG_ON((sg_list->sg == NULL) || (sg_list == NULL)); BUG_ON((sg_list->sg == NULL) || (sg_list == NULL));
...@@ -978,7 +922,9 @@ zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn) ...@@ -978,7 +922,9 @@ zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn)
struct zfcp_unit * struct zfcp_unit *
zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
{ {
struct zfcp_unit *unit; struct zfcp_unit *unit, *tmp_unit;
scsi_lun_t scsi_lun;
int found;
/* /*
* check that there is no unit with this FCP_LUN already in list * check that there is no unit with this FCP_LUN already in list
...@@ -1002,13 +948,7 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) ...@@ -1002,13 +948,7 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
init_waitqueue_head(&unit->remove_wq); init_waitqueue_head(&unit->remove_wq);
unit->port = port; unit->port = port;
/*
* FIXME: reuse of scsi_luns!
*/
unit->scsi_lun = port->max_scsi_lun + 1;
unit->fcp_lun = fcp_lun; unit->fcp_lun = fcp_lun;
unit->common_magic = ZFCP_MAGIC;
unit->specific_magic = ZFCP_MAGIC_UNIT;
/* setup for sysfs registration */ /* setup for sysfs registration */
snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun); snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun);
...@@ -1025,43 +965,29 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) ...@@ -1025,43 +965,29 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
} }
if (zfcp_sysfs_unit_create_files(&unit->sysfs_device)) { if (zfcp_sysfs_unit_create_files(&unit->sysfs_device)) {
/*
* failed to create all sysfs attributes, therefore the unit
* must be put on the unit_remove listhead of the port where
* the release function expects it.
*/
write_lock_irq(&zfcp_data.config_lock);
list_add_tail(&unit->list, &port->unit_remove_lh);
write_unlock_irq(&zfcp_data.config_lock);
device_unregister(&unit->sysfs_device); device_unregister(&unit->sysfs_device);
return NULL; return NULL;
} }
/*
* update max SCSI LUN of logical units attached to parent remote port
*/
port->max_scsi_lun++;
/*
* update max SCSI LUN of logical units attached to parent adapter
*/
if (port->adapter->max_scsi_lun < port->max_scsi_lun)
port->adapter->max_scsi_lun = port->max_scsi_lun;
/*
* update max SCSI LUN of logical units attached to host (SCSI stack)
*/
if (port->adapter->scsi_host &&
(port->adapter->scsi_host->max_lun < port->max_scsi_lun))
port->adapter->scsi_host->max_lun = port->max_scsi_lun + 1;
zfcp_unit_get(unit); zfcp_unit_get(unit);
/* unit is new and needs to be added to list */ scsi_lun = 0;
found = 0;
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
list_for_each_entry(tmp_unit, &port->unit_list_head, list) {
if (tmp_unit->scsi_lun != scsi_lun) {
found = 1;
break;
}
scsi_lun++;
}
unit->scsi_lun = scsi_lun;
if (found)
list_add_tail(&unit->list, &tmp_unit->list);
else
list_add_tail(&unit->list, &port->unit_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
list_add_tail(&unit->list, &port->unit_list_head);
write_unlock_irq(&zfcp_data.config_lock); write_unlock_irq(&zfcp_data.config_lock);
port->units++; port->units++;
...@@ -1070,21 +996,17 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) ...@@ -1070,21 +996,17 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
return unit; return unit;
} }
/* locks: config_sema must be held */
void void
zfcp_unit_dequeue(struct zfcp_unit *unit) zfcp_unit_dequeue(struct zfcp_unit *unit)
{ {
/* remove specified unit data structure from list */ zfcp_unit_wait(unit);
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
list_del(&unit->list); list_del(&unit->list);
write_unlock_irq(&zfcp_data.config_lock); write_unlock_irq(&zfcp_data.config_lock);
unit->port->units--; unit->port->units--;
zfcp_port_put(unit->port); zfcp_port_put(unit->port);
zfcp_sysfs_unit_remove_files(&unit->sysfs_device);
kfree(unit); device_unregister(&unit->sysfs_device);
return;
} }
static void * static void *
...@@ -1198,6 +1120,91 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) ...@@ -1198,6 +1120,91 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
mempool_destroy(adapter->pool.data_gid_pn); mempool_destroy(adapter->pool.data_gid_pn);
} }
/**
* zfcp_adapter_debug_register - registers debug feature for an adapter
* @adapter: pointer to adapter for which debug features should be registered
* return: -ENOMEM on error, 0 otherwise
*/
int
zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
{
char dbf_name[20];
/* debug feature area which records fsf request sequence numbers */
sprintf(dbf_name, ZFCP_REQ_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->req_dbf = debug_register(dbf_name,
ZFCP_REQ_DBF_INDEX,
ZFCP_REQ_DBF_AREAS,
ZFCP_REQ_DBF_LENGTH);
debug_register_view(adapter->req_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->req_dbf, ZFCP_REQ_DBF_LEVEL);
debug_text_event(adapter->req_dbf, 1, "zzz");
/* debug feature area which records SCSI command failures (hostbyte) */
rwlock_init(&adapter->cmd_dbf_lock);
sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->cmd_dbf = debug_register(dbf_name,
ZFCP_CMD_DBF_INDEX,
ZFCP_CMD_DBF_AREAS,
ZFCP_CMD_DBF_LENGTH);
debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->cmd_dbf, ZFCP_CMD_DBF_LEVEL);
/* debug feature area which records SCSI command aborts */
sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->abort_dbf = debug_register(dbf_name,
ZFCP_ABORT_DBF_INDEX,
ZFCP_ABORT_DBF_AREAS,
ZFCP_ABORT_DBF_LENGTH);
debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL);
/* debug feature area which records SCSI command aborts */
sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->in_els_dbf = debug_register(dbf_name,
ZFCP_IN_ELS_DBF_INDEX,
ZFCP_IN_ELS_DBF_AREAS,
ZFCP_IN_ELS_DBF_LENGTH);
debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL);
/* debug feature area which records erp events */
sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->erp_dbf = debug_register(dbf_name,
ZFCP_ERP_DBF_INDEX,
ZFCP_ERP_DBF_AREAS,
ZFCP_ERP_DBF_LENGTH);
debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
if (adapter->req_dbf && adapter->cmd_dbf && adapter->abort_dbf &&
adapter->in_els_dbf && adapter->erp_dbf)
return 0;
zfcp_adapter_debug_unregister(adapter);
return -ENOMEM;
}
/**
* zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
* @adapter: pointer to adapter for which debug features should be unregistered
*/
void
zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
{
debug_unregister(adapter->erp_dbf);
debug_unregister(adapter->req_dbf);
debug_unregister(adapter->cmd_dbf);
debug_unregister(adapter->abort_dbf);
debug_unregister(adapter->in_els_dbf);
}
/* /*
* Enqueues an adapter at the end of the adapter list in the driver data. * Enqueues an adapter at the end of the adapter list in the driver data.
* All adapter internal structures are set up. * All adapter internal structures are set up.
...@@ -1213,7 +1220,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -1213,7 +1220,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
{ {
int retval = 0; int retval = 0;
struct zfcp_adapter *adapter; struct zfcp_adapter *adapter;
char dbf_name[20];
/* /*
* Note: It is safe to release the list_lock, as any list changes * Note: It is safe to release the list_lock, as any list changes
...@@ -1246,10 +1252,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -1246,10 +1252,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
if (retval) if (retval)
goto failed_low_mem_buffers; goto failed_low_mem_buffers;
/* set magics */
adapter->common_magic = ZFCP_MAGIC;
adapter->specific_magic = ZFCP_MAGIC_ADAPTER;
/* initialise reference count stuff */ /* initialise reference count stuff */
atomic_set(&adapter->refcount, 0); atomic_set(&adapter->refcount, 0);
init_waitqueue_head(&adapter->remove_wq); init_waitqueue_head(&adapter->remove_wq);
...@@ -1292,103 +1294,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -1292,103 +1294,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
if (zfcp_sysfs_adapter_create_files(&ccw_device->dev)) if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
goto sysfs_failed; goto sysfs_failed;
#ifdef ZFCP_DEBUG_REQUESTS
/* debug feature area which records fsf request sequence numbers */
sprintf(dbf_name, ZFCP_REQ_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->req_dbf = debug_register(dbf_name,
ZFCP_REQ_DBF_INDEX,
ZFCP_REQ_DBF_AREAS,
ZFCP_REQ_DBF_LENGTH);
if (!adapter->req_dbf) {
ZFCP_LOG_INFO
("error: Out of resources. Request debug feature for "
"adapter %s could not be generated.\n",
zfcp_get_busid_by_adapter(adapter));
retval = -ENOMEM;
goto failed_req_dbf;
}
debug_register_view(adapter->req_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->req_dbf, ZFCP_REQ_DBF_LEVEL);
debug_text_event(adapter->req_dbf, 1, "zzz");
#endif /* ZFCP_DEBUG_REQUESTS */
#ifdef ZFCP_DEBUG_COMMANDS
/* debug feature area which records SCSI command failures (hostbyte) */
rwlock_init(&adapter->cmd_dbf_lock);
sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->cmd_dbf = debug_register(dbf_name,
ZFCP_CMD_DBF_INDEX,
ZFCP_CMD_DBF_AREAS,
ZFCP_CMD_DBF_LENGTH);
if (!adapter->cmd_dbf) {
ZFCP_LOG_INFO
("error: Out of resources. Command debug feature for "
"adapter %s could not be generated.\n",
zfcp_get_busid_by_adapter(adapter));
retval = -ENOMEM;
goto failed_cmd_dbf;
}
debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->cmd_dbf, ZFCP_CMD_DBF_LEVEL);
#endif /* ZFCP_DEBUG_COMMANDS */
#ifdef ZFCP_DEBUG_ABORTS
/* debug feature area which records SCSI command aborts */
sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->abort_dbf = debug_register(dbf_name,
ZFCP_ABORT_DBF_INDEX,
ZFCP_ABORT_DBF_AREAS,
ZFCP_ABORT_DBF_LENGTH);
if (!adapter->abort_dbf) {
ZFCP_LOG_INFO
("error: Out of resources. Abort debug feature for "
"adapter %s could not be generated.\n",
zfcp_get_busid_by_adapter(adapter));
retval = -ENOMEM;
goto failed_abort_dbf;
}
debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL);
#endif /* ZFCP_DEBUG_ABORTS */
#ifdef ZFCP_DEBUG_INCOMING_ELS
/* debug feature area which records SCSI command aborts */
sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->in_els_dbf = debug_register(dbf_name,
ZFCP_IN_ELS_DBF_INDEX,
ZFCP_IN_ELS_DBF_AREAS,
ZFCP_IN_ELS_DBF_LENGTH);
if (!adapter->in_els_dbf) {
ZFCP_LOG_INFO("error: Out of resources. ELS debug feature for "
"adapter %s could not be generated.\n",
zfcp_get_busid_by_adapter(adapter));
retval = -ENOMEM;
goto failed_in_els_dbf;
}
debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL);
#endif /* ZFCP_DEBUG_INCOMING_ELS */
sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s",
zfcp_get_busid_by_adapter(adapter));
adapter->erp_dbf = debug_register(dbf_name,
ZFCP_ERP_DBF_INDEX,
ZFCP_ERP_DBF_AREAS,
ZFCP_ERP_DBF_LENGTH);
if (!adapter->erp_dbf) {
ZFCP_LOG_INFO("error: Out of resources. ERP debug feature for "
"adapter %s could not be generated.\n",
zfcp_get_busid_by_adapter(adapter));
retval = -ENOMEM;
goto failed_erp_dbf;
}
debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
/* put allocated adapter at list tail */ /* put allocated adapter at list tail */
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
...@@ -1399,27 +1304,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -1399,27 +1304,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
goto out; goto out;
failed_erp_dbf:
#ifdef ZFCP_DEBUG_INCOMING_ELS
debug_unregister(adapter->in_els_dbf);
failed_in_els_dbf:
#endif
#ifdef ZFCP_DEBUG_ABORTS
debug_unregister(adapter->abort_dbf);
failed_abort_dbf:
#endif
#ifdef ZFCP_DEBUG_COMMANDS
debug_unregister(adapter->cmd_dbf);
failed_cmd_dbf:
#endif
#ifdef ZFCP_DEBUG_REQUESTS
debug_unregister(adapter->req_dbf);
failed_req_dbf:
#endif
zfcp_sysfs_adapter_remove_files(&ccw_device->dev);
sysfs_failed: sysfs_failed:
dev_set_drvdata(&ccw_device->dev, NULL); dev_set_drvdata(&ccw_device->dev, NULL);
failed_low_mem_buffers: failed_low_mem_buffers:
...@@ -1488,23 +1372,6 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) ...@@ -1488,23 +1372,6 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
"mechanism for adapter %s\n", "mechanism for adapter %s\n",
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
debug_unregister(adapter->erp_dbf);
#ifdef ZFCP_DEBUG_REQUESTS
debug_unregister(adapter->req_dbf);
#endif
#ifdef ZFCP_DEBUG_COMMANDS
debug_unregister(adapter->cmd_dbf);
#endif
#ifdef ZFCP_DEBUG_ABORTS
debug_unregister(adapter->abort_dbf);
#endif
#ifdef ZFCP_DEBUG_INCOMING_ELS
debug_unregister(adapter->in_els_dbf);
#endif
zfcp_free_low_mem_buffers(adapter); zfcp_free_low_mem_buffers(adapter);
/* free memory of adapter data structure and queues */ /* free memory of adapter data structure and queues */
zfcp_qdio_free_queues(adapter); zfcp_qdio_free_queues(adapter);
...@@ -1515,25 +1382,20 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) ...@@ -1515,25 +1382,20 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
} }
/* /*
* Enqueues a remote port at the end of the port list. * Enqueues a remote port to the port list. All port internal structures
* All port internal structures are set-up and the proc-fs entry is also * are set up and the sysfs entry is also generated.
* allocated. Some SCSI-stack structures are modified for the port.
* *
* returns: 0 if a new port was successfully enqueued * returns: pointer to port or NULL
* ZFCP_KNOWN if a port with the requested wwpn already exists
* -ENOMEM if allocation failed
* -EINVAL if at least one of the specified parameters was wrong
* locks: config_sema must be held to serialise changes to the port list * locks: config_sema must be held to serialise changes to the port list
* within this function (must not be held on entry)
*/ */
struct zfcp_port * struct zfcp_port *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
{ {
struct zfcp_port *port; struct zfcp_port *port, *tmp_port;
int check_scsi_id;
int check_wwpn; int check_wwpn;
scsi_id_t scsi_id;
int found;
check_scsi_id = !(status & ZFCP_STATUS_PORT_NO_SCSI_ID);
check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN); check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
/* /*
...@@ -1561,17 +1423,11 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) ...@@ -1561,17 +1423,11 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
port->adapter = adapter; port->adapter = adapter;
if (check_scsi_id)
port->scsi_id = adapter->max_scsi_id + 1;
if (check_wwpn) if (check_wwpn)
port->wwpn = wwpn; port->wwpn = wwpn;
atomic_set_mask(status, &port->status); atomic_set_mask(status, &port->status);
port->common_magic = ZFCP_MAGIC;
port->specific_magic = ZFCP_MAGIC_PORT;
/* setup for sysfs registration */ /* setup for sysfs registration */
if (status & ZFCP_STATUS_PORT_NAMESERVER) if (status & ZFCP_STATUS_PORT_NAMESERVER)
snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "nameserver"); snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "nameserver");
...@@ -1591,41 +1447,32 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) ...@@ -1591,41 +1447,32 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
} }
if (zfcp_sysfs_port_create_files(&port->sysfs_device, status)) { if (zfcp_sysfs_port_create_files(&port->sysfs_device, status)) {
/*
* failed to create all sysfs attributes, therefore the port
* must be put on the port_remove listhead of the adapter
* where the release function expects it.
*/
write_lock_irq(&zfcp_data.config_lock);
list_add_tail(&port->list, &adapter->port_remove_lh);
write_unlock_irq(&zfcp_data.config_lock);
device_unregister(&port->sysfs_device); device_unregister(&port->sysfs_device);
return NULL; return NULL;
} }
if (check_scsi_id) {
/*
* update max. SCSI ID of remote ports attached to
* "parent" adapter if necessary
* (do not care about the adapters own SCSI ID)
*/
adapter->max_scsi_id++;
/*
* update max. SCSI ID of remote ports attached to
* "parent" host (SCSI stack) if necessary
*/
if (adapter->scsi_host &&
(adapter->scsi_host->max_id < adapter->max_scsi_id + 1))
adapter->scsi_host->max_id = adapter->max_scsi_id + 1;
}
zfcp_port_get(port); zfcp_port_get(port);
scsi_id = 1;
found = 0;
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
&tmp_port->status))
continue;
if (tmp_port->scsi_id != scsi_id) {
found = 1;
break;
}
scsi_id++;
}
port->scsi_id = scsi_id;
if (found)
list_add_tail(&port->list, &tmp_port->list);
else
list_add_tail(&port->list, &adapter->port_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
list_add_tail(&port->list, &adapter->port_list_head);
write_unlock_irq(&zfcp_data.config_lock); write_unlock_irq(&zfcp_data.config_lock);
adapter->ports++; adapter->ports++;
...@@ -1634,26 +1481,18 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) ...@@ -1634,26 +1481,18 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
return port; return port;
} }
/*
* returns: 0 - struct zfcp_port data structure successfully removed
* !0 - struct zfcp_port data structure could not be removed
* (e.g. still used)
* locks : port list write lock is assumed to be held by caller
*/
void void
zfcp_port_dequeue(struct zfcp_port *port) zfcp_port_dequeue(struct zfcp_port *port)
{ {
/* remove specified port from list */ zfcp_port_wait(port);
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
list_del(&port->list); list_del(&port->list);
write_unlock_irq(&zfcp_data.config_lock); write_unlock_irq(&zfcp_data.config_lock);
port->adapter->ports--; port->adapter->ports--;
zfcp_adapter_put(port->adapter); zfcp_adapter_put(port->adapter);
zfcp_sysfs_port_remove_files(&port->sysfs_device,
kfree(port); atomic_read(&port->status));
device_unregister(&port->sysfs_device);
return;
} }
/* Enqueues a nameserver port */ /* Enqueues a nameserver port */
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#define ZFCP_CCW_C_REVISION "$Revision: 1.48 $" #define ZFCP_CCW_C_REVISION "$Revision: 1.52 $"
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -55,6 +55,7 @@ static struct ccw_device_id zfcp_ccw_device_id[] = { ...@@ -55,6 +55,7 @@ static struct ccw_device_id zfcp_ccw_device_id[] = {
}; };
static struct ccw_driver zfcp_ccw_driver = { static struct ccw_driver zfcp_ccw_driver = {
.owner = THIS_MODULE,
.name = ZFCP_NAME, .name = ZFCP_NAME,
.ids = zfcp_ccw_device_id, .ids = zfcp_ccw_device_id,
.probe = zfcp_ccw_probe, .probe = zfcp_ccw_probe,
...@@ -130,14 +131,9 @@ zfcp_ccw_remove(struct ccw_device *ccw_device) ...@@ -130,14 +131,9 @@ zfcp_ccw_remove(struct ccw_device *ccw_device)
list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) { list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) {
list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) { list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) {
zfcp_unit_wait(unit); zfcp_unit_dequeue(unit);
zfcp_sysfs_unit_remove_files(&unit->sysfs_device);
device_unregister(&unit->sysfs_device);
} }
zfcp_port_wait(port); zfcp_port_dequeue(port);
zfcp_sysfs_port_remove_files(&port->sysfs_device,
atomic_read(&port->status));
device_unregister(&port->sysfs_device);
} }
zfcp_adapter_wait(adapter); zfcp_adapter_wait(adapter);
zfcp_adapter_dequeue(adapter); zfcp_adapter_dequeue(adapter);
...@@ -163,13 +159,16 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) ...@@ -163,13 +159,16 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
down(&zfcp_data.config_sema); down(&zfcp_data.config_sema);
adapter = dev_get_drvdata(&ccw_device->dev); adapter = dev_get_drvdata(&ccw_device->dev);
retval = zfcp_adapter_debug_register(adapter);
if (retval)
goto out;
retval = zfcp_erp_thread_setup(adapter); retval = zfcp_erp_thread_setup(adapter);
if (retval) { if (retval) {
ZFCP_LOG_INFO("error: out of resources. " ZFCP_LOG_INFO("error: out of resources. "
"error recovery thread for adapter %s " "error recovery thread for adapter %s "
"could not be started\n", "could not be started\n",
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
goto out; goto out_erp_thread;
} }
retval = zfcp_adapter_scsi_register(adapter); retval = zfcp_adapter_scsi_register(adapter);
...@@ -183,6 +182,8 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) ...@@ -183,6 +182,8 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
out_scsi_register: out_scsi_register:
zfcp_erp_thread_kill(adapter); zfcp_erp_thread_kill(adapter);
out_erp_thread:
zfcp_adapter_debug_unregister(adapter);
out: out:
up(&zfcp_data.config_sema); up(&zfcp_data.config_sema);
return retval; return retval;
...@@ -208,6 +209,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device) ...@@ -208,6 +209,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
zfcp_erp_wait(adapter); zfcp_erp_wait(adapter);
zfcp_adapter_scsi_unregister(adapter); zfcp_adapter_scsi_unregister(adapter);
zfcp_erp_thread_kill(adapter); zfcp_erp_thread_kill(adapter);
zfcp_adapter_debug_unregister(adapter);
up(&zfcp_data.config_sema); up(&zfcp_data.config_sema);
return 0; return 0;
} }
......
...@@ -33,25 +33,29 @@ ...@@ -33,25 +33,29 @@
#define ZFCP_DEF_H #define ZFCP_DEF_H
/* this drivers version (do not edit !!! generated and updated by cvs) */ /* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_DEF_REVISION "$Revision: 1.62 $" #define ZFCP_DEF_REVISION "$Revision: 1.71 $"
/*************************** INCLUDES *****************************************/ /*************************** INCLUDES *****************************************/
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/miscdevice.h>
#include <linux/major.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include "../../scsi/scsi.h"
#include "../../fc4/fc.h" #include "../../fc4/fc.h"
#include "zfcp_fsf.h" /* FSF SW Interface */ #include "zfcp_fsf.h"
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/qdio.h> #include <asm/qdio.h>
#include <asm/debug.h> #include <asm/debug.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/mempool.h> #include <linux/mempool.h>
#include <linux/syscalls.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#ifdef CONFIG_S390_SUPPORT #ifdef CONFIG_S390_SUPPORT
#include <linux/ioctl32.h> #include <linux/ioctl32.h>
...@@ -60,10 +64,6 @@ ...@@ -60,10 +64,6 @@
/************************ DEBUG FLAGS *****************************************/ /************************ DEBUG FLAGS *****************************************/
#define ZFCP_PRINT_FLAGS #define ZFCP_PRINT_FLAGS
#define ZFCP_DEBUG_REQUESTS /* fsf_req tracing */
#define ZFCP_DEBUG_COMMANDS /* host_byte tracing */
#define ZFCP_DEBUG_ABORTS /* scsi_cmnd abort tracing */
#define ZFCP_DEBUG_INCOMING_ELS /* incoming ELS tracing */
#define ZFCP_STAT_REQSIZES #define ZFCP_STAT_REQSIZES
#define ZFCP_STAT_QUEUES #define ZFCP_STAT_QUEUES
...@@ -723,11 +723,6 @@ struct zfcp_cfdc_sense_data { ...@@ -723,11 +723,6 @@ struct zfcp_cfdc_sense_data {
#define ZFCP_CFDC_MAX_CONTROL_FILE_SIZE 127 * 1024 #define ZFCP_CFDC_MAX_CONTROL_FILE_SIZE 127 * 1024
static const char zfcp_act_subtable_type[5][8] = {
{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
};
/************************* STRUCTURE DEFINITIONS *****************************/ /************************* STRUCTURE DEFINITIONS *****************************/
struct zfcp_fsf_req; struct zfcp_fsf_req;
...@@ -937,8 +932,6 @@ struct zfcp_erp_action { ...@@ -937,8 +932,6 @@ struct zfcp_erp_action {
struct zfcp_adapter { struct zfcp_adapter {
u32 common_magic; /* driver common magic */
u32 specific_magic; /* struct specific magic */
struct list_head list; /* list of adapters */ struct list_head list; /* list of adapters */
atomic_t refcount; /* reference count */ atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for wait_queue_head_t remove_wq; /* can be used to wait for
...@@ -956,14 +949,12 @@ struct zfcp_adapter { ...@@ -956,14 +949,12 @@ struct zfcp_adapter {
u32 hardware_version; /* of FCP channel */ u32 hardware_version; /* of FCP channel */
u8 serial_number[32]; /* of hardware */ u8 serial_number[32]; /* of hardware */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
unsigned short scsi_host_no; /* Assigned host number */
unsigned char name[9]; unsigned char name[9];
struct list_head port_list_head; /* remote port list */ struct list_head port_list_head; /* remote port list */
struct list_head port_remove_lh; /* head of ports to be struct list_head port_remove_lh; /* head of ports to be
removed */ removed */
u32 ports; /* number of remote ports */ u32 ports; /* number of remote ports */
scsi_id_t max_scsi_id; /* largest SCSI ID */
scsi_lun_t max_scsi_lun; /* largest SCSI LUN */
struct timer_list scsi_er_timer; /* SCSI err recovery watch */ struct timer_list scsi_er_timer; /* SCSI err recovery watch */
struct list_head fsf_req_list_head; /* head of FSF req list */ struct list_head fsf_req_list_head; /* head of FSF req list */
rwlock_t fsf_req_list_lock; /* lock for ops on list of rwlock_t fsf_req_list_lock; /* lock for ops on list of
...@@ -1003,9 +994,13 @@ struct zfcp_adapter { ...@@ -1003,9 +994,13 @@ struct zfcp_adapter {
struct qdio_initialize qdio_init_data; /* for qdio_establish */ struct qdio_initialize qdio_init_data; /* for qdio_establish */
}; };
/*
* the struct device sysfs_device must be at the beginning of this structure.
* pointer to struct device is used to free port structure in release function
* of the device. don't change!
*/
struct zfcp_port { struct zfcp_port {
u32 common_magic; /* driver wide common magic */ struct device sysfs_device; /* sysfs device */
u32 specific_magic; /* structure specific magic */
struct list_head list; /* list of remote ports */ struct list_head list; /* list of remote ports */
atomic_t refcount; /* reference count */ atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for wait_queue_head_t remove_wq; /* can be used to wait for
...@@ -1020,37 +1015,36 @@ struct zfcp_port { ...@@ -1020,37 +1015,36 @@ struct zfcp_port {
wwn_t wwnn; /* WWNN if known */ wwn_t wwnn; /* WWNN if known */
wwn_t wwpn; /* WWPN */ wwn_t wwpn; /* WWPN */
fc_id_t d_id; /* D_ID */ fc_id_t d_id; /* D_ID */
scsi_lun_t max_scsi_lun; /* largest SCSI LUN */
u32 handle; /* handle assigned by FSF */ u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */ struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter; atomic_t erp_counter;
struct device sysfs_device; /* sysfs device */
}; };
/* the struct device sysfs_device must be at the beginning of this structure.
* pointer to struct device is used to free unit structure in release function
* of the device. don't change!
*/
struct zfcp_unit { struct zfcp_unit {
u32 common_magic; /* driver wide common magic */ struct device sysfs_device; /* sysfs device */
u32 specific_magic; /* structure specific magic */
struct list_head list; /* list of logical units */ struct list_head list; /* list of logical units */
atomic_t refcount; /* reference count */ atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for wait_queue_head_t remove_wq; /* can be used to wait for
refcount drop to zero */ refcount drop to zero */
struct zfcp_port *port; /* remote port of unit */ struct zfcp_port *port; /* remote port of unit */
atomic_t status; /* status of this logical unit */ atomic_t status; /* status of this logical unit */
u32 lun_access; /* access flags for this unit */
scsi_lun_t scsi_lun; /* own SCSI LUN */ scsi_lun_t scsi_lun; /* own SCSI LUN */
fcp_lun_t fcp_lun; /* own FCP_LUN */ fcp_lun_t fcp_lun; /* own FCP_LUN */
u32 handle; /* handle assigned by FSF */ u32 handle; /* handle assigned by FSF */
struct scsi_device *device; /* scsi device struct pointer */ struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */ struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter; atomic_t erp_counter;
struct device sysfs_device; /* sysfs device */
atomic_t scsi_add_work; /* used to synchronize */ atomic_t scsi_add_work; /* used to synchronize */
wait_queue_head_t scsi_add_wq; /* wait for scsi_add_device */ wait_queue_head_t scsi_add_wq; /* wait for scsi_add_device */
}; };
/* FSF request */ /* FSF request */
struct zfcp_fsf_req { struct zfcp_fsf_req {
u32 common_magic; /* driver wide common magic */
u32 specific_magic; /* structure specific magic */
struct list_head list; /* list of FSF requests */ struct list_head list; /* list of FSF requests */
struct zfcp_adapter *adapter; /* adapter request belongs to */ struct zfcp_adapter *adapter; /* adapter request belongs to */
u8 sbal_number; /* nr of SBALs free for use */ u8 sbal_number; /* nr of SBALs free for use */
...@@ -1158,13 +1152,6 @@ struct zfcp_fsf_req_pool_element { ...@@ -1158,13 +1152,6 @@ struct zfcp_fsf_req_pool_element {
#define ZFCP_INTERRUPTIBLE 1 #define ZFCP_INTERRUPTIBLE 1
#define ZFCP_UNINTERRUPTIBLE 0 #define ZFCP_UNINTERRUPTIBLE 0
/* some magics which may be used to authenticate data structures */
#define ZFCP_MAGIC 0xFCFCFCFC
#define ZFCP_MAGIC_ADAPTER 0xAAAAAAAA
#define ZFCP_MAGIC_PORT 0xBBBBBBBB
#define ZFCP_MAGIC_UNIT 0xCCCCCCCC
#define ZFCP_MAGIC_FSFREQ 0xEEEEEEEE
#ifndef atomic_test_mask #ifndef atomic_test_mask
#define atomic_test_mask(mask, target) \ #define atomic_test_mask(mask, target) \
((atomic_read(target) & mask) == mask) ((atomic_read(target) & mask) == mask)
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
/* this drivers version (do not edit !!! generated and updated by cvs) */ /* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_ERP_REVISION "$Revision: 1.44 $" #define ZFCP_ERP_REVISION "$Revision: 1.49 $"
#include "zfcp_ext.h" #include "zfcp_ext.h"
...@@ -1202,7 +1202,7 @@ zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, ...@@ -1202,7 +1202,7 @@ zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
* returns: 0 - there was an action to handle * returns: 0 - there was an action to handle
* !0 - otherwise * !0 - otherwise
*/ */
static int int
zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, zfcp_erp_async_handler(struct zfcp_erp_action *erp_action,
unsigned long set_mask) unsigned long set_mask)
{ {
...@@ -1217,28 +1217,6 @@ zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, ...@@ -1217,28 +1217,6 @@ zfcp_erp_async_handler(struct zfcp_erp_action *erp_action,
return retval; return retval;
} }
/*
* purpose: is called for finished FSF requests related to erp,
* moves concerned erp action to 'ready' queue and
* signals erp thread to process it,
* besides it cancels a timeout
*/
void
zfcp_erp_fsf_req_handler(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_erp_action *erp_action = fsf_req->erp_action;
struct zfcp_adapter *adapter = fsf_req->adapter;
debug_text_event(adapter->erp_dbf, 3, "a_frh");
debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
if (erp_action) {
debug_event(adapter->erp_dbf, 3, &erp_action->action,
sizeof (int));
zfcp_erp_async_handler(erp_action, 0);
}
}
/* /*
* purpose: is called for erp_action which was slept waiting for * purpose: is called for erp_action which was slept waiting for
* memory becoming avaliable, * memory becoming avaliable,
...@@ -1892,7 +1870,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit) ...@@ -1892,7 +1870,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit)
unit->fcp_lun, unit->fcp_lun,
unit->port->wwpn, unit->port->wwpn,
zfcp_get_busid_by_unit(unit)); zfcp_get_busid_by_unit(unit));
atomic_set(&p->unit->scsi_add_work, 0); atomic_set(&unit->scsi_add_work, 0);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2500,10 +2478,8 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) ...@@ -2500,10 +2478,8 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
("bug: Could not clean QDIO (data transfer mechanism) " ("bug: Could not clean QDIO (data transfer mechanism) "
"queues. (debug info %i).\n", retval_cleanup); "queues. (debug info %i).\n", retval_cleanup);
} }
#ifdef ZFCP_DEBUG_REQUESTS
else else
debug_text_event(adapter->req_dbf, 1, "q_clean"); debug_text_event(adapter->req_dbf, 1, "q_clean");
#endif /* ZFCP_DEBUG_REQUESTS */
failed_qdio_establish: failed_qdio_establish:
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
...@@ -2577,9 +2553,7 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) ...@@ -2577,9 +2553,7 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
} else { } else {
ZFCP_LOG_DEBUG("queues cleaned up\n"); ZFCP_LOG_DEBUG("queues cleaned up\n");
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 1, "q_clean"); debug_text_event(adapter->req_dbf, 1, "q_clean");
#endif /* ZFCP_DEBUG_REQUESTS */
} }
/* /*
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#ifndef ZFCP_EXT_H #ifndef ZFCP_EXT_H
#define ZFCP_EXT_H #define ZFCP_EXT_H
/* this drivers version (do not edit !!! generated and updated by cvs) */ /* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_EXT_REVISION "$Revision: 1.45 $" #define ZFCP_EXT_REVISION "$Revision: 1.49 $"
#include "zfcp_def.h" #include "zfcp_def.h"
...@@ -55,7 +55,9 @@ extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, ...@@ -55,7 +55,9 @@ extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *,
extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *,
wwn_t wwpn); wwn_t wwpn);
extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
extern int zfcp_adapter_debug_register(struct zfcp_adapter *);
extern void zfcp_adapter_dequeue(struct zfcp_adapter *); extern void zfcp_adapter_dequeue(struct zfcp_adapter *);
extern void zfcp_adapter_debug_unregister(struct zfcp_adapter *);
extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32); extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32);
extern void zfcp_port_dequeue(struct zfcp_port *); extern void zfcp_port_dequeue(struct zfcp_port *);
extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t); extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
...@@ -158,7 +160,7 @@ extern void zfcp_erp_scsi_low_mem_buffer_timeout_handler(unsigned long); ...@@ -158,7 +160,7 @@ extern void zfcp_erp_scsi_low_mem_buffer_timeout_handler(unsigned long);
extern int zfcp_erp_thread_setup(struct zfcp_adapter *); extern int zfcp_erp_thread_setup(struct zfcp_adapter *);
extern int zfcp_erp_thread_kill(struct zfcp_adapter *); extern int zfcp_erp_thread_kill(struct zfcp_adapter *);
extern int zfcp_erp_wait(struct zfcp_adapter *); extern int zfcp_erp_wait(struct zfcp_adapter *);
extern void zfcp_erp_fsf_req_handler(struct zfcp_fsf_req *); extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
extern int zfcp_test_link(struct zfcp_port *); extern int zfcp_test_link(struct zfcp_port *);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
*/ */
/* this drivers version (do not edit !!! generated and updated by cvs) */ /* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_FSF_C_REVISION "$Revision: 1.29 $" #define ZFCP_FSF_C_REVISION "$Revision: 1.43 $"
#include "zfcp_ext.h" #include "zfcp_ext.h"
...@@ -78,6 +78,11 @@ static u32 fsf_qtcb_type[] = { ...@@ -78,6 +78,11 @@ static u32 fsf_qtcb_type[] = {
[FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND
}; };
static const char zfcp_act_subtable_type[5][8] = {
{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
};
/****************************************************************/ /****************************************************************/
/*************** FSF related Functions *************************/ /*************** FSF related Functions *************************/
/****************************************************************/ /****************************************************************/
...@@ -320,7 +325,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) ...@@ -320,7 +325,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
sizeof(struct fsf_qtcb)); sizeof(struct fsf_qtcb));
goto forget_log; goto forget_log;
} }
if ((fsf_req->qtcb->header.log_start + if ((size_t) (fsf_req->qtcb->header.log_start +
fsf_req->qtcb->header.log_length) fsf_req->qtcb->header.log_length)
> sizeof(struct fsf_qtcb)) { > sizeof(struct fsf_qtcb)) {
ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
...@@ -388,7 +393,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) ...@@ -388,7 +393,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
zfcp_get_busid_by_adapter(adapter), zfcp_get_busid_by_adapter(adapter),
fsf_req->qtcb->prefix.prot_status_qual. fsf_req->qtcb->prefix.prot_status_qual.
sequence_error.exp_req_seq_no); sequence_error.exp_req_seq_no);
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 1, "exp_seq!"); debug_text_event(adapter->req_dbf, 1, "exp_seq!");
debug_event(adapter->req_dbf, 1, debug_event(adapter->req_dbf, 1,
&fsf_req->qtcb->prefix.prot_status_qual. &fsf_req->qtcb->prefix.prot_status_qual.
...@@ -396,7 +400,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) ...@@ -396,7 +400,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
debug_text_event(adapter->req_dbf, 1, "qtcb_seq!"); debug_text_event(adapter->req_dbf, 1, "qtcb_seq!");
debug_exception(adapter->req_dbf, 1, debug_exception(adapter->req_dbf, 1,
&fsf_req->qtcb->prefix.req_seq_no, 4); &fsf_req->qtcb->prefix.req_seq_no, 4);
#endif /* ZFCP_DEBUG_REQUESTS */
debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err"); debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err");
/* restart operation on this adapter */ /* restart operation on this adapter */
zfcp_erp_adapter_reopen(adapter, 0); zfcp_erp_adapter_reopen(adapter, 0);
...@@ -771,6 +774,8 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) ...@@ -771,6 +774,8 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
static int static int
zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
{ {
struct zfcp_erp_action *erp_action = fsf_req->erp_action;
struct zfcp_adapter *adapter = fsf_req->adapter;
int retval = 0; int retval = 0;
if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
...@@ -861,7 +866,13 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) ...@@ -861,7 +866,13 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
fsf_req->qtcb->header.fsf_command); fsf_req->qtcb->header.fsf_command);
} }
zfcp_erp_fsf_req_handler(fsf_req); if (!erp_action)
return retval;
debug_text_event(adapter->erp_dbf, 3, "a_frh");
debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
zfcp_erp_async_handler(erp_action, 0);
return retval; return retval;
} }
...@@ -924,9 +935,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) ...@@ -924,9 +935,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
ZFCP_LOG_TRACE("Status Read request initiated " ZFCP_LOG_TRACE("Status Read request initiated "
"(adapter busid=%s)\n", "(adapter busid=%s)\n",
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 1, "unso"); debug_text_event(adapter->req_dbf, 1, "unso");
#endif
goto out; goto out;
failed_req_send: failed_req_send:
...@@ -1044,8 +1053,12 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) ...@@ -1044,8 +1053,12 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
case FSF_STATUS_READ_LINK_DOWN: case FSF_STATUS_READ_LINK_DOWN:
ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_DOWN\n"); ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_DOWN\n");
debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:");
/* Unneccessary, ignoring.... */ ZFCP_LOG_INFO("Local link to adapter %s is down\n",
zfcp_get_busid_by_adapter(adapter));
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&adapter->status);
zfcp_erp_adapter_failed(adapter);
break; break;
case FSF_STATUS_READ_LINK_UP: case FSF_STATUS_READ_LINK_UP:
...@@ -1065,27 +1078,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) ...@@ -1065,27 +1078,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break; break;
case FSF_STATUS_READ_NOTIFICATION_LOST:
ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_NOTIFICATION_LOST\n");
debug_text_event(adapter->erp_dbf, 2, "unsol_not_lost:");
switch (status_buffer->status_subtype) {
case FSF_STATUS_READ_SUB_LOST_CFDC_UPDATED:
ZFCP_LOG_NORMAL(
"The unsolicited status information about "
"CFDC update on the adapter %s is lost "
"due to the lack of internal resources\n",
zfcp_get_busid_by_adapter(adapter));
break;
case FSF_STATUS_READ_SUB_LOST_CFDC_HARDENED:
ZFCP_LOG_NORMAL(
"The unsolicited status information about "
"CFDC harden on the adapter %s is lost "
"due to the lack of internal resources\n",
zfcp_get_busid_by_adapter(adapter));
break;
}
break;
case FSF_STATUS_READ_CFDC_UPDATED: case FSF_STATUS_READ_CFDC_UPDATED:
ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_UPDATED\n"); ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_UPDATED\n");
debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:"); debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
...@@ -1344,16 +1336,10 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) ...@@ -1344,16 +1336,10 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
case FSF_FCP_COMMAND_DOES_NOT_EXIST: case FSF_FCP_COMMAND_DOES_NOT_EXIST:
ZFCP_LOG_FLAGS(2, "FSF_FCP_COMMAND_DOES_NOT_EXIST\n"); ZFCP_LOG_FLAGS(2, "FSF_FCP_COMMAND_DOES_NOT_EXIST\n");
retval = 0; retval = 0;
#ifdef ZFCP_DEBUG_REQUESTS
/*
* debug feature area which records
* fsf request sequence numbers
*/
debug_text_event(new_fsf_req->adapter->req_dbf, 3, "no_exist"); debug_text_event(new_fsf_req->adapter->req_dbf, 3, "no_exist");
debug_event(new_fsf_req->adapter->req_dbf, 3, debug_event(new_fsf_req->adapter->req_dbf, 3,
&new_fsf_req->qtcb->bottom.support.req_handle, &new_fsf_req->qtcb->bottom.support.req_handle,
sizeof (unsigned long)); sizeof (unsigned long));
#endif /* ZFCP_DEBUG_REQUESTS */
debug_text_event(new_fsf_req->adapter->erp_dbf, 3, debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_no_exist"); "fsf_s_no_exist");
new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
...@@ -1670,20 +1656,19 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) ...@@ -1670,20 +1656,19 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
"to a port with WWPN 0x%Lx connected " "to a port with WWPN 0x%Lx connected "
"to the adapter %s\n", port->wwpn, "to the adapter %s\n", port->wwpn,
zfcp_get_busid_by_port(port)); zfcp_get_busid_by_port(port));
counter = 0; for (counter = 0; counter < 2; counter++) {
do { subtable = header->fsf_status_qual.halfword[counter * 2];
subtable = header->fsf_status_qual.halfword[counter++]; rule = header->fsf_status_qual.halfword[counter * 2 + 1];
rule = header->fsf_status_qual.halfword[counter++];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_INFO("Access denied (%s rule %d)\n",
zfcp_act_subtable_type[subtable], rule); zfcp_act_subtable_type[subtable], rule);
break; break;
} }
} while (counter < 4); }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -2036,20 +2021,19 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2036,20 +2021,19 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_NORMAL("Access denied, cannot send ELS " ZFCP_LOG_NORMAL("Access denied, cannot send ELS "
"(adapter: %s, wwpn=0x%016Lx)\n", "(adapter: %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port), port->wwpn); zfcp_get_busid_by_port(port), port->wwpn);
counter = 0; for (counter = 0; counter < 2; counter++) {
do { subtable = header->fsf_status_qual.halfword[counter * 2];
subtable = header->fsf_status_qual.halfword[counter++]; rule = header->fsf_status_qual.halfword[counter * 2 + 1];
rule = header->fsf_status_qual.halfword[counter++];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_INFO("Access denied (%s rule %d)\n",
zfcp_act_subtable_type[subtable], rule); zfcp_act_subtable_type[subtable], rule);
break; break;
} }
} while (counter < 4); }
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -2114,7 +2098,8 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) ...@@ -2114,7 +2098,8 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req->erp_action = erp_action; erp_action->fsf_req->erp_action = erp_action;
erp_action->fsf_req->qtcb->bottom.config.feature_selection = erp_action->fsf_req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_CFDC; FSF_FEATURE_CFDC |
FSF_FEATURE_LOST_SAN_NOTIFICATION;
/* start QDIO request for this FSF request */ /* start QDIO request for this FSF request */
retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
...@@ -2138,59 +2123,51 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) ...@@ -2138,59 +2123,51 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
return retval; return retval;
} }
/* /**
* function: zfcp_fsf_exchange_config_data_handler * zfcp_fsf_exchange_config_evaluate
* * @fsf_req: fsf_req which belongs to xchg config data request
* purpose: is called for finished Exchange Configuration Data command * @xchg_ok: specifies if xchg config data was incomplete or complete (0/1)
* *
* returns: * returns: -EIO on error, 0 otherwise
*/ */
static int static int
zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
{ {
int retval = -EIO;
struct fsf_qtcb_bottom_config *bottom; struct fsf_qtcb_bottom_config *bottom;
struct zfcp_adapter *adapter = fsf_req->adapter; struct zfcp_adapter *adapter = fsf_req->adapter;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't set any value, stay with the old (unitialized) ones */
goto skip_fsfstatus;
}
/* evaluate FSF status in QTCB */
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_GOOD:
ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
bottom = &fsf_req->qtcb->bottom.config; bottom = &fsf_req->qtcb->bottom.config;
/* only log QTCB versions for now */ ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n",
ZFCP_LOG_DEBUG("low QTCB version 0x%x of FSF, " bottom->low_qtcb_version, bottom->high_qtcb_version);
"high QTCB version 0x%x of FSF, \n", adapter->fsf_lic_version = bottom->lic_version;
bottom->low_qtcb_version, adapter->supported_features = bottom->supported_features;
bottom->high_qtcb_version);
if (xchg_ok) {
adapter->wwnn = bottom->nport_serv_param.wwnn; adapter->wwnn = bottom->nport_serv_param.wwnn;
adapter->wwpn = bottom->nport_serv_param.wwpn; adapter->wwpn = bottom->nport_serv_param.wwpn;
adapter->s_id = bottom->s_id & ZFCP_DID_MASK; adapter->s_id = bottom->s_id & ZFCP_DID_MASK;
adapter->hydra_version = bottom->adapter_type;
adapter->fsf_lic_version = bottom->lic_version;
adapter->fc_topology = bottom->fc_topology; adapter->fc_topology = bottom->fc_topology;
adapter->fc_link_speed = bottom->fc_link_speed; adapter->fc_link_speed = bottom->fc_link_speed;
adapter->supported_features = bottom->supported_features; adapter->hydra_version = bottom->adapter_type;
} else {
adapter->wwnn = 0;
adapter->wwpn = 0;
adapter->s_id = 0;
adapter->fc_topology = 0;
adapter->fc_link_speed = 0;
adapter->hydra_version = 0;
}
if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){ if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){
adapter->hardware_version = bottom->hardware_version; adapter->hardware_version = bottom->hardware_version;
/* copy just first 17 bytes */ memcpy(adapter->serial_number, bottom->serial_number, 17);
memcpy(adapter->serial_number, EBCASC(adapter->serial_number, sizeof(adapter->serial_number));
bottom->serial_number, 17); }
EBCASC(adapter->serial_number,
sizeof(adapter->serial_number)); ZFCP_LOG_INFO("The adapter %s reported the following characteristics:\n"
} "WWNN 0x%016Lx, "
"WWPN 0x%016Lx, "
ZFCP_LOG_INFO("The adapter %s reported " "S_ID 0x%08x,\n"
"the following characteristics:\n"
"WWNN 0x%16.16Lx, "
"WWPN 0x%16.16Lx, "
"S_ID 0x%6.6x,\n"
"adapter version 0x%x, " "adapter version 0x%x, "
"LIC version 0x%x, " "LIC version 0x%x, "
"FC link speed %d Gb/s\n", "FC link speed %d Gb/s\n",
...@@ -2207,10 +2184,9 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2207,10 +2184,9 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"versions in comparison to this device " "versions in comparison to this device "
"driver (try updated device driver)\n", "driver (try updated device driver)\n",
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
debug_text_event(fsf_req->adapter->erp_dbf, 0, debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver");
"low_qtcb_ver");
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
goto skip_fsfstatus; return -EIO;
} }
if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) { if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) {
ZFCP_LOG_NORMAL("error: the adapter %s " ZFCP_LOG_NORMAL("error: the adapter %s "
...@@ -2218,11 +2194,37 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2218,11 +2194,37 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"versions than this device driver uses" "versions than this device driver uses"
"(consider a microcode upgrade)\n", "(consider a microcode upgrade)\n",
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
debug_text_event(fsf_req->adapter->erp_dbf, 0, debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver");
"high_qtcb_ver");
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
goto skip_fsfstatus; return -EIO;
} }
return 0;
}
/*
* function: zfcp_fsf_exchange_config_data_handler
*
* purpose: is called for finished Exchange Configuration Data command
*
* returns:
*/
static int
zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
{
struct fsf_qtcb_bottom_config *bottom;
struct zfcp_adapter *adapter = fsf_req->adapter;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
return -EIO;
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_GOOD:
ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
return -EIO;
switch (adapter->fc_topology) { switch (adapter->fc_topology) {
case FSF_TOPO_P2P: case FSF_TOPO_P2P:
ZFCP_LOG_FLAGS(1, "FSF_TOPO_P2P\n"); ZFCP_LOG_FLAGS(1, "FSF_TOPO_P2P\n");
...@@ -2234,7 +2236,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2234,7 +2236,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 0, debug_text_event(fsf_req->adapter->erp_dbf, 0,
"top-p-to-p"); "top-p-to-p");
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
goto skip_fsfstatus; return -EIO;
case FSF_TOPO_AL: case FSF_TOPO_AL:
ZFCP_LOG_FLAGS(1, "FSF_TOPO_AL\n"); ZFCP_LOG_FLAGS(1, "FSF_TOPO_AL\n");
ZFCP_LOG_NORMAL("error: Arbitrated loop fibre-channel " ZFCP_LOG_NORMAL("error: Arbitrated loop fibre-channel "
...@@ -2245,7 +2247,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2245,7 +2247,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 0, debug_text_event(fsf_req->adapter->erp_dbf, 0,
"top-al"); "top-al");
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
goto skip_fsfstatus; return -EIO;
case FSF_TOPO_FABRIC: case FSF_TOPO_FABRIC:
ZFCP_LOG_FLAGS(1, "FSF_TOPO_FABRIC\n"); ZFCP_LOG_FLAGS(1, "FSF_TOPO_FABRIC\n");
ZFCP_LOG_INFO("Switched fabric fibre-channel " ZFCP_LOG_INFO("Switched fabric fibre-channel "
...@@ -2264,8 +2266,9 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2264,8 +2266,9 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
debug_text_exception(fsf_req->adapter->erp_dbf, 0, debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"unknown-topo"); "unknown-topo");
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
goto skip_fsfstatus; return -EIO;
} }
bottom = &fsf_req->qtcb->bottom.config;
if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) "
"allowed by the adapter %s " "allowed by the adapter %s "
...@@ -2279,22 +2282,32 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2279,22 +2282,32 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
debug_event(fsf_req->adapter->erp_dbf, 0, debug_event(fsf_req->adapter->erp_dbf, 0,
&bottom->max_qtcb_size, sizeof (u32)); &bottom->max_qtcb_size, sizeof (u32));
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
goto skip_fsfstatus; return -EIO;
} }
atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
&adapter->status); &adapter->status);
retval = 0;
break; break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
debug_text_event(adapter->erp_dbf, 0, "xchg-inco");
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
return -EIO;
ZFCP_LOG_INFO("Local link to adapter %s is down\n",
zfcp_get_busid_by_adapter(adapter));
atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&adapter->status);
zfcp_erp_adapter_failed(adapter);
break;
default: default:
/* retval is -EIO by default */
debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
debug_event(fsf_req->adapter->erp_dbf, 0, debug_event(fsf_req->adapter->erp_dbf, 0,
&fsf_req->qtcb->header.fsf_status, sizeof (u32)); &fsf_req->qtcb->header.fsf_status, sizeof (u32));
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
} }
skip_fsfstatus: return 0;
return retval;
} }
/* /*
...@@ -2408,20 +2421,19 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2408,20 +2421,19 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_NORMAL("Access denied, cannot open port " ZFCP_LOG_NORMAL("Access denied, cannot open port "
"with WWPN 0x%Lx connected to the adapter %s\n", "with WWPN 0x%Lx connected to the adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port)); port->wwpn, zfcp_get_busid_by_port(port));
counter = 0; for (counter = 0; counter < 2; counter++) {
do { subtable = header->fsf_status_qual.halfword[counter * 2];
subtable = header->fsf_status_qual.halfword[counter++]; rule = header->fsf_status_qual.halfword[counter * 2 + 1];
rule = header->fsf_status_qual.halfword[counter++];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_INFO("Access denied (%s rule %d)\n",
zfcp_act_subtable_type[subtable], rule); zfcp_act_subtable_type[subtable], rule);
break; break;
} }
} while (counter < 4); }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
zfcp_erp_port_failed(port); zfcp_erp_port_failed(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
...@@ -2814,20 +2826,19 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) ...@@ -2814,20 +2826,19 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
"physical port with WWPN 0x%Lx connected to " "physical port with WWPN 0x%Lx connected to "
"the adapter %s\n", port->wwpn, "the adapter %s\n", port->wwpn,
zfcp_get_busid_by_port(port)); zfcp_get_busid_by_port(port));
counter = 0; for (counter = 0; counter < 2; counter++) {
do { subtable = header->fsf_status_qual.halfword[counter * 2];
subtable = header->fsf_status_qual.halfword[counter++]; rule = header->fsf_status_qual.halfword[counter * 2 + 1];
rule = header->fsf_status_qual.halfword[counter++];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_INFO("Access denied (%s rule %d)\n",
zfcp_act_subtable_type[subtable], rule); zfcp_act_subtable_type[subtable], rule);
break; break;
} }
} while (counter < 4); }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -2956,8 +2967,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) ...@@ -2956,8 +2967,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
erp_action->fsf_req->data.open_unit.unit = erp_action->unit; erp_action->fsf_req->data.open_unit.unit = erp_action->unit;
erp_action->fsf_req->erp_action = erp_action; erp_action->fsf_req->erp_action = erp_action;
erp_action->fsf_req->qtcb->bottom.support.option = // erp_action->fsf_req->qtcb->bottom.support.option =
FSF_OPEN_LUN_SUPPRESS_BOXING; // FSF_OPEN_LUN_UNSOLICITED_SENSE_DATA;
/* start QDIO request for this FSF request */ /* start QDIO request for this FSF request */
retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
...@@ -2994,12 +3005,16 @@ static int ...@@ -2994,12 +3005,16 @@ static int
zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
{ {
int retval = -EINVAL; int retval = -EINVAL;
struct zfcp_adapter *adapter;
struct zfcp_unit *unit; struct zfcp_unit *unit;
struct fsf_qtcb_header *header; struct fsf_qtcb_header *header;
struct fsf_qtcb_bottom_support *bottom;
u16 subtable, rule, counter; u16 subtable, rule, counter;
adapter = fsf_req->adapter;
unit = fsf_req->data.open_unit.unit; unit = fsf_req->data.open_unit.unit;
header = &fsf_req->qtcb->header; header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't change unit status in our bookkeeping */ /* don't change unit status in our bookkeeping */
...@@ -3021,7 +3036,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3021,7 +3036,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) &header->fsf_status_qual, (char *) &header->fsf_status_qual,
sizeof (union fsf_status_qual)); sizeof (union fsf_status_qual));
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_ph_nv"); debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv");
zfcp_erp_adapter_reopen(unit->port->adapter, 0); zfcp_erp_adapter_reopen(unit->port->adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -3034,7 +3049,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3034,7 +3049,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
"to the adapter %s twice.\n", "to the adapter %s twice.\n",
unit->fcp_lun, unit->fcp_lun,
unit->port->wwpn, zfcp_get_busid_by_unit(unit)); unit->port->wwpn, zfcp_get_busid_by_unit(unit));
debug_text_exception(fsf_req->adapter->erp_dbf, 0, debug_text_exception(adapter->erp_dbf, 0,
"fsf_s_uopen"); "fsf_s_uopen");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -3046,21 +3061,20 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3046,21 +3061,20 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
"WWPN 0x%Lx connected to the adapter %s\n", "WWPN 0x%Lx connected to the adapter %s\n",
unit->fcp_lun, unit->port->wwpn, unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_unit(unit)); zfcp_get_busid_by_unit(unit));
counter = 0; for (counter = 0; counter < 2; counter++) {
do { subtable = header->fsf_status_qual.halfword[counter * 2];
subtable = header->fsf_status_qual.halfword[counter++]; rule = header->fsf_status_qual.halfword[counter * 2 + 1];
rule = header->fsf_status_qual.halfword[counter++];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_INFO("Access denied (%s rule %d)\n",
zfcp_act_subtable_type[subtable], rule); zfcp_act_subtable_type[subtable], rule);
break; break;
} }
} while (counter < 4); }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
zfcp_erp_unit_failed(unit); zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -3071,7 +3085,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3071,7 +3085,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
"with WWPN 0x%Lx on the adapter %s " "with WWPN 0x%Lx on the adapter %s "
"needs to be reopened\n", "needs to be reopened\n",
unit->port->wwpn, zfcp_get_busid_by_unit(unit)); unit->port->wwpn, zfcp_get_busid_by_unit(unit));
debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
zfcp_erp_port_reopen(unit->port, 0); zfcp_erp_port_reopen(unit->port, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY; ZFCP_STATUS_FSFREQ_RETRY;
...@@ -3079,30 +3093,38 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3079,30 +3093,38 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
case FSF_LUN_SHARING_VIOLATION : case FSF_LUN_SHARING_VIOLATION :
ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n"); ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n");
ZFCP_LOG_NORMAL("error: FCP-LUN 0x%Lx at " subtable = header->fsf_status_qual.halfword[4];
"the remote port with WWPN 0x%Lx connected " rule = header->fsf_status_qual.halfword[5];
"to the adapter %s " if (rule == 0xFFFF) {
"is already owned by another operating system " ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port "
"instance (LPAR or VM guest)\n", "with WWPN 0x%Lx connected to the "
"adapter %s is already in use\n",
unit->fcp_lun, unit->fcp_lun,
unit->port->wwpn, unit->port->wwpn,
zfcp_get_busid_by_unit(unit)); zfcp_get_busid_by_unit(unit));
subtable = header->fsf_status_qual.halfword[4]; } else {
rule = header->fsf_status_qual.halfword[5];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_NORMAL("Access to FCP-LUN 0x%Lx at the "
zfcp_act_subtable_type[subtable], rule); "remote port with WWPN 0x%Lx "
"connected to the adapter %s "
"is denied (%s rule %d)\n",
unit->fcp_lun,
unit->port->wwpn,
zfcp_get_busid_by_unit(unit),
zfcp_act_subtable_type[subtable],
rule);
break; break;
} }
ZFCP_LOG_NORMAL("Additional sense data is presented:\n"); }
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, ZFCP_LOG_DEBUG("status qualifier:\n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) &header->fsf_status_qual, (char *) &header->fsf_status_qual,
sizeof (union fsf_status_qual)); sizeof (union fsf_status_qual));
debug_text_event(fsf_req->adapter->erp_dbf, 2, debug_text_event(adapter->erp_dbf, 2,
"fsf_s_l_sh_vio"); "fsf_s_l_sh_vio");
zfcp_erp_unit_failed(unit); zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
...@@ -3118,7 +3140,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3118,7 +3140,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
unit->fcp_lun, unit->fcp_lun,
unit->port->wwpn, unit->port->wwpn,
zfcp_get_busid_by_unit(unit)); zfcp_get_busid_by_unit(unit));
debug_text_event(fsf_req->adapter->erp_dbf, 1, debug_text_event(adapter->erp_dbf, 1,
"fsf_s_max_units"); "fsf_s_max_units");
zfcp_erp_unit_failed(unit); zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
...@@ -3131,7 +3153,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3131,7 +3153,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_FLAGS(2, ZFCP_LOG_FLAGS(2,
"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* Re-establish link to port */ /* Re-establish link to port */
debug_text_event(fsf_req->adapter->erp_dbf, 1, debug_text_event(adapter->erp_dbf, 1,
"fsf_sq_ltest"); "fsf_sq_ltest");
zfcp_erp_port_reopen(unit->port, 0); zfcp_erp_port_reopen(unit->port, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
...@@ -3140,7 +3162,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3140,7 +3162,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_FLAGS(2, ZFCP_LOG_FLAGS(2,
"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n"); "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */ /* ERP strategy will escalate */
debug_text_event(fsf_req->adapter->erp_dbf, 1, debug_text_event(adapter->erp_dbf, 1,
"fsf_sq_ulp"); "fsf_sq_ulp");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -3148,27 +3170,41 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3148,27 +3170,41 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_NORMAL ZFCP_LOG_NORMAL
("bug: Wrong status qualifier 0x%x arrived.\n", ("bug: Wrong status qualifier 0x%x arrived.\n",
header->fsf_status_qual.word[0]); header->fsf_status_qual.word[0]);
debug_text_event(fsf_req->adapter->erp_dbf, 0, debug_text_event(adapter->erp_dbf, 0,
"fsf_sq_inval:"); "fsf_sq_inval:");
debug_exception(fsf_req->adapter->erp_dbf, 0, debug_exception(adapter->erp_dbf, 0,
&header->fsf_status_qual.word[0], &header->fsf_status_qual.word[0],
sizeof (u32)); sizeof (u32));
} }
break; break;
case FSF_INVALID_COMMAND_OPTION:
ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n");
ZFCP_LOG_NORMAL(
"Invalid option 0x%x has been specified "
"in QTCB bottom sent to the adapter %s\n",
bottom->option,
zfcp_get_busid_by_adapter(adapter));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
retval = -EINVAL;
break;
case FSF_GOOD: case FSF_GOOD:
ZFCP_LOG_FLAGS(3, "FSF_GOOD\n"); ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
/* save LUN handle assigned by FSF */ /* save LUN handle assigned by FSF */
unit->handle = header->lun_handle; unit->handle = header->lun_handle;
ZFCP_LOG_TRACE("unit (FCP_LUN=0x%Lx) of remote port " ZFCP_LOG_TRACE("unit (FCP_LUN=0x%Lx) of remote port "
"(WWPN=0x%Lx) via adapter (busid=%s) opened, " "(WWPN=0x%Lx) via adapter (busid=%s) opened, "
"port handle 0x%x \n", "port handle 0x%x, access flag 0x%02x\n",
unit->fcp_lun, unit->fcp_lun,
unit->port->wwpn, unit->port->wwpn,
zfcp_get_busid_by_unit(unit), zfcp_get_busid_by_unit(unit),
unit->handle); unit->handle,
bottom->lun_access);
/* mark unit as open */ /* mark unit as open */
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
if (adapter->supported_features & FSF_FEATURE_CFDC)
unit->lun_access = bottom->lun_access;
retval = 0; retval = 0;
break; break;
...@@ -3176,8 +3212,8 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3176,8 +3212,8 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
"(debug info 0x%x)\n", "(debug info 0x%x)\n",
header->fsf_status); header->fsf_status);
debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:");
debug_exception(fsf_req->adapter->erp_dbf, 0, debug_exception(adapter->erp_dbf, 0,
&header->fsf_status, sizeof (u32)); &header->fsf_status, sizeof (u32));
break; break;
} }
...@@ -3454,15 +3490,11 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, ...@@ -3454,15 +3490,11 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
* (need this for look up on normal command completion) * (need this for look up on normal command completion)
*/ */
fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd; fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd;
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 3, "fsf/sc"); debug_text_event(adapter->req_dbf, 3, "fsf/sc");
debug_event(adapter->req_dbf, 3, &fsf_req, sizeof (unsigned long)); debug_event(adapter->req_dbf, 3, &fsf_req, sizeof (unsigned long));
debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long)); debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long));
#endif /* ZFCP_DEBUG_REQUESTS */
#ifdef ZFCP_DEBUG_ABORTS
fsf_req->data.send_fcp_command_task.start_jiffies = jiffies;
#endif
fsf_req->data.send_fcp_command_task.start_jiffies = jiffies;
fsf_req->data.send_fcp_command_task.unit = unit; fsf_req->data.send_fcp_command_task.unit = unit;
ZFCP_LOG_DEBUG("unit=0x%lx, unit_fcp_lun=0x%Lx\n", ZFCP_LOG_DEBUG("unit=0x%lx, unit_fcp_lun=0x%Lx\n",
(unsigned long) unit, unit->fcp_lun); (unsigned long) unit, unit->fcp_lun);
...@@ -3605,10 +3637,8 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, ...@@ -3605,10 +3637,8 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
no_fit: no_fit:
failed_scsi_cmnd: failed_scsi_cmnd:
/* dequeue new FSF request previously enqueued */ /* dequeue new FSF request previously enqueued */
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 3, "fail_sc"); debug_text_event(adapter->req_dbf, 3, "fail_sc");
debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long)); debug_event(adapter->req_dbf, 3, &scsi_cmnd, sizeof (unsigned long));
#endif /* ZFCP_DEBUG_REQUESTS */
zfcp_fsf_req_free(fsf_req); zfcp_fsf_req_free(fsf_req);
fsf_req = NULL; fsf_req = NULL;
...@@ -3863,20 +3893,19 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) ...@@ -3863,20 +3893,19 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
"remote port with WWPN 0x%Lx connected to the " "remote port with WWPN 0x%Lx connected to the "
"adapter %s\n", unit->fcp_lun, unit->port->wwpn, "adapter %s\n", unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_unit(unit)); zfcp_get_busid_by_unit(unit));
counter = 0; for (counter = 0; counter < 2; counter++) {
do { subtable = header->fsf_status_qual.halfword[counter * 2];
subtable = header->fsf_status_qual.halfword[counter++]; rule = header->fsf_status_qual.halfword[counter * 2 + 1];
rule = header->fsf_status_qual.halfword[counter++];
switch (subtable) { switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS: case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID: case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
case FSF_SQ_CFDC_SUBTABLE_LUN: case FSF_SQ_CFDC_SUBTABLE_LUN:
ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", ZFCP_LOG_INFO("Access denied (%s rule %d)\n",
zfcp_act_subtable_type[subtable], rule); zfcp_act_subtable_type[subtable], rule);
break; break;
} }
} while (counter < 4); }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
...@@ -4384,7 +4413,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ...@@ -4384,7 +4413,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
* the new eh * the new eh
*/ */
/* always call back */ /* always call back */
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(fsf_req->adapter->req_dbf, 2, "ok_done:"); debug_text_event(fsf_req->adapter->req_dbf, 2, "ok_done:");
debug_event(fsf_req->adapter->req_dbf, 2, &scpnt, debug_event(fsf_req->adapter->req_dbf, 2, &scpnt,
sizeof (unsigned long)); sizeof (unsigned long));
...@@ -4392,7 +4420,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ...@@ -4392,7 +4420,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
sizeof (unsigned long)); sizeof (unsigned long));
debug_event(fsf_req->adapter->req_dbf, 2, &fsf_req, debug_event(fsf_req->adapter->req_dbf, 2, &fsf_req,
sizeof (unsigned long)); sizeof (unsigned long));
#endif /* ZFCP_DEBUG_REQUESTS */
(scpnt->scsi_done) (scpnt); (scpnt->scsi_done) (scpnt);
/* /*
* We must hold this lock until scsi_done has been called. * We must hold this lock until scsi_done has been called.
...@@ -4505,15 +4532,13 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, ...@@ -4505,15 +4532,13 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
int direction; int direction;
int retval = 0; int retval = 0;
#if 0 if (!(adapter->supported_features & FSF_FEATURE_CFDC)) {
if (!(adapter->features & FSF_FEATURE_CFDC)) {
ZFCP_LOG_INFO( ZFCP_LOG_INFO(
"Adapter %s does not support control file\n", "Adapter %s does not support control file\n",
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
retval = -EOPNOTSUPP; retval = -EOPNOTSUPP;
goto no_act_support; goto no_cfdc_support;
} }
#endif
switch (fsf_command) { switch (fsf_command) {
...@@ -4595,6 +4620,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, ...@@ -4595,6 +4620,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
invalid_command: invalid_command:
no_cfdc_support:
return retval; return retval;
} }
...@@ -4932,11 +4958,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, ...@@ -4932,11 +4958,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
goto failed_sbals; goto failed_sbals;
} }
/* set magics */
fsf_req->common_magic = ZFCP_MAGIC;
fsf_req->specific_magic = ZFCP_MAGIC_FSFREQ;
fsf_req->adapter = adapter; /* pointer to "parent" adapter */ fsf_req->adapter = adapter; /* pointer to "parent" adapter */
fsf_req->fsf_command = fsf_cmd; fsf_req->fsf_command = fsf_cmd;
fsf_req->sbal_number = 1; fsf_req->sbal_number = 1;
...@@ -5085,7 +5106,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -5085,7 +5106,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
"to request queue.\n"); "to request queue.\n");
} else { } else {
req_queue->distance_from_int = new_distance_from_int; req_queue->distance_from_int = new_distance_from_int;
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 1, "o:a/seq"); debug_text_event(adapter->req_dbf, 1, "o:a/seq");
debug_event(adapter->req_dbf, 1, &fsf_req, debug_event(adapter->req_dbf, 1, &fsf_req,
sizeof (unsigned long)); sizeof (unsigned long));
...@@ -5095,7 +5115,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -5095,7 +5115,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
} else { } else {
debug_text_event(adapter->req_dbf, 1, "nocb"); debug_text_event(adapter->req_dbf, 1, "nocb");
} }
#endif /* ZFCP_DEBUG_REQUESTS */
/* /*
* increase FSF sequence counter - * increase FSF sequence counter -
* this must only be done for request successfully enqueued to * this must only be done for request successfully enqueued to
......
...@@ -108,6 +108,7 @@ ...@@ -108,6 +108,7 @@
#define FSF_CONFLICTS_OVERRULED 0x00000058 #define FSF_CONFLICTS_OVERRULED 0x00000058
#define FSF_PORT_BOXED 0x00000059 #define FSF_PORT_BOXED 0x00000059
#define FSF_LUN_BOXED 0x0000005A #define FSF_LUN_BOXED 0x0000005A
#define FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE 0x0000005B
#define FSF_PAYLOAD_SIZE_MISMATCH 0x00000060 #define FSF_PAYLOAD_SIZE_MISMATCH 0x00000060
#define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061
#define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062
...@@ -156,7 +157,6 @@ ...@@ -156,7 +157,6 @@
#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004
#define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */ #define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */
#define FSF_STATUS_READ_LINK_UP 0x00000006 #define FSF_STATUS_READ_LINK_UP 0x00000006
#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009
#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
...@@ -165,8 +165,6 @@ ...@@ -165,8 +165,6 @@
#define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002
/* status subtypes for CFDC */ /* status subtypes for CFDC */
#define FSF_STATUS_READ_SUB_LOST_CFDC_UPDATED 0x00000020
#define FSF_STATUS_READ_SUB_LOST_CFDC_HARDENED 0x00000040
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
...@@ -198,18 +196,23 @@ ...@@ -198,18 +196,23 @@
/* channel features */ /* channel features */
#define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001 #define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001
#define FSF_FEATURE_CFDC 0x00000002 #define FSF_FEATURE_CFDC 0x00000002
#define FSF_FEATURE_SENSEDATA_REPLICATION 0x00000004
#define FSF_FEATURE_LOST_SAN_NOTIFICATION 0x00000008 #define FSF_FEATURE_LOST_SAN_NOTIFICATION 0x00000008
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
/* option */ /* option */
#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001
#define FSF_OPEN_LUN_UNSOLICITED_SENSE_DATA 0x00000002
/* adapter types */ /* adapter types */
#define FSF_ADAPTER_TYPE_FICON 0x00000001 #define FSF_ADAPTER_TYPE_FICON 0x00000001
#define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002 #define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002
/* flags */
#define FSF_CFDC_OPEN_LUN_ALLOWED 0x01
#define FSF_CFDC_EXCLUSIVE_ACCESS 0x02
#define FSF_CFDC_OUTBOUND_TRANSFER_ALLOWED 0x10
/* port types */ /* port types */
#define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001 #define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001
#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 #define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003
...@@ -396,7 +399,8 @@ struct fsf_qtcb_bottom_support { ...@@ -396,7 +399,8 @@ struct fsf_qtcb_bottom_support {
u32 service_class; u32 service_class;
u8 res3[3]; u8 res3[3];
u8 timeout; u8 timeout;
u8 res4[184]; u32 lun_access;
u8 res4[180];
u32 els1_length; u32 els1_length;
u32 els2_length; u32 els2_length;
u32 req_buf_length; u32 req_buf_length;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#define ZFCP_QDIO_C_REVISION "$Revision: 1.13 $" #define ZFCP_QDIO_C_REVISION "$Revision: 1.16 $"
#include "zfcp_ext.h" #include "zfcp_ext.h"
...@@ -485,11 +485,9 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) ...@@ -485,11 +485,9 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
struct zfcp_fsf_req *fsf_req; struct zfcp_fsf_req *fsf_req;
int retval = 0; int retval = 0;
#ifdef ZFCP_DEBUG_REQUESTS
/* Note: seq is entered later */ /* Note: seq is entered later */
debug_text_event(adapter->req_dbf, 1, "i:a/seq"); debug_text_event(adapter->req_dbf, 1, "i:a/seq");
debug_event(adapter->req_dbf, 1, &sbale_addr, sizeof (unsigned long)); debug_event(adapter->req_dbf, 1, &sbale_addr, sizeof (unsigned long));
#endif /* ZFCP_DEBUG_REQUESTS */
/* invalid (per convention used in this driver) */ /* invalid (per convention used in this driver) */
if (unlikely(!sbale_addr)) { if (unlikely(!sbale_addr)) {
...@@ -502,17 +500,6 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) ...@@ -502,17 +500,6 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
/* valid request id and thus (hopefully :) valid fsf_req address */ /* valid request id and thus (hopefully :) valid fsf_req address */
fsf_req = (struct zfcp_fsf_req *) sbale_addr; fsf_req = (struct zfcp_fsf_req *) sbale_addr;
if (unlikely((fsf_req->common_magic != ZFCP_MAGIC) ||
(fsf_req->specific_magic != ZFCP_MAGIC_FSFREQ))) {
ZFCP_LOG_NORMAL("bug: An inbound FSF acknowledgement was "
"faulty (debug info 0x%x, 0x%x, 0x%lx)\n",
fsf_req->common_magic,
fsf_req->specific_magic,
(unsigned long) fsf_req);
retval = -EINVAL;
goto out;
}
if (unlikely(adapter != fsf_req->adapter)) { if (unlikely(adapter != fsf_req->adapter)) {
ZFCP_LOG_NORMAL("bug: An inbound FSF acknowledgement was not " ZFCP_LOG_NORMAL("bug: An inbound FSF acknowledgement was not "
"correct (debug info 0x%lx, 0x%lx, 0%lx) \n", "correct (debug info 0x%lx, 0x%lx, 0%lx) \n",
...@@ -522,13 +509,11 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) ...@@ -522,13 +509,11 @@ zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
#ifdef ZFCP_DEBUG_REQUESTS
/* debug feature stuff (test for QTCB: remember new unsol. status!) */ /* debug feature stuff (test for QTCB: remember new unsol. status!) */
if (likely(fsf_req->qtcb)) { if (likely(fsf_req->qtcb)) {
debug_event(adapter->req_dbf, 1, debug_event(adapter->req_dbf, 1,
&fsf_req->qtcb->prefix.req_seq_no, sizeof (u32)); &fsf_req->qtcb->prefix.req_seq_no, sizeof (u32));
} }
#endif /* ZFCP_DEBUG_REQUESTS */
ZFCP_LOG_TRACE("fsf_req at 0x%lx, QTCB at 0x%lx\n", ZFCP_LOG_TRACE("fsf_req at 0x%lx, QTCB at 0x%lx\n",
(unsigned long) fsf_req, (unsigned long) fsf_req->qtcb); (unsigned long) fsf_req, (unsigned long) fsf_req->qtcb);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
/* this drivers version (do not edit !!! generated and updated by cvs) */ /* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_SCSI_REVISION "$Revision: 1.52 $" #define ZFCP_SCSI_REVISION "$Revision: 1.59 $"
#include <linux/blkdev.h> #include <linux/blkdev.h>
...@@ -48,14 +48,15 @@ static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); ...@@ -48,14 +48,15 @@ static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *);
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
static int zfcp_task_management_function(struct zfcp_unit *, u8); static int zfcp_task_management_function(struct zfcp_unit *, u8);
static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, int, int); static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
scsi_lun_t);
static struct device_attribute *zfcp_sysfs_sdev_attrs[]; static struct device_attribute *zfcp_sysfs_sdev_attrs[];
struct zfcp_data zfcp_data = { struct zfcp_data zfcp_data = {
.scsi_host_template = { .scsi_host_template = {
name: ZFCP_NAME, name: ZFCP_NAME,
proc_name: "dummy", proc_name: "zfcp",
proc_info: NULL, proc_info: NULL,
detect: NULL, detect: NULL,
slave_alloc: zfcp_scsi_slave_alloc, slave_alloc: zfcp_scsi_slave_alloc,
...@@ -299,12 +300,9 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, ...@@ -299,12 +300,9 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
ZFCP_LOG_DEBUG("error: Could not send a Send FCP Command\n"); ZFCP_LOG_DEBUG("error: Could not send a Send FCP Command\n");
retval = SCSI_MLQUEUE_HOST_BUSY; retval = SCSI_MLQUEUE_HOST_BUSY;
} else { } else {
#ifdef ZFCP_DEBUG_REQUESTS
debug_text_event(adapter->req_dbf, 3, "q_scpnt"); debug_text_event(adapter->req_dbf, 3, "q_scpnt");
debug_event(adapter->req_dbf, 3, &scpnt, debug_event(adapter->req_dbf, 3, &scpnt,
sizeof (unsigned long)); sizeof (unsigned long));
#endif /* ZFCP_DEBUG_REQUESTS */
} }
out: out:
...@@ -376,7 +374,8 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, ...@@ -376,7 +374,8 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
* context: * context:
*/ */
static struct zfcp_unit * static struct zfcp_unit *
zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, int id, int lun) zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
scsi_lun_t lun)
{ {
struct zfcp_port *port; struct zfcp_port *port;
struct zfcp_unit *unit, *retval = NULL; struct zfcp_unit *unit, *retval = NULL;
...@@ -426,8 +425,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ...@@ -426,8 +425,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
unsigned long flags; unsigned long flags;
u32 status = 0; u32 status = 0;
#ifdef ZFCP_DEBUG_ABORTS
/* the components of a abort_dbf record (fixed size record) */ /* the components of a abort_dbf record (fixed size record) */
u64 dbf_scsi_cmnd = (unsigned long) scpnt; u64 dbf_scsi_cmnd = (unsigned long) scpnt;
char dbf_opcode[ZFCP_ABORT_DBF_LENGTH]; char dbf_opcode[ZFCP_ABORT_DBF_LENGTH];
...@@ -445,7 +442,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ...@@ -445,7 +442,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
memcpy(dbf_opcode, memcpy(dbf_opcode,
scpnt->cmnd, scpnt->cmnd,
min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH)); min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH));
#endif
/*TRACE*/ /*TRACE*/
ZFCP_LOG_INFO ZFCP_LOG_INFO
...@@ -488,11 +484,11 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ...@@ -488,11 +484,11 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* Figure out which fsf_req needs to be aborted. */ /* Figure out which fsf_req needs to be aborted. */
old_fsf_req = req_data->send_fcp_command_task.fsf_req; old_fsf_req = req_data->send_fcp_command_task.fsf_req;
#ifdef ZFCP_DEBUG_ABORTS
dbf_fsf_req = (unsigned long) old_fsf_req; dbf_fsf_req = (unsigned long) old_fsf_req;
dbf_timeout = dbf_timeout =
(jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ; (jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ;
#endif
/* DEBUG */ /* DEBUG */
ZFCP_LOG_DEBUG("old_fsf_req=0x%lx\n", (unsigned long) old_fsf_req); ZFCP_LOG_DEBUG("old_fsf_req=0x%lx\n", (unsigned long) old_fsf_req);
if (!old_fsf_req) { if (!old_fsf_req) {
...@@ -548,7 +544,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ...@@ -548,7 +544,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* wait for completion of abort */ /* wait for completion of abort */
ZFCP_LOG_DEBUG("Waiting for cleanup....\n"); ZFCP_LOG_DEBUG("Waiting for cleanup....\n");
#ifdef ZFCP_DEBUG_ABORTS #ifdef 1
/* /*
* FIXME: * FIXME:
* copying zfcp_fsf_req_wait_and_cleanup code is not really nice * copying zfcp_fsf_req_wait_and_cleanup code is not really nice
...@@ -585,7 +581,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ...@@ -585,7 +581,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
} }
out: out:
#ifdef ZFCP_DEBUG_ABORTS
debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64)); debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64));
debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH); debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH);
debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t)); debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t));
...@@ -598,7 +593,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ...@@ -598,7 +593,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64)); debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64));
debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64)); debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64));
debug_text_event(adapter->abort_dbf, 1, dbf_result); debug_text_event(adapter->abort_dbf, 1, dbf_result);
#endif
spin_lock_irq(scsi_host->host_lock); spin_lock_irq(scsi_host->host_lock);
return retval; return retval;
} }
...@@ -796,11 +791,16 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) ...@@ -796,11 +791,16 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
(unsigned long) adapter->scsi_host); (unsigned long) adapter->scsi_host);
/* tell the SCSI stack some characteristics of this adapter */ /* tell the SCSI stack some characteristics of this adapter */
adapter->scsi_host->max_id = adapter->max_scsi_id + 1; adapter->scsi_host->max_id = 1;
adapter->scsi_host->max_lun = adapter->max_scsi_lun + 1; adapter->scsi_host->max_lun = 1;
adapter->scsi_host->max_channel = 0; adapter->scsi_host->max_channel = 0;
adapter->scsi_host->unique_id = unique_id++; /* FIXME */ adapter->scsi_host->unique_id = unique_id++; /* FIXME */
adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;
/*
* Reverse mapping of the host number to avoid race condition
*/
adapter->scsi_host_no = adapter->scsi_host->host_no;
/* /*
* save a pointer to our own adapter data structure within * save a pointer to our own adapter data structure within
* hostdata field of SCSI host data structure * hostdata field of SCSI host data structure
...@@ -835,6 +835,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) ...@@ -835,6 +835,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
scsi_remove_host(shost); scsi_remove_host(shost);
scsi_host_put(shost); scsi_host_put(shost);
adapter->scsi_host = NULL; adapter->scsi_host = NULL;
adapter->scsi_host_no = 0;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return; return;
...@@ -850,68 +851,32 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) ...@@ -850,68 +851,32 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
add_timer(&adapter->scsi_er_timer); add_timer(&adapter->scsi_er_timer);
} }
/**
* zfcp_sysfs_hba_id_show - display hba_id of scsi device
* @dev: pointer to belonging device
* @buf: pointer to input buffer
*
* "hba_id" attribute of a scsi device. Displays hba_id (bus_id)
* of the adapter belonging to a scsi device.
*/
static ssize_t
zfcp_sysfs_hba_id_show(struct device *dev, char *buf)
{
struct scsi_device *sdev;
struct zfcp_unit *unit;
sdev = to_scsi_device(dev);
unit = (struct zfcp_unit *) sdev->hostdata;
return sprintf(buf, "%s\n", zfcp_get_busid_by_unit(unit));
}
static DEVICE_ATTR(hba_id, S_IRUGO, zfcp_sysfs_hba_id_show, NULL);
/** /**
* zfcp_sysfs_wwpn_show - display wwpn of scsi device * ZFCP_DEFINE_SCSI_ATTR
* @dev: pointer to belonging device * @_name: name of show attribute
* @buf: pointer to input buffer * @_format: format string
* * @_value: value to print
* "wwpn" attribute of a scsi device. Displays wwpn of the port *
* belonging to a scsi device. * Generates attribute for a unit.
*/ */
static ssize_t #define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value) \
zfcp_sysfs_wwpn_show(struct device *dev, char *buf) static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
{ char *buf) \
struct scsi_device *sdev; { \
struct zfcp_unit *unit; struct scsi_device *sdev; \
struct zfcp_unit *unit; \
sdev = to_scsi_device(dev); \
unit = (struct zfcp_unit *) sdev->hostdata; sdev = to_scsi_device(dev); \
return sprintf(buf, "0x%016llx\n", unit->port->wwpn); unit = sdev->hostdata; \
} return sprintf(buf, _format, _value); \
} \
static DEVICE_ATTR(wwpn, S_IRUGO, zfcp_sysfs_wwpn_show, NULL); \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
/**
* zfcp_sysfs_fcp_lun_show - display fcp lun of scsi device ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", zfcp_get_busid_by_unit(unit));
* @dev: pointer to belonging device ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);
* @buf: pointer to input buffer ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);
*
* "fcp_lun" attribute of a scsi device. Displays fcp_lun of the unit
* belonging to a scsi device.
*/
static ssize_t
zfcp_sysfs_fcp_lun_show(struct device *dev, char *buf)
{
struct scsi_device *sdev;
struct zfcp_unit *unit;
sdev = to_scsi_device(dev);
unit = (struct zfcp_unit *) sdev->hostdata;
return sprintf(buf, "0x%016llx\n", unit->fcp_lun);
}
static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_fcp_lun_show, NULL);
static struct device_attribute *zfcp_sysfs_sdev_attrs[] = { static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun, &dev_attr_fcp_lun,
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.30 $" #define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.32 $"
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include "zfcp_ext.h" #include "zfcp_ext.h"
...@@ -75,6 +75,7 @@ ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", ...@@ -75,6 +75,7 @@ ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
adapter->hardware_version); adapter->hardware_version);
ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number); ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
/** /**
* zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter
...@@ -99,30 +100,6 @@ zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf) ...@@ -99,30 +100,6 @@ zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf)
static DEVICE_ATTR(in_recovery, S_IRUGO, static DEVICE_ATTR(in_recovery, S_IRUGO,
zfcp_sysfs_adapter_in_recovery_show, NULL); zfcp_sysfs_adapter_in_recovery_show, NULL);
/**
* zfcp_sysfs_adapter_scsi_host_no_show - display scsi_host_no of adapter
* @dev: pointer to belonging device
* @buf: pointer to input buffer
*
* "scsi_host_no" attribute of adapter. Displays the SCSI host number.
*/
static ssize_t
zfcp_sysfs_adapter_scsi_host_no_show(struct device *dev, char *buf)
{
struct zfcp_adapter *adapter;
unsigned short host_no = 0;
down(&zfcp_data.config_sema);
adapter = dev_get_drvdata(dev);
if (adapter->scsi_host)
host_no = adapter->scsi_host->host_no;
up(&zfcp_data.config_sema);
return sprintf(buf, "0x%x\n", host_no);
}
static DEVICE_ATTR(scsi_host_no, S_IRUGO, zfcp_sysfs_adapter_scsi_host_no_show,
NULL);
/** /**
* zfcp_sysfs_port_add_store - add a port to sysfs tree * zfcp_sysfs_port_add_store - add a port to sysfs tree
* @dev: pointer to belonging device * @dev: pointer to belonging device
...@@ -219,9 +196,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count) ...@@ -219,9 +196,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count)
zfcp_erp_port_shutdown(port, 0); zfcp_erp_port_shutdown(port, 0);
zfcp_erp_wait(adapter); zfcp_erp_wait(adapter);
zfcp_port_put(port); zfcp_port_put(port);
zfcp_sysfs_port_remove_files(&port->sysfs_device, zfcp_port_dequeue(port);
atomic_read(&port->status));
device_unregister(&port->sysfs_device);
out: out:
up(&zfcp_data.config_sema); up(&zfcp_data.config_sema);
return retval ? retval : count; return retval ? retval : count;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.37 $" #define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.39 $"
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -43,11 +43,7 @@ ...@@ -43,11 +43,7 @@
void void
zfcp_sysfs_port_release(struct device *dev) zfcp_sysfs_port_release(struct device *dev)
{ {
struct zfcp_port *port; kfree(dev);
port = dev_get_drvdata(dev);
zfcp_port_dequeue(port);
return;
} }
/** /**
...@@ -112,7 +108,6 @@ zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count) ...@@ -112,7 +108,6 @@ zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count)
zfcp_erp_unit_reopen(unit, 0); zfcp_erp_unit_reopen(unit, 0);
zfcp_erp_wait(unit->port->adapter); zfcp_erp_wait(unit->port->adapter);
wait_event(unit->scsi_add_wq, atomic_read(&unit->scsi_add_work) == 0);
zfcp_unit_put(unit); zfcp_unit_put(unit);
out: out:
up(&zfcp_data.config_sema); up(&zfcp_data.config_sema);
...@@ -168,8 +163,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count) ...@@ -168,8 +163,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count)
zfcp_erp_unit_shutdown(unit, 0); zfcp_erp_unit_shutdown(unit, 0);
zfcp_erp_wait(unit->port->adapter); zfcp_erp_wait(unit->port->adapter);
zfcp_unit_put(unit); zfcp_unit_put(unit);
zfcp_sysfs_unit_remove_files(&unit->sysfs_device); zfcp_unit_dequeue(unit);
device_unregister(&unit->sysfs_device);
out: out:
up(&zfcp_data.config_sema); up(&zfcp_data.config_sema);
return retval ? retval : count; return retval ? retval : count;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.23 $" #define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.24 $"
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -43,11 +43,7 @@ ...@@ -43,11 +43,7 @@
void void
zfcp_sysfs_unit_release(struct device *dev) zfcp_sysfs_unit_release(struct device *dev)
{ {
struct zfcp_unit *unit; kfree(dev);
unit = dev_get_drvdata(dev);
zfcp_unit_dequeue(unit);
return;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment