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.
- Replace release function for device structures by kfree. Move struct
device to the start of struct zfcp_port/zfcp_unit to make it work.
- 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.
diffstat:
drivers/s390/scsi/zfcp_aux.c | 191 ++++++++-------------------------
drivers/s390/scsi/zfcp_ccw.c | 14 --
drivers/s390/scsi/zfcp_def.h | 44 +++----
drivers/s390/scsi/zfcp_erp.c | 26 ----
drivers/s390/scsi/zfcp_ext.h | 6 -
drivers/s390/scsi/zfcp_fsf.c | 185 +++++++++++++++++--------------
drivers/s390/scsi/zfcp_fsf.h | 12 +-
drivers/s390/scsi/zfcp_qdio.c | 15 --
drivers/s390/scsi/zfcp_scsi.c | 98 +++++-----------
drivers/s390/scsi/zfcp_sysfs_adapter.c | 31 -----
drivers/s390/scsi/zfcp_sysfs_port.c | 20 ---
drivers/s390/scsi/zfcp_sysfs_unit.c | 16 --
12 files changed, 236 insertions(+), 422 deletions(-)
diff -urN linux-2.6/drivers/s390/scsi/zfcp_aux.c linux-2.6-s390/drivers/s390/scsi/zfcp_aux.c
--- linux-2.6/drivers/s390/scsi/zfcp_aux.c Thu Mar 11 03:55:54 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_aux.c Tue Mar 16 14:03:14 2004
@@ -29,43 +29,10 @@
*/
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_AUX_REVISION "$Revision: 1.98 $"
-
-/********************** 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>
+#define ZFCP_AUX_REVISION "$Revision: 1.103 $"
#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) */
static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS;
static char *device;
@@ -421,8 +388,8 @@
goto out_unit;
up(&zfcp_data.config_sema);
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);
+ down(&zfcp_data.config_sema);
zfcp_unit_put(unit);
out_unit:
zfcp_port_put(port);
@@ -978,7 +945,9 @@
struct zfcp_unit *
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
@@ -1002,18 +971,12 @@
init_waitqueue_head(&unit->remove_wq);
unit->port = port;
- /*
- * FIXME: reuse of scsi_luns!
- */
- unit->scsi_lun = port->max_scsi_lun + 1;
unit->fcp_lun = fcp_lun;
- unit->common_magic = ZFCP_MAGIC;
- unit->specific_magic = ZFCP_MAGIC_UNIT;
/* setup for sysfs registration */
snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun);
unit->sysfs_device.parent = &port->sysfs_device;
- unit->sysfs_device.release = zfcp_sysfs_unit_release;
+ unit->sysfs_device.release = (void (*)(struct device *))kfree;
dev_set_drvdata(&unit->sysfs_device, unit);
/* mark unit unusable as long as sysfs registration is not complete */
@@ -1025,43 +988,29 @@
}
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);
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);
- /* unit is new and needs to be added to list */
+ scsi_lun = 0;
+ found = 0;
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_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
- list_add_tail(&unit->list, &port->unit_list_head);
write_unlock_irq(&zfcp_data.config_lock);
port->units++;
@@ -1070,21 +1019,17 @@
return unit;
}
-/* locks: config_sema must be held */
void
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);
list_del(&unit->list);
write_unlock_irq(&zfcp_data.config_lock);
-
unit->port->units--;
zfcp_port_put(unit->port);
-
- kfree(unit);
-
- return;
+ zfcp_sysfs_unit_remove_files(&unit->sysfs_device);
+ device_unregister(&unit->sysfs_device);
}
static void *
@@ -1154,7 +1099,7 @@
adapter->pool.data_status_read =
mempool_create(ZFCP_POOL_STATUS_READ_NR,
- zfcp_mempool_alloc, zfcp_mempool_free,
+ zfcp_mempool_alloc, zfcp_mempool_free,
(void *) sizeof(struct fsf_status_read_buffer));
if (NULL == adapter->pool.data_status_read) {
@@ -1246,10 +1191,6 @@
if (retval)
goto failed_low_mem_buffers;
- /* set magics */
- adapter->common_magic = ZFCP_MAGIC;
- adapter->specific_magic = ZFCP_MAGIC_ADAPTER;
-
/* initialise reference count stuff */
atomic_set(&adapter->refcount, 0);
init_waitqueue_head(&adapter->remove_wq);
@@ -1515,25 +1456,20 @@
}
/*
- * Enqueues a remote port at the end of the port list.
- * All port internal structures are set-up and the proc-fs entry is also
- * allocated. Some SCSI-stack structures are modified for the port.
+ * Enqueues a remote port to the port list. All port internal structures
+ * are set up and the sysfs entry is also generated.
*
- * returns: 0 if a new port was successfully enqueued
- * 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
+ * returns: pointer to port or NULL
* 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 *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
{
- struct zfcp_port *port;
- int check_scsi_id;
+ struct zfcp_port *port, *tmp_port;
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);
/*
@@ -1561,17 +1497,11 @@
port->adapter = adapter;
- if (check_scsi_id)
- port->scsi_id = adapter->max_scsi_id + 1;
-
if (check_wwpn)
port->wwpn = wwpn;
atomic_set_mask(status, &port->status);
- port->common_magic = ZFCP_MAGIC;
- port->specific_magic = ZFCP_MAGIC_PORT;
-
/* setup for sysfs registration */
if (status & ZFCP_STATUS_PORT_NAMESERVER)
snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "nameserver");
@@ -1579,7 +1509,7 @@
snprintf(port->sysfs_device.bus_id,
BUS_ID_SIZE, "0x%016llx", wwpn);
port->sysfs_device.parent = &adapter->ccw_device->dev;
- port->sysfs_device.release = zfcp_sysfs_port_release;
+ port->sysfs_device.release = (void (*)(struct device *))kfree;
dev_set_drvdata(&port->sysfs_device, port);
/* mark port unusable as long as sysfs registration is not complete */
@@ -1591,41 +1521,32 @@
}
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);
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);
+ scsi_id = 1;
+ found = 0;
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_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
- list_add_tail(&port->list, &adapter->port_list_head);
write_unlock_irq(&zfcp_data.config_lock);
adapter->ports++;
@@ -1634,26 +1555,18 @@
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
zfcp_port_dequeue(struct zfcp_port *port)
{
- /* remove specified port from list */
+ zfcp_port_wait(port);
write_lock_irq(&zfcp_data.config_lock);
list_del(&port->list);
write_unlock_irq(&zfcp_data.config_lock);
-
port->adapter->ports--;
zfcp_adapter_put(port->adapter);
-
- kfree(port);
-
- return;
+ zfcp_sysfs_port_remove_files(&port->sysfs_device,
+ atomic_read(&port->status));
+ device_unregister(&port->sysfs_device);
}
/* Enqueues a nameserver port */
diff -urN linux-2.6/drivers/s390/scsi/zfcp_ccw.c linux-2.6-s390/drivers/s390/scsi/zfcp_ccw.c
--- linux-2.6/drivers/s390/scsi/zfcp_ccw.c Thu Mar 11 03:55:24 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_ccw.c Tue Mar 16 14:03:14 2004
@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_CCW_C_REVISION "$Revision: 1.48 $"
+#define ZFCP_CCW_C_REVISION "$Revision: 1.51 $"
#include <linux/init.h>
#include <linux/module.h>
@@ -55,6 +55,7 @@
};
static struct ccw_driver zfcp_ccw_driver = {
+ .owner = THIS_MODULE,
.name = ZFCP_NAME,
.ids = zfcp_ccw_device_id,
.probe = zfcp_ccw_probe,
@@ -130,14 +131,9 @@
list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) {
list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) {
- zfcp_unit_wait(unit);
- zfcp_sysfs_unit_remove_files(&unit->sysfs_device);
- device_unregister(&unit->sysfs_device);
+ zfcp_unit_dequeue(unit);
}
- zfcp_port_wait(port);
- zfcp_sysfs_port_remove_files(&port->sysfs_device,
- atomic_read(&port->status));
- device_unregister(&port->sysfs_device);
+ zfcp_port_dequeue(port);
}
zfcp_adapter_wait(adapter);
zfcp_adapter_dequeue(adapter);
@@ -163,7 +159,7 @@
down(&zfcp_data.config_sema);
adapter = dev_get_drvdata(&ccw_device->dev);
- retval = zfcp_erp_thread_setup(adapter);
+ retval = zfcp_erp_thread_setup(adapter);
if (retval) {
ZFCP_LOG_INFO("error: out of resources. "
"error recovery thread for adapter %s "
diff -urN linux-2.6/drivers/s390/scsi/zfcp_def.h linux-2.6-s390/drivers/s390/scsi/zfcp_def.h
--- linux-2.6/drivers/s390/scsi/zfcp_def.h Thu Mar 11 03:55:28 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_def.h Tue Mar 16 14:03:14 2004
@@ -33,25 +33,29 @@
#define ZFCP_DEF_H
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_DEF_REVISION "$Revision: 1.62 $"
+#define ZFCP_DEF_REVISION "$Revision: 1.69 $"
/*************************** INCLUDES *****************************************/
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/major.h>
#include <linux/blkdev.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
-#include "../../scsi/scsi.h"
#include "../../fc4/fc.h"
-#include "zfcp_fsf.h" /* FSF SW Interface */
+#include "zfcp_fsf.h"
#include <asm/ccwdev.h>
#include <asm/qdio.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
#include <linux/reboot.h>
#include <linux/mempool.h>
+#include <linux/syscalls.h>
#include <linux/ioctl.h>
#ifdef CONFIG_S390_SUPPORT
#include <linux/ioctl32.h>
@@ -937,8 +941,6 @@
struct zfcp_adapter {
- u32 common_magic; /* driver common magic */
- u32 specific_magic; /* struct specific magic */
struct list_head list; /* list of adapters */
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
@@ -956,14 +958,12 @@
u32 hardware_version; /* of FCP channel */
u8 serial_number[32]; /* of hardware */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
-
+ unsigned short scsi_host_no; /* Assigned host number */
unsigned char name[9];
struct list_head port_list_head; /* remote port list */
struct list_head port_remove_lh; /* head of ports to be
removed */
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 list_head fsf_req_list_head; /* head of FSF req list */
rwlock_t fsf_req_list_lock; /* lock for ops on list of
@@ -1003,9 +1003,13 @@
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 {
- u32 common_magic; /* driver wide common magic */
- u32 specific_magic; /* structure specific magic */
+ struct device sysfs_device; /* sysfs device */
struct list_head list; /* list of remote ports */
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
@@ -1020,37 +1024,36 @@
wwn_t wwnn; /* WWNN if known */
wwn_t wwpn; /* WWPN */
fc_id_t d_id; /* D_ID */
- scsi_lun_t max_scsi_lun; /* largest SCSI LUN */
u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */
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 {
- u32 common_magic; /* driver wide common magic */
- u32 specific_magic; /* structure specific magic */
+ struct device sysfs_device; /* sysfs device */
struct list_head list; /* list of logical units */
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
refcount drop to zero */
struct zfcp_port *port; /* remote port of 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 */
fcp_lun_t fcp_lun; /* own FCP_LUN */
u32 handle; /* handle assigned by FSF */
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
- struct device sysfs_device; /* sysfs device */
atomic_t scsi_add_work; /* used to synchronize */
wait_queue_head_t scsi_add_wq; /* wait for scsi_add_device */
};
/* FSF request */
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 zfcp_adapter *adapter; /* adapter request belongs to */
u8 sbal_number; /* nr of SBALs free for use */
@@ -1158,13 +1161,6 @@
#define ZFCP_INTERRUPTIBLE 1
#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
#define atomic_test_mask(mask, target) \
((atomic_read(target) & mask) == mask)
diff -urN linux-2.6/drivers/s390/scsi/zfcp_erp.c linux-2.6-s390/drivers/s390/scsi/zfcp_erp.c
--- linux-2.6/drivers/s390/scsi/zfcp_erp.c Thu Mar 11 03:55:23 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_erp.c Tue Mar 16 14:07:24 2004
@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_ERP_REVISION "$Revision: 1.44 $"
+#define ZFCP_ERP_REVISION "$Revision: 1.46 $"
#include "zfcp_ext.h"
@@ -1202,7 +1202,7 @@
* returns: 0 - there was an action to handle
* !0 - otherwise
*/
-static int
+int
zfcp_erp_async_handler(struct zfcp_erp_action *erp_action,
unsigned long set_mask)
{
@@ -1218,28 +1218,6 @@
}
/*
- * 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
* memory becoming avaliable,
* will trigger that this action will be continued
diff -urN linux-2.6/drivers/s390/scsi/zfcp_ext.h linux-2.6-s390/drivers/s390/scsi/zfcp_ext.h
--- linux-2.6/drivers/s390/scsi/zfcp_ext.h Thu Mar 11 03:55:23 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_ext.h Tue Mar 16 14:07:55 2004
@@ -31,7 +31,7 @@
#ifndef ZFCP_EXT_H
#define ZFCP_EXT_H
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_EXT_REVISION "$Revision: 1.45 $"
+#define ZFCP_EXT_REVISION "$Revision: 1.48 $"
#include "zfcp_def.h"
@@ -46,8 +46,6 @@
extern void zfcp_sysfs_port_remove_files(struct device *, u32);
extern int zfcp_sysfs_unit_create_files(struct device *);
extern void zfcp_sysfs_unit_remove_files(struct device *);
-extern void zfcp_sysfs_port_release(struct device *);
-extern void zfcp_sysfs_unit_release(struct device *);
/**************************** CONFIGURATION *********************************/
extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *,
@@ -158,7 +156,7 @@
extern int zfcp_erp_thread_setup(struct zfcp_adapter *);
extern int zfcp_erp_thread_kill(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 *);
diff -urN linux-2.6/drivers/s390/scsi/zfcp_fsf.c linux-2.6-s390/drivers/s390/scsi/zfcp_fsf.c
--- linux-2.6/drivers/s390/scsi/zfcp_fsf.c Thu Mar 11 03:55:36 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_fsf.c Tue Mar 16 14:08:08 2004
@@ -29,7 +29,7 @@
*/
/* 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.38 $"
#include "zfcp_ext.h"
@@ -771,6 +771,8 @@
static int
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;
if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
@@ -861,7 +863,13 @@
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;
}
@@ -1670,20 +1678,19 @@
"to a port with WWPN 0x%Lx connected "
"to the adapter %s\n", port->wwpn,
zfcp_get_busid_by_port(port));
- counter = 0;
- do {
- subtable = header->fsf_status_qual.halfword[counter++];
- rule = header->fsf_status_qual.halfword[counter++];
+ for (counter = 0; counter < 2; counter++) {
+ subtable = header->fsf_status_qual.halfword[counter * 2];
+ rule = header->fsf_status_qual.halfword[counter * 2 + 1];
switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
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);
break;
}
- } while (counter < 4);
+ }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -2036,20 +2043,19 @@
ZFCP_LOG_NORMAL("Access denied, cannot send ELS "
"(adapter: %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port), port->wwpn);
- counter = 0;
- do {
- subtable = header->fsf_status_qual.halfword[counter++];
- rule = header->fsf_status_qual.halfword[counter++];
+ for (counter = 0; counter < 2; counter++) {
+ subtable = header->fsf_status_qual.halfword[counter * 2];
+ rule = header->fsf_status_qual.halfword[counter * 2 + 1];
switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
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);
break;
}
- } while (counter < 4);
+ }
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -2114,7 +2120,8 @@
erp_action->fsf_req->erp_action = erp_action;
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 */
retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
@@ -2408,20 +2415,19 @@
ZFCP_LOG_NORMAL("Access denied, cannot open port "
"with WWPN 0x%Lx connected to the adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port));
- counter = 0;
- do {
- subtable = header->fsf_status_qual.halfword[counter++];
- rule = header->fsf_status_qual.halfword[counter++];
+ for (counter = 0; counter < 2; counter++) {
+ subtable = header->fsf_status_qual.halfword[counter * 2];
+ rule = header->fsf_status_qual.halfword[counter * 2 + 1];
switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
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);
break;
}
- } while (counter < 4);
+ }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
zfcp_erp_port_failed(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -2814,20 +2820,19 @@
"physical port with WWPN 0x%Lx connected to "
"the adapter %s\n", port->wwpn,
zfcp_get_busid_by_port(port));
- counter = 0;
- do {
- subtable = header->fsf_status_qual.halfword[counter++];
- rule = header->fsf_status_qual.halfword[counter++];
+ for (counter = 0; counter < 2; counter++) {
+ subtable = header->fsf_status_qual.halfword[counter * 2];
+ rule = header->fsf_status_qual.halfword[counter * 2 + 1];
switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
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);
break;
}
- } while (counter < 4);
+ }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -2956,8 +2961,8 @@
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->erp_action = erp_action;
- erp_action->fsf_req->qtcb->bottom.support.option =
- FSF_OPEN_LUN_SUPPRESS_BOXING;
+// erp_action->fsf_req->qtcb->bottom.support.option =
+// FSF_OPEN_LUN_UNSOLICITED_SENSE_DATA;
/* start QDIO request for this FSF request */
retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
@@ -2994,12 +2999,16 @@
zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
{
int retval = -EINVAL;
+ struct zfcp_adapter *adapter;
struct zfcp_unit *unit;
struct fsf_qtcb_header *header;
+ struct fsf_qtcb_bottom_support *bottom;
u16 subtable, rule, counter;
+ adapter = fsf_req->adapter;
unit = fsf_req->data.open_unit.unit;
header = &fsf_req->qtcb->header;
+ bottom = &fsf_req->qtcb->bottom.support;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't change unit status in our bookkeeping */
@@ -3021,7 +3030,7 @@
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) &header->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);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3034,7 +3043,7 @@
"to the adapter %s twice.\n",
unit->fcp_lun,
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_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3046,21 +3055,20 @@
"WWPN 0x%Lx connected to the adapter %s\n",
unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_unit(unit));
- counter = 0;
- do {
- subtable = header->fsf_status_qual.halfword[counter++];
- rule = header->fsf_status_qual.halfword[counter++];
+ for (counter = 0; counter < 2; counter++) {
+ subtable = header->fsf_status_qual.halfword[counter * 2];
+ rule = header->fsf_status_qual.halfword[counter * 2 + 1];
switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
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);
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);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3071,7 +3079,7 @@
"with WWPN 0x%Lx on the adapter %s "
"needs to be reopened\n",
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);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
@@ -3079,30 +3087,38 @@
case FSF_LUN_SHARING_VIOLATION :
ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n");
- ZFCP_LOG_NORMAL("error: FCP-LUN 0x%Lx at "
- "the remote port with WWPN 0x%Lx connected "
- "to the adapter %s "
- "is already owned by another operating system "
- "instance (LPAR or VM guest)\n",
- unit->fcp_lun,
- unit->port->wwpn,
- zfcp_get_busid_by_unit(unit));
subtable = header->fsf_status_qual.halfword[4];
rule = header->fsf_status_qual.halfword[5];
- switch (subtable) {
- case FSF_SQ_CFDC_SUBTABLE_OS:
- case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
- case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
- case FSF_SQ_CFDC_SUBTABLE_LUN:
- ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n",
- zfcp_act_subtable_type[subtable], rule);
- break;
+ if (rule == 0xFFFF) {
+ ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port "
+ "with WWPN 0x%Lx connected to the "
+ "adapter %s is already in use\n",
+ unit->fcp_lun,
+ unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+ } else {
+ switch (subtable) {
+ case FSF_SQ_CFDC_SUBTABLE_OS:
+ case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
+ case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
+ case FSF_SQ_CFDC_SUBTABLE_LUN:
+ ZFCP_LOG_NORMAL("Access to FCP-LUN 0x%Lx at the "
+ "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;
+ }
}
- ZFCP_LOG_NORMAL("Additional sense data is presented:\n");
+ ZFCP_LOG_DEBUG("status qualifier:\n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
(char *) &header->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");
zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -3118,7 +3134,7 @@
unit->fcp_lun,
unit->port->wwpn,
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");
zfcp_erp_unit_failed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -3131,7 +3147,7 @@
ZFCP_LOG_FLAGS(2,
"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* Re-establish link to port */
- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+ debug_text_event(adapter->erp_dbf, 1,
"fsf_sq_ltest");
zfcp_erp_port_reopen(unit->port, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -3140,7 +3156,7 @@
ZFCP_LOG_FLAGS(2,
"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */
- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+ debug_text_event(adapter->erp_dbf, 1,
"fsf_sq_ulp");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3148,27 +3164,41 @@
ZFCP_LOG_NORMAL
("bug: Wrong status qualifier 0x%x arrived.\n",
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:");
- debug_exception(fsf_req->adapter->erp_dbf, 0,
+ debug_exception(adapter->erp_dbf, 0,
&header->fsf_status_qual.word[0],
sizeof (u32));
}
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:
ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
/* save LUN handle assigned by FSF */
unit->handle = header->lun_handle;
ZFCP_LOG_TRACE("unit (FCP_LUN=0x%Lx) of remote port "
"(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->port->wwpn,
zfcp_get_busid_by_unit(unit),
- unit->handle);
+ unit->handle,
+ bottom->lun_access);
/* mark unit as open */
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
+ if (adapter->supported_features & FSF_FEATURE_CFDC)
+ unit->lun_access = bottom->lun_access;
retval = 0;
break;
@@ -3176,8 +3206,8 @@
ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
"(debug info 0x%x)\n",
header->fsf_status);
- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
- debug_exception(fsf_req->adapter->erp_dbf, 0,
+ debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:");
+ debug_exception(adapter->erp_dbf, 0,
&header->fsf_status, sizeof (u32));
break;
}
@@ -3863,20 +3893,19 @@
"remote port with WWPN 0x%Lx connected to the "
"adapter %s\n", unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_unit(unit));
- counter = 0;
- do {
- subtable = header->fsf_status_qual.halfword[counter++];
- rule = header->fsf_status_qual.halfword[counter++];
+ for (counter = 0; counter < 2; counter++) {
+ subtable = header->fsf_status_qual.halfword[counter * 2];
+ rule = header->fsf_status_qual.halfword[counter * 2 + 1];
switch (subtable) {
case FSF_SQ_CFDC_SUBTABLE_OS:
case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:
case FSF_SQ_CFDC_SUBTABLE_PORT_DID:
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);
break;
}
- } while (counter < 4);
+ }
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -4505,15 +4534,13 @@
int direction;
int retval = 0;
-#if 0
- if (!(adapter->features & FSF_FEATURE_CFDC)) {
+ if (!(adapter->supported_features & FSF_FEATURE_CFDC)) {
ZFCP_LOG_INFO(
"Adapter %s does not support control file\n",
zfcp_get_busid_by_adapter(adapter));
retval = -EOPNOTSUPP;
- goto no_act_support;
+ goto no_cfdc_support;
}
-#endif
switch (fsf_command) {
@@ -4595,6 +4622,7 @@
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
invalid_command:
+no_cfdc_support:
return retval;
}
@@ -4932,11 +4960,6 @@
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->fsf_command = fsf_cmd;
fsf_req->sbal_number = 1;
diff -urN linux-2.6/drivers/s390/scsi/zfcp_fsf.h linux-2.6-s390/drivers/s390/scsi/zfcp_fsf.h
--- linux-2.6/drivers/s390/scsi/zfcp_fsf.h Thu Mar 11 03:55:43 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_fsf.h Tue Mar 16 14:03:14 2004
@@ -198,18 +198,23 @@
/* channel features */
#define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001
#define FSF_FEATURE_CFDC 0x00000002
-#define FSF_FEATURE_SENSEDATA_REPLICATION 0x00000004
#define FSF_FEATURE_LOST_SAN_NOTIFICATION 0x00000008
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
/* option */
#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001
+#define FSF_OPEN_LUN_UNSOLICITED_SENSE_DATA 0x00000002
/* adapter types */
#define FSF_ADAPTER_TYPE_FICON 0x00000001
#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 */
#define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001
#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003
@@ -394,9 +399,10 @@
u64 res2;
u64 req_handle;
u32 service_class;
- u8 res3[3];
+ u8 res3[3];
u8 timeout;
- u8 res4[184];
+ u32 lun_access;
+ u8 res4[180];
u32 els1_length;
u32 els2_length;
u32 req_buf_length;
diff -urN linux-2.6/drivers/s390/scsi/zfcp_qdio.c linux-2.6-s390/drivers/s390/scsi/zfcp_qdio.c
--- linux-2.6/drivers/s390/scsi/zfcp_qdio.c Thu Mar 11 03:55:22 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_qdio.c Tue Mar 16 14:03:14 2004
@@ -28,7 +28,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_QDIO_C_REVISION "$Revision: 1.13 $"
+#define ZFCP_QDIO_C_REVISION "$Revision: 1.15 $"
#include "zfcp_ext.h"
@@ -502,17 +502,6 @@
/* valid request id and thus (hopefully :) valid fsf_req address */
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)) {
ZFCP_LOG_NORMAL("bug: An inbound FSF acknowledgement was not "
"correct (debug info 0x%lx, 0x%lx, 0%lx) \n",
@@ -665,7 +654,7 @@
/**
* zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue
- * with zero from
+ * with zero from
*/
static inline int
zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last)
diff -urN linux-2.6/drivers/s390/scsi/zfcp_scsi.c linux-2.6-s390/drivers/s390/scsi/zfcp_scsi.c
--- linux-2.6/drivers/s390/scsi/zfcp_scsi.c Thu Mar 11 03:55:26 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_scsi.c Tue Mar 16 14:03:14 2004
@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_SCSI_REVISION "$Revision: 1.52 $"
+#define ZFCP_SCSI_REVISION "$Revision: 1.57 $"
#include <linux/blkdev.h>
@@ -55,7 +55,7 @@
struct zfcp_data zfcp_data = {
.scsi_host_template = {
name: ZFCP_NAME,
- proc_name: "dummy",
+ proc_name: "zfcp",
proc_info: NULL,
detect: NULL,
slave_alloc: zfcp_scsi_slave_alloc,
@@ -796,12 +796,17 @@
(unsigned long) adapter->scsi_host);
/* tell the SCSI stack some characteristics of this adapter */
- adapter->scsi_host->max_id = adapter->max_scsi_id + 1;
- adapter->scsi_host->max_lun = adapter->max_scsi_lun + 1;
+ adapter->scsi_host->max_id = 1;
+ adapter->scsi_host->max_lun = 1;
adapter->scsi_host->max_channel = 0;
adapter->scsi_host->unique_id = unique_id++; /* FIXME */
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
* hostdata field of SCSI host data structure
*/
@@ -835,6 +840,7 @@
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
+ adapter->scsi_host_no = 0;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return;
@@ -850,68 +856,32 @@
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
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- *
- * "wwpn" attribute of a scsi device. Displays wwpn of the port
- * belonging to a scsi device.
- */
-static ssize_t
-zfcp_sysfs_wwpn_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->port->wwpn);
-}
-
-static DEVICE_ATTR(wwpn, S_IRUGO, zfcp_sysfs_wwpn_show, NULL);
-
-/**
- * zfcp_sysfs_fcp_lun_show - display fcp lun of scsi device
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- *
- * "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);
+ * ZFCP_DEFINE_SCSI_ATTR
+ * @_name: name of show attribute
+ * @_format: format string
+ * @_value: value to print
+ *
+ * Generates attribute for a unit.
+ */
+#define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value) \
+static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
+ char *buf) \
+{ \
+ struct scsi_device *sdev; \
+ struct zfcp_unit *unit; \
+ \
+ sdev = to_scsi_device(dev); \
+ unit = sdev->hostdata; \
+ return sprintf(buf, _format, _value); \
+} \
+ \
+static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
+
+ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", zfcp_get_busid_by_unit(unit));
+ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);
+ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);
static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
diff -urN linux-2.6/drivers/s390/scsi/zfcp_sysfs_adapter.c linux-2.6-s390/drivers/s390/scsi/zfcp_sysfs_adapter.c
--- linux-2.6/drivers/s390/scsi/zfcp_sysfs_adapter.c Thu Mar 11 03:55:21 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_sysfs_adapter.c Tue Mar 16 14:03:14 2004
@@ -26,7 +26,7 @@
* 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 "zfcp_ext.h"
@@ -75,6 +75,7 @@
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
adapter->hardware_version);
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
@@ -100,30 +101,6 @@
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
* @dev: pointer to belonging device
* @buf: pointer to input buffer
@@ -219,9 +196,7 @@
zfcp_erp_port_shutdown(port, 0);
zfcp_erp_wait(adapter);
zfcp_port_put(port);
- zfcp_sysfs_port_remove_files(&port->sysfs_device,
- atomic_read(&port->status));
- device_unregister(&port->sysfs_device);
+ zfcp_port_dequeue(port);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
diff -urN linux-2.6/drivers/s390/scsi/zfcp_sysfs_port.c linux-2.6-s390/drivers/s390/scsi/zfcp_sysfs_port.c
--- linux-2.6/drivers/s390/scsi/zfcp_sysfs_port.c Thu Mar 11 03:55:44 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_sysfs_port.c Tue Mar 16 14:03:14 2004
@@ -26,7 +26,7 @@
* 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/module.h>
@@ -37,20 +37,6 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
/**
- * zfcp_sysfs_port_release - gets called when a struct device port is released
- * @dev: pointer to belonging device
- */
-void
-zfcp_sysfs_port_release(struct device *dev)
-{
- struct zfcp_port *port;
-
- port = dev_get_drvdata(dev);
- zfcp_port_dequeue(port);
- return;
-}
-
-/**
* ZFCP_DEFINE_PORT_ATTR
* @_name: name of show attribute
* @_format: format string
@@ -112,7 +98,6 @@
zfcp_erp_unit_reopen(unit, 0);
zfcp_erp_wait(unit->port->adapter);
- wait_event(unit->scsi_add_wq, atomic_read(&unit->scsi_add_work) == 0);
zfcp_unit_put(unit);
out:
up(&zfcp_data.config_sema);
@@ -168,8 +153,7 @@
zfcp_erp_unit_shutdown(unit, 0);
zfcp_erp_wait(unit->port->adapter);
zfcp_unit_put(unit);
- zfcp_sysfs_unit_remove_files(&unit->sysfs_device);
- device_unregister(&unit->sysfs_device);
+ zfcp_unit_dequeue(unit);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
diff -urN linux-2.6/drivers/s390/scsi/zfcp_sysfs_unit.c linux-2.6-s390/drivers/s390/scsi/zfcp_sysfs_unit.c
--- linux-2.6/drivers/s390/scsi/zfcp_sysfs_unit.c Thu Mar 11 03:56:03 2004
+++ linux-2.6-s390/drivers/s390/scsi/zfcp_sysfs_unit.c Tue Mar 16 14:03:14 2004
@@ -26,7 +26,7 @@
* 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/module.h>
@@ -37,20 +37,6 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
/**
- * zfcp_sysfs_unit_release - gets called when a struct device unit is released
- * @dev: pointer to belonging device
- */
-void
-zfcp_sysfs_unit_release(struct device *dev)
-{
- struct zfcp_unit *unit;
-
- unit = dev_get_drvdata(dev);
- zfcp_unit_dequeue(unit);
- return;
-}
-
-/**
* ZFCP_DEFINE_UNIT_ATTR
* @_name: name of show attribute
* @_format: format string
On Tue, 2004-03-16 at 08:51, Martin Schwidefsky wrote:
> +ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", zfcp_get_busid_by_unit(unit));
> +ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);
> +ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);
These attributes all properly belong in the fibrechannel transport
class, could you look at moving them over, please.
James
> > +ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", zfcp_get_busid_by_unit(unit));
> > +ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);
> > +ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);
> These attributes all properly belong in the fibrechannel transport
> class, could you look at moving them over, please.
We can certainly do that for the wwpn (->port_name). For the fcp_lun we
would need to extend the fc transport class.
The hba_id doesn't belong to the fc transport class at all. It's just
the busid of our host adapter, so that we can identify it uniquely.
By the way, Christoph asked why we have the zfcp lldd in
drivers/s390/scsi. This is just for historical reasons. If you don't
mind seeing a ~32000 lines patch we can move it to drivers/scsi/zfcp.
Heiko
Hi Greg,
> This is not ok. If you have to do something like this, I really suggest
> that you not allow the "sub modules" be able to unload before the upper
> module can. In fact, why would you want to do such a thing?
How do sub modules help with the release function problem? The unit/port
objects get unregistered in zfcp_unit_dequeue. This happens e.g. when
a zfcp adapter gets removed because of a detach. After the last zfcp
adapter got removed the module is in principle ready to be removed.
Now there are two cases. 1) The module count of the zfcp module (or one
of the non-existent sub-modules) is NOT increase because of the outstanding
call to the release function. It obvious that the release function can't
be part of the zfcp module(s) in this case. 2) The module count of the
zfcp module(s) is elevated because of the outstanding call to release.
Who does the module_put in this case? The release function only can do it
if it is not part of ANY of the modules. If it is part of a zfcp module
the cpu doing the module_put might not be able to get out of the release
function fast enough before another cpu has removed the module(s)
(including the sub-modules).
Did I miss something ?
> I still really strongly object to this patch. If it's a scsi problem,
> fix it there, but odds are it's your driver's problem as no other scsi
> driver needs this.
If we can move the port/unit objects to the scsi mid layer that would
"solve" the problem for the zfcp module. But the problem itself doesn't
go away. It's just moved one step up the ladder.
blue skies,
Martin
Linux/390 Design & Development, IBM Deutschland Entwicklung GmbH
Sch?naicherstr. 220, D-71032 B?blingen, Telefon: 49 - (0)7031 - 16-2247
E-Mail: [email protected]
Hi Greg,
> > This is not ok. If you have to do something like this, I really suggest
> > that you not allow the "sub modules" be able to unload before the upper
> > module can. In fact, why would you want to do such a thing?
> How do sub modules help with the release function problem? The unit/port
> objects get unregistered in zfcp_unit_dequeue. This happens e.g. when
> a zfcp adapter gets removed because of a detach. After the last zfcp
> adapter got removed the module is in principle ready to be removed.
> Now there are two cases. 1) The module count of the zfcp module (or one
> of the non-existent sub-modules) is NOT increase because of the outstanding
> call to the release function. It obvious that the release function can't
> be part of the zfcp module(s) in this case. 2) The module count of the
> zfcp module(s) is elevated because of the outstanding call to release.
> Who does the module_put in this case? The release function only can do it
> if it is not part of ANY of the modules. If it is part of a zfcp module
> the cpu doing the module_put might not be able to get out of the release
> function fast enough before another cpu has removed the module(s)
> (including the sub-modules).
> Did I miss something ?
>
> > I still really strongly object to this patch. If it's a scsi problem,
> > fix it there, but odds are it's your driver's problem as no other scsi
> > driver needs this.
> If we can move the port/unit objects to the scsi mid layer that would
> "solve" the problem for the zfcp module. But the problem itself doesn't
> go away. It's just moved one step up the ladder.
Did I manage to convince you or are you just fed up with the discussion?
I'll ask because the zfcp patches are still pending and I want to get this
issue resolved before the next try to get them integrated.
blue skies,
Martin
Linux/390 Design & Development, IBM Deutschland Entwicklung GmbH
Sch?naicherstr. 220, D-71032 B?blingen, Telefon: 49 - (0)7031 - 16-2247
E-Mail: [email protected]
On Mon, Mar 29, 2004 at 12:03:13PM +0200, Martin Schwidefsky wrote:
>
> Did I manage to convince you or are you just fed up with the discussion?
Heh, I'm still not convinced :)
> I'll ask because the zfcp patches are still pending and I want to get this
> issue resolved before the next try to get them integrated.
I think you need to talk to the scsi people, as kfree() should _never_
need to be set as the release function. There's something just wrong
with the design if that is necessary.
thanks,
greg k-h