summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c26
-rw-r--r--drivers/s390/block/dasd_3990_erp.c2
-rw-r--r--drivers/s390/block/dasd_alias.c5
-rw-r--r--drivers/s390/block/dasd_diag.c5
-rw-r--r--drivers/s390/block/dasd_eckd.c47
-rw-r--r--drivers/s390/block/dasd_eer.c4
-rw-r--r--drivers/s390/block/dasd_erp.c4
-rw-r--r--drivers/s390/block/dasd_fba.c9
-rw-r--r--drivers/s390/block/dasd_int.h11
-rw-r--r--drivers/s390/block/dasd_ioctl.c24
-rw-r--r--drivers/s390/block/xpram.c65
-rw-r--r--drivers/s390/char/Kconfig10
-rw-r--r--drivers/s390/char/Makefile1
-rw-r--r--drivers/s390/char/monreader.c2
-rw-r--r--drivers/s390/char/sclp.h4
-rw-r--r--drivers/s390/char/sclp_async.c224
-rw-r--r--drivers/s390/char/tape_34xx.c2
-rw-r--r--drivers/s390/char/tape_3590.c4
-rw-r--r--drivers/s390/char/tape_block.c12
-rw-r--r--drivers/s390/char/tape_core.c18
-rw-r--r--drivers/s390/char/tape_std.c2
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/vmur.c19
-rw-r--r--drivers/s390/char/zcore.c2
-rw-r--r--drivers/s390/cio/Makefile2
-rw-r--r--drivers/s390/cio/chp.c3
-rw-r--r--drivers/s390/cio/chsc.h24
-rw-r--r--drivers/s390/cio/cio.c56
-rw-r--r--drivers/s390/cio/cio.h4
-rw-r--r--drivers/s390/cio/css.c32
-rw-r--r--drivers/s390/cio/device.c172
-rw-r--r--drivers/s390/cio/device_fsm.c22
-rw-r--r--drivers/s390/cio/qdio.h4
-rw-r--r--drivers/s390/cio/qdio_debug.c55
-rw-r--r--drivers/s390/cio/qdio_main.c4
-rw-r--r--drivers/s390/cio/scsw.c843
-rw-r--r--drivers/s390/crypto/ap_bus.c17
-rw-r--r--drivers/s390/kvm/kvm_virtio.c8
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/net/ctcm_main.c11
-rw-r--r--drivers/s390/net/lcs.c8
-rw-r--r--drivers/s390/net/netiucv.c16
-rw-r--r--drivers/s390/net/qeth_core.h10
-rw-r--r--drivers/s390/net/qeth_core_main.c114
-rw-r--r--drivers/s390/net/qeth_core_sys.c2
-rw-r--r--drivers/s390/net/qeth_l2_main.c48
-rw-r--r--drivers/s390/net/qeth_l3_main.c52
-rw-r--r--drivers/s390/net/smsgiucv.c6
-rw-r--r--drivers/s390/scsi/zfcp_aux.c288
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c94
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c544
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h175
-rw-r--r--drivers/s390/scsi/zfcp_def.h183
-rw-r--r--drivers/s390/scsi/zfcp_erp.c155
-rw-r--r--drivers/s390/scsi/zfcp_ext.h102
-rw-r--r--drivers/s390/scsi/zfcp_fc.c176
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c635
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h3
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c369
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c73
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c34
61 files changed, 2165 insertions, 2687 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 3f62dd50bbb..e109da4583a 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -669,14 +669,14 @@ static void dasd_profile_end(struct dasd_block *block,
* memory and 2) dasd_smalloc_request uses the static ccw memory
* that gets allocated for each device.
*/
-struct dasd_ccw_req *dasd_kmalloc_request(char *magic, int cplength,
+struct dasd_ccw_req *dasd_kmalloc_request(int magic, int cplength,
int datasize,
struct dasd_device *device)
{
struct dasd_ccw_req *cqr;
/* Sanity checks */
- BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+ BUG_ON(datasize > PAGE_SIZE ||
(cplength*sizeof(struct ccw1)) > PAGE_SIZE);
cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC);
@@ -700,14 +700,13 @@ struct dasd_ccw_req *dasd_kmalloc_request(char *magic, int cplength,
return ERR_PTR(-ENOMEM);
}
}
- strncpy((char *) &cqr->magic, magic, 4);
- ASCEBC((char *) &cqr->magic, 4);
+ cqr->magic = magic;
set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
dasd_get_device(device);
return cqr;
}
-struct dasd_ccw_req *dasd_smalloc_request(char *magic, int cplength,
+struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
int datasize,
struct dasd_device *device)
{
@@ -717,7 +716,7 @@ struct dasd_ccw_req *dasd_smalloc_request(char *magic, int cplength,
int size;
/* Sanity checks */
- BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+ BUG_ON(datasize > PAGE_SIZE ||
(cplength*sizeof(struct ccw1)) > PAGE_SIZE);
size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
@@ -744,8 +743,7 @@ struct dasd_ccw_req *dasd_smalloc_request(char *magic, int cplength,
cqr->data = data;
memset(cqr->data, 0, datasize);
}
- strncpy((char *) &cqr->magic, magic, 4);
- ASCEBC((char *) &cqr->magic, 4);
+ cqr->magic = magic;
set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
dasd_get_device(device);
return cqr;
@@ -899,9 +897,6 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
switch (rc) {
case 0:
cqr->status = DASD_CQR_IN_IO;
- DBF_DEV_EVENT(DBF_DEBUG, device,
- "start_IO: request %p started successful",
- cqr);
break;
case -EBUSY:
DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
@@ -1699,8 +1694,11 @@ static void __dasd_process_request_queue(struct dasd_block *block)
* for that. State DASD_STATE_ONLINE is normal block device
* operation.
*/
- if (basedev->state < DASD_STATE_READY)
+ if (basedev->state < DASD_STATE_READY) {
+ while ((req = blk_fetch_request(block->request_queue)))
+ __blk_end_request_all(req, -EIO);
return;
+ }
/* Now we try to fetch requests from the request queue */
while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) {
if (basedev->features & DASD_FEATURE_READONLY &&
@@ -2530,7 +2528,7 @@ EXPORT_SYMBOL_GPL(dasd_generic_restore_device);
static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
void *rdc_buffer,
int rdc_buffer_size,
- char *magic)
+ int magic)
{
struct dasd_ccw_req *cqr;
struct ccw1 *ccw;
@@ -2561,7 +2559,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
}
-int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
+int dasd_generic_read_dev_chars(struct dasd_device *device, int magic,
void *rdc_buffer, int rdc_buffer_size)
{
int ret;
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 27991b69205..e8ff7b0c961 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -7,7 +7,7 @@
*
*/
-#define KMSG_COMPONENT "dasd"
+#define KMSG_COMPONENT "dasd-eckd"
#include <linux/timer.h>
#include <linux/slab.h>
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 5b7bbc87593..70a008c0052 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -5,7 +5,7 @@
* Author(s): Stefan Weinhuber <wein@de.ibm.com>
*/
-#define KMSG_COMPONENT "dasd"
+#define KMSG_COMPONENT "dasd-eckd"
#include <linux/list.h>
#include <asm/ebcdic.h>
@@ -379,8 +379,7 @@ static int read_unit_address_configuration(struct dasd_device *device,
int rc;
unsigned long flags;
- cqr = dasd_kmalloc_request("ECKD",
- 1 /* PSF */ + 1 /* RSSD */ ,
+ cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data)),
device);
if (IS_ERR(cqr))
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 644086ba2ed..4e49b4a6c88 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -8,7 +8,7 @@
*
*/
-#define KMSG_COMPONENT "dasd"
+#define KMSG_COMPONENT "dasd-diag"
#include <linux/stddef.h>
#include <linux/kernel.h>
@@ -523,8 +523,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
/* Build the request */
datasize = sizeof(struct dasd_diag_req) +
count*sizeof(struct dasd_diag_bio);
- cqr = dasd_smalloc_request(dasd_diag_discipline.name, 0,
- datasize, memdev);
+ cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, datasize, memdev);
if (IS_ERR(cqr))
return cqr;
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index c11770f5b36..a1ce573648a 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -10,7 +10,7 @@
* Author.........: Nigel Hislop <hislop_nigel@emc.com>
*/
-#define KMSG_COMPONENT "dasd"
+#define KMSG_COMPONENT "dasd-eckd"
#include <linux/stddef.h>
#include <linux/kernel.h>
@@ -730,7 +730,8 @@ static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
struct dasd_ccw_req *cqr;
struct ccw1 *ccw;
- cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */, ciw->count,
+ device);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
@@ -934,8 +935,7 @@ static int dasd_eckd_read_features(struct dasd_device *device)
struct dasd_eckd_private *private;
private = (struct dasd_eckd_private *) device->private;
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- 1 /* PSF */ + 1 /* RSSD */ ,
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data) +
sizeof(struct dasd_rssd_features)),
device);
@@ -998,7 +998,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,
struct dasd_psf_ssc_data *psf_ssc_data;
struct ccw1 *ccw;
- cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ ,
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ ,
sizeof(struct dasd_psf_ssc_data),
device);
@@ -1149,8 +1149,8 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
goto out_err3;
/* Read Device Characteristics */
- rc = dasd_generic_read_dev_chars(device, "ECKD", &private->rdc_data,
- 64);
+ rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
+ &private->rdc_data, 64);
if (rc) {
DBF_EVENT(DBF_WARNING,
"Read device characteristics failed, rc=%d for "
@@ -1217,8 +1217,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
cplength = 8;
datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data);
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- cplength, datasize, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device);
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
@@ -1499,8 +1498,7 @@ dasd_eckd_format_device(struct dasd_device * device,
return ERR_PTR(-EINVAL);
}
/* Allocate the format ccw request. */
- fcp = dasd_smalloc_request(dasd_eckd_discipline.name,
- cplength, datasize, device);
+ fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device);
if (IS_ERR(fcp))
return fcp;
@@ -1783,8 +1781,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
datasize += count*sizeof(struct LO_eckd_data);
}
/* Allocate the ccw request. */
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- cplength, datasize, startdev);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize,
+ startdev);
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
@@ -1948,8 +1946,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
cidaw * sizeof(unsigned long long);
/* Allocate the ccw request. */
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- cplength, datasize, startdev);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize,
+ startdev);
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
@@ -2249,8 +2247,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
/* Allocate the ccw request. */
itcw_size = itcw_calc_size(0, ctidaw, 0);
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- 0, itcw_size, startdev);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev);
if (IS_ERR(cqr))
return cqr;
@@ -2557,8 +2554,7 @@ dasd_eckd_release(struct dasd_device *device)
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- 1, 32, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate initialization request");
@@ -2600,8 +2596,7 @@ dasd_eckd_reserve(struct dasd_device *device)
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- 1, 32, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate initialization request");
@@ -2642,8 +2637,7 @@ dasd_eckd_steal_lock(struct dasd_device *device)
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- 1, 32, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate initialization request");
@@ -2681,8 +2675,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp)
struct ccw1 *ccw;
int rc;
- cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
- 1 /* PSF */ + 1 /* RSSD */ ,
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data) +
sizeof(struct dasd_rssd_perf_stats_t)),
device);
@@ -2828,7 +2821,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
}
/* setup CCWs for PSF + RSSD */
- cqr = dasd_smalloc_request("ECKD", 2 , 0, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate initialization request");
@@ -3254,7 +3247,7 @@ int dasd_eckd_restore_device(struct dasd_device *device)
/* Read Device Characteristics */
memset(&private->rdc_data, 0, sizeof(private->rdc_data));
- rc = dasd_generic_read_dev_chars(device, "ECKD",
+ rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
&private->rdc_data, 64);
if (rc) {
DBF_EVENT(DBF_WARNING,
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index c24c8c30380..d96039eae59 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -6,7 +6,7 @@
* Author(s): Stefan Weinhuber <wein@de.ibm.com>
*/
-#define KMSG_COMPONENT "dasd"
+#define KMSG_COMPONENT "dasd-eckd"
#include <linux/init.h>
#include <linux/fs.h>
@@ -464,7 +464,7 @@ int dasd_eer_enable(struct dasd_device *device)
if (!device->discipline || strcmp(device->discipline->name, "ECKD"))
return -EPERM; /* FIXME: -EMEDIUMTYPE ? */
- cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */,
+ cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* SNSS */,
SNSS_DATA_SIZE, device);
if (IS_ERR(cqr))
return -ENOMEM;
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index cb8f9cef742..7656384a811 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -99,8 +99,8 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr)
cqr->lpm = LPM_ANYPATH;
cqr->status = DASD_CQR_FILLED;
} else {
- dev_err(&device->cdev->dev,
- "default ERP has run out of retries and failed\n");
+ pr_err("%s: default ERP has run out of retries and failed\n",
+ dev_name(&device->cdev->dev));
cqr->status = DASD_CQR_FAILED;
cqr->stopclk = get_clock();
}
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 31849ad5e59..f245377e8e2 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -5,7 +5,7 @@
* Copyright IBM Corp. 1999, 2009
*/
-#define KMSG_COMPONENT "dasd"
+#define KMSG_COMPONENT "dasd-fba"
#include <linux/stddef.h>
#include <linux/kernel.h>
@@ -152,8 +152,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
block->base = device;
/* Read Device Characteristics */
- rc = dasd_generic_read_dev_chars(device, "FBA ", &private->rdc_data,
- 32);
+ rc = dasd_generic_read_dev_chars(device, DASD_FBA_MAGIC,
+ &private->rdc_data, 32);
if (rc) {
DBF_EVENT(DBF_WARNING, "Read device characteristics returned "
"error %d for device: %s",
@@ -305,8 +305,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
datasize += (count - 1)*sizeof(struct LO_fba_data);
}
/* Allocate the ccw request. */
- cqr = dasd_smalloc_request(dasd_fba_discipline.name,
- cplength, datasize, memdev);
+ cqr = dasd_smalloc_request(DASD_FBA_MAGIC, cplength, datasize, memdev);
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index b699ca356ac..5e47a1ee52b 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -59,6 +59,11 @@
#include <asm/dasd.h>
#include <asm/idals.h>
+/* DASD discipline magic */
+#define DASD_ECKD_MAGIC 0xC5C3D2C4
+#define DASD_DIAG_MAGIC 0xC4C9C1C7
+#define DASD_FBA_MAGIC 0xC6C2C140
+
/*
* SECTION: Type definitions
*/
@@ -540,9 +545,9 @@ extern struct block_device_operations dasd_device_operations;
extern struct kmem_cache *dasd_page_cache;
struct dasd_ccw_req *
-dasd_kmalloc_request(char *, int, int, struct dasd_device *);
+dasd_kmalloc_request(int , int, int, struct dasd_device *);
struct dasd_ccw_req *
-dasd_smalloc_request(char *, int, int, struct dasd_device *);
+dasd_smalloc_request(int , int, int, struct dasd_device *);
void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
@@ -587,7 +592,7 @@ void dasd_generic_handle_state_change(struct dasd_device *);
int dasd_generic_pm_freeze(struct ccw_device *);
int dasd_generic_restore_device(struct ccw_device *);
-int dasd_generic_read_dev_chars(struct dasd_device *, char *, void *, int);
+int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
char *dasd_get_sense(struct irb *);
/* externals in dasd_devmap.c */
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index df918ef2796..f756a1b0c57 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -98,8 +98,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block)
if (!capable (CAP_SYS_ADMIN))
return -EACCES;
- dev_info(&base->cdev->dev, "The DASD has been put in the quiesce "
- "state\n");
+ pr_info("%s: The DASD has been put in the quiesce "
+ "state\n", dev_name(&base->cdev->dev));
spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
base->stopped |= DASD_STOPPED_QUIESCE;
spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
@@ -119,8 +119,8 @@ static int dasd_ioctl_resume(struct dasd_block *block)
if (!capable (CAP_SYS_ADMIN))
return -EACCES;
- dev_info(&base->cdev->dev, "I/O operations have been resumed "
- "on the DASD\n");
+ pr_info("%s: I/O operations have been resumed "
+ "on the DASD\n", dev_name(&base->cdev->dev));
spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
base->stopped &= ~DASD_STOPPED_QUIESCE;
spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
@@ -146,8 +146,8 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
return -EPERM;
if (base->state != DASD_STATE_BASIC) {
- dev_warn(&base->cdev->dev,
- "The DASD cannot be formatted while it is enabled\n");
+ pr_warning("%s: The DASD cannot be formatted while it is "
+ "enabled\n", dev_name(&base->cdev->dev));
return -EBUSY;
}
@@ -175,9 +175,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
dasd_sfree_request(cqr, cqr->memdev);
if (rc) {
if (rc != -ERESTARTSYS)
- dev_err(&base->cdev->dev,
- "Formatting unit %d failed with "
- "rc=%d\n", fdata->start_unit, rc);
+ pr_err("%s: Formatting unit %d failed with "
+ "rc=%d\n", dev_name(&base->cdev->dev),
+ fdata->start_unit, rc);
return rc;
}
fdata->start_unit++;
@@ -204,9 +204,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
return -EFAULT;
if (bdev != bdev->bd_contains) {
- dev_warn(&block->base->cdev->dev,
- "The specified DASD is a partition and cannot be "
- "formatted\n");
+ pr_warning("%s: The specified DASD is a partition and cannot "
+ "be formatted\n",
+ dev_name(&block->base->cdev->dev));
return -EINVAL;
}
return dasd_format(block, &fdata);
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index db442cd6621..ee604e92a5f 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -42,7 +42,6 @@
#include <linux/suspend.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
-#include <asm/checksum.h>
#define XPRAM_NAME "xpram"
#define XPRAM_DEVS 1 /* one partition */
@@ -51,7 +50,6 @@
typedef struct {
unsigned int size; /* size of xpram segment in pages */
unsigned int offset; /* start page of xpram segment */
- unsigned int csum; /* partition checksum for suspend */
} xpram_device_t;
static xpram_device_t xpram_devices[XPRAM_MAX_DEVS];
@@ -387,58 +385,6 @@ out:
}
/*
- * Save checksums for all partitions.
- */
-static int xpram_save_checksums(void)
-{
- unsigned long mem_page;
- int rc, i;
-
- rc = 0;
- mem_page = (unsigned long) __get_free_page(GFP_KERNEL);
- if (!mem_page)
- return -ENOMEM;
- for (i = 0; i < xpram_devs; i++) {
- rc = xpram_page_in(mem_page, xpram_devices[i].offset);
- if (rc)
- goto fail;
- xpram_devices[i].csum = csum_partial((const void *) mem_page,
- PAGE_SIZE, 0);
- }
-fail:
- free_page(mem_page);
- return rc ? -ENXIO : 0;
-}
-
-/*
- * Verify checksums for all partitions.
- */
-static int xpram_validate_checksums(void)
-{
- unsigned long mem_page;
- unsigned int csum;
- int rc, i;
-
- rc = 0;
- mem_page = (unsigned long) __get_free_page(GFP_KERNEL);
- if (!mem_page)
- return -ENOMEM;
- for (i = 0; i < xpram_devs; i++) {
- rc = xpram_page_in(mem_page, xpram_devices[i].offset);
- if (rc)
- goto fail;
- csum = csum_partial((const void *) mem_page, PAGE_SIZE, 0);
- if (xpram_devices[i].csum != csum) {
- rc = -EINVAL;
- goto fail;
- }
- }
-fail:
- free_page(mem_page);
- return rc ? -ENXIO : 0;
-}
-
-/*
* Resume failed: Print error message and call panic.
*/
static void xpram_resume_error(const char *message)
@@ -458,21 +404,10 @@ static int xpram_restore(struct device *dev)
xpram_resume_error("xpram disappeared");
if (xpram_pages != xpram_highest_page_index() + 1)
xpram_resume_error("Size of xpram changed");
- if (xpram_validate_checksums())
- xpram_resume_error("Data of xpram changed");
return 0;
}
-/*
- * Save necessary state in suspend.
- */
-static int xpram_freeze(struct device *dev)
-{
- return xpram_save_checksums();
-}
-
static struct dev_pm_ops xpram_pm_ops = {
- .freeze = xpram_freeze,
.restore = xpram_restore,
};
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 0769ced52db..4e34d3686c2 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -82,6 +82,16 @@ config SCLP_CPI
You should only select this option if you know what you are doing,
need this feature and intend to run your kernel in LPAR.
+config SCLP_ASYNC
+ tristate "Support for Call Home via Asynchronous SCLP Records"
+ depends on S390
+ help
+ This option enables the call home function, which is able to inform
+ the service element and connected organisations about a kernel panic.
+ You should only select this option if you know what you are doing,
+ want for inform other people about your kernel panics,
+ need this feature and intend to run your kernel in LPAR.
+
config S390_TAPE
tristate "S/390 tape device support"
depends on CCW
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index 7e73e39a174..efb500ab66c 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o
obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
+obj-$(CONFIG_SCLP_ASYNC) += sclp_async.o
obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o
obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 3234e90bd7f..89ece1c235a 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -581,7 +581,7 @@ static int __init mon_init(void)
monreader_device->release = (void (*)(struct device *))kfree;
rc = device_register(monreader_device);
if (rc) {
- kfree(monreader_device);
+ put_device(monreader_device);
goto out_driver;
}
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 60e7cb07095..6bb5a6bdfab 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -27,6 +27,7 @@
#define EVTYP_VT220MSG 0x1A
#define EVTYP_CONFMGMDATA 0x04
#define EVTYP_SDIAS 0x1C
+#define EVTYP_ASYNC 0x0A
#define EVTYP_OPCMD_MASK 0x80000000
#define EVTYP_MSG_MASK 0x40000000
@@ -38,6 +39,7 @@
#define EVTYP_VT220MSG_MASK 0x00000040
#define EVTYP_CONFMGMDATA_MASK 0x10000000
#define EVTYP_SDIAS_MASK 0x00000010
+#define EVTYP_ASYNC_MASK 0x00400000
#define GNRLMSGFLGS_DOM 0x8000
#define GNRLMSGFLGS_SNDALRM 0x4000
@@ -85,12 +87,12 @@ struct sccb_header {
} __attribute__((packed));
extern u64 sclp_facilities;
-
#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
#define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL)
#define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL)
+
struct gds_subvector {
u8 length;
u8 key;
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
new file mode 100644
index 00000000000..daaec185ed3
--- /dev/null
+++ b/drivers/s390/char/sclp_async.c
@@ -0,0 +1,224 @@
+/*
+ * Enable Asynchronous Notification via SCLP.
+ *
+ * Copyright IBM Corp. 2009
+ * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/kmod.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include <linux/utsname.h>
+#include "sclp.h"
+
+static int callhome_enabled;
+static struct sclp_req *request;
+static struct sclp_async_sccb *sccb;
+static int sclp_async_send_wait(char *message);
+static struct ctl_table_header *callhome_sysctl_header;
+static DEFINE_SPINLOCK(sclp_async_lock);
+static char nodename[64];
+#define SCLP_NORMAL_WRITE 0x00
+
+struct async_evbuf {
+ struct evbuf_header header;
+ u64 reserved;
+ u8 rflags;
+ u8 empty;
+ u8 rtype;
+ u8 otype;
+ char comp_id[12];
+ char data[3000]; /* there is still some space left */
+} __attribute__((packed));
+
+struct sclp_async_sccb {
+ struct sccb_header header;
+ struct async_evbuf evbuf;
+} __attribute__((packed));
+
+static struct sclp_register sclp_async_register = {
+ .send_mask = EVTYP_ASYNC_MASK,
+};
+
+static int call_home_on_panic(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ strncat(data, nodename, strlen(nodename));
+ sclp_async_send_wait(data);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block call_home_panic_nb = {
+ .notifier_call = call_home_on_panic,
+ .priority = INT_MAX,
+};
+
+static int proc_handler_callhome(ctl_table *ctl, int write, struct file *filp,
+ void __user *buffer, size_t *count,
+ loff_t *ppos)
+{
+ unsigned long val;
+ int len, rc;
+ char buf[2];
+
+ if (!*count | (*ppos && !write)) {
+ *count = 0;
+ return 0;
+ }
+ if (!write) {
+ len = sprintf(buf, "%d\n", callhome_enabled);
+ buf[len] = '\0';
+ rc = copy_to_user(buffer, buf, sizeof(buf));
+ if (rc != 0)
+ return -EFAULT;
+ } else {
+ len = *count;
+ rc = copy_from_user(buf, buffer, sizeof(buf));
+ if (rc != 0)
+ return -EFAULT;
+ if (strict_strtoul(buf, 0, &val) != 0)
+ return -EINVAL;
+ if (val != 0 && val != 1)
+ return -EINVAL;
+ callhome_enabled = val;
+ }
+ *count = len;
+ *ppos += len;
+ return 0;
+}
+
+static struct ctl_table callhome_table[] = {
+ {
+ .procname = "callhome",
+ .mode = 0644,
+ .proc_handler = &proc_handler_callhome,
+ },
+ { .ctl_name = 0 }
+};
+
+static struct ctl_table kern_dir_table[] = {
+ {
+ .ctl_name = CTL_KERN,
+ .procname = "kernel",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = callhome_table,
+ },
+ { .ctl_name = 0 }
+};
+
+/*
+ * Function used to transfer asynchronous notification
+ * records which waits for send completion
+ */
+static int sclp_async_send_wait(char *message)
+{
+ struct async_evbuf *evb;
+ int rc;
+ unsigned long flags;
+
+ if (!callhome_enabled)
+ return 0;
+ sccb->evbuf.header.type = EVTYP_ASYNC;
+ sccb->evbuf.rtype = 0xA5;
+ sccb->evbuf.otype = 0x00;
+ evb = &sccb->evbuf;
+ request->command = SCLP_CMDW_WRITE_EVENT_DATA;
+ request->sccb = sccb;
+ request->status = SCLP_REQ_FILLED;
+ strncpy(sccb->evbuf.data, message, sizeof(sccb->evbuf.data));
+ /*
+ * Retain Queue
+ * e.g. 5639CC140 500 Red Hat RHEL5 Linux for zSeries (RHEL AS)
+ */
+ strncpy(sccb->evbuf.comp_id, "000000000", sizeof(sccb->evbuf.comp_id));
+ sccb->evbuf.header.length = sizeof(sccb->evbuf);
+ sccb->header.length = sizeof(sccb->evbuf) + sizeof(sccb->header);
+ sccb->header.function_code = SCLP_NORMAL_WRITE;
+ rc = sclp_add_request(request);
+ if (rc)
+ return rc;
+ spin_lock_irqsave(&sclp_async_lock, flags);
+ while (request->status != SCLP_REQ_DONE &&
+ request->status != SCLP_REQ_FAILED) {
+ sclp_sync_wait();
+ }
+ spin_unlock_irqrestore(&sclp_async_lock, flags);
+ if (request->status != SCLP_REQ_DONE)
+ return -EIO;
+ rc = ((struct sclp_async_sccb *)
+ request->sccb)->header.response_code;
+ if (rc != 0x0020)
+ return -EIO;
+ if (evb->header.flags != 0x80)
+ return -EIO;
+ return rc;
+}
+
+static int __init sclp_async_init(void)
+{
+ int rc;
+
+ rc = sclp_register(&sclp_async_register);
+ if (rc)
+ return rc;
+ callhome_sysctl_header = register_sysctl_table(kern_dir_table);
+ if (!callhome_sysctl_header) {
+ rc = -ENOMEM;
+ goto out_sclp;
+ }
+ if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) {
+ rc = -EOPNOTSUPP;
+ goto out_sclp;
+ }
+ rc = -ENOMEM;
+ request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
+ if (!request)
+ goto out_sys;
+ sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!sccb)
+ goto out_mem;
+ rc = atomic_notifier_chain_register(&panic_notifier_list,
+ &call_home_panic_nb);
+ if (rc)
+ goto out_mem;
+
+ strncpy(nodename, init_utsname()->nodename, 64);
+ return 0;
+
+out_mem:
+ kfree(request);
+ free_page((unsigned long) sccb);
+out_sys:
+ unregister_sysctl_table(callhome_sysctl_header);
+out_sclp:
+ sclp_unregister(&sclp_async_register);
+ return rc;
+
+}
+module_init(sclp_async_init);
+
+static void __exit sclp_async_exit(void)
+{
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &call_home_panic_nb);
+ unregister_sysctl_table(callhome_sysctl_header);
+ sclp_unregister(&sclp_async_register);
+ free_page((unsigned long) sccb);
+ kfree(request);
+}
+module_exit(sclp_async_exit);
+
+MODULE_AUTHOR("Copyright IBM Corp. 2009");
+MODULE_AUTHOR("Hans-Joachim Picht <hans@linux.vnet.ibm.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SCLP Asynchronous Notification Records");
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 5a519fac37b..2fe45ff77b7 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -8,7 +8,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape"
+#define KMSG_COMPONENT "tape_34xx"
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 418f72dd39b..e4cc3aae916 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -8,7 +8,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#define KMSG_COMPONENT "tape"
+#define KMSG_COMPONENT "tape_3590"
#include <linux/module.h>
#include <linux/init.h>
@@ -39,8 +39,6 @@ EXPORT_SYMBOL(TAPE_DBF_AREA);
* - Read Alternate: implemented
*******************************************************************/
-#define KMSG_COMPONENT "tape"
-
static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = {
[0x00] = "",
[0x10] = "Lost Sense",
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 47ff695255e..4cb9e70507a 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -302,8 +302,6 @@ tapeblock_revalidate_disk(struct gendisk *disk)
if (!device->blk_data.medium_changed)
return 0;
- dev_info(&device->cdev->dev, "Determining the size of the recorded "
- "area...\n");
rc = tape_mtop(device, MTFSFM, 1);
if (rc)
return rc;
@@ -312,6 +310,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
if (rc < 0)
return rc;
+ pr_info("%s: Determining the size of the recorded area...\n",
+ dev_name(&device->cdev->dev));
DBF_LH(3, "Image file ends at %d\n", rc);
nr_of_blks = rc;
@@ -330,8 +330,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
device->bof = rc;
nr_of_blks -= rc;
- dev_info(&device->cdev->dev, "The size of the recorded area is %i "
- "blocks\n", nr_of_blks);
+ pr_info("%s: The size of the recorded area is %i blocks\n",
+ dev_name(&device->cdev->dev), nr_of_blks);
set_capacity(device->blk_data.disk,
nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512));
@@ -366,8 +366,8 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
if (device->required_tapemarks) {
DBF_EVENT(2, "TBLOCK: missing tapemarks\n");
- dev_warn(&device->cdev->dev, "Opening the tape failed because"
- " of missing end-of-file marks\n");
+ pr_warning("%s: Opening the tape failed because of missing "
+ "end-of-file marks\n", dev_name(&device->cdev->dev));
rc = -EPERM;
goto put_device;
}
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 1d420d94759..5cd31e07164 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -214,13 +214,15 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
switch(newstate){
case MS_UNLOADED:
device->tape_generic_status |= GMT_DR_OPEN(~0);
- dev_info(&device->cdev->dev, "The tape cartridge has been "
- "successfully unloaded\n");
+ if (device->medium_state == MS_LOADED)
+ pr_info("%s: The tape cartridge has been successfully "
+ "unloaded\n", dev_name(&device->cdev->dev));
break;
case MS_LOADED:
device->tape_generic_status &= ~GMT_DR_OPEN(~0);
- dev_info(&device->cdev->dev, "A tape cartridge has been "
- "mounted\n");
+ if (device->medium_state == MS_UNLOADED)
+ pr_info("%s: A tape cartridge has been mounted\n",
+ dev_name(&device->cdev->dev));
break;
default:
// print nothing
@@ -358,11 +360,11 @@ tape_generic_online(struct tape_device *device,
out_char:
tapechar_cleanup_device(device);
+out_minor:
+ tape_remove_minor(device);
out_discipline:
device->discipline->cleanup_device(device);
device->discipline = NULL;
-out_minor:
- tape_remove_minor(device);
out:
module_put(discipline->owner);
return rc;
@@ -654,8 +656,8 @@ tape_generic_remove(struct ccw_device *cdev)
*/
DBF_EVENT(3, "(%08x): Drive in use vanished!\n",
device->cdev_id);
- dev_warn(&device->cdev->dev, "A tape unit was detached"
- " while in use\n");
+ pr_warning("%s: A tape unit was detached while in "
+ "use\n", dev_name(&device->cdev->dev));
tape_state_set(device, TS_NOT_OPER);
__tape_discard_requests(device);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 1a9420ba518..750354ad16e 100644
--- a/drivers/s390/char/tape_std.c
+++ b/drivers/s390/char/tape_std.c
@@ -68,7 +68,7 @@ tape_std_assign(struct tape_device *device)
* to another host (actually this shouldn't happen but it does).
* So we set up a timeout for this call.
*/
- init_timer(&timeout);
+ init_timer_on_stack(&timeout);
timeout.function = tape_std_assign_timeout;
timeout.data = (unsigned long) request;
timeout.expires = jiffies + 2 * HZ;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index c20a4fe6da5..d1a142fa3eb 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -765,8 +765,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
} else
return -ENOMEM;
ret = device_register(dev);
- if (ret)
+ if (ret) {
+ put_device(dev);
return ret;
+ }
ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group);
if (ret) {
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 31b902e94f7..77571b68539 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -1026,9 +1026,15 @@ static int __init ur_init(void)
debug_set_level(vmur_dbf, 6);
+ vmur_class = class_create(THIS_MODULE, "vmur");
+ if (IS_ERR(vmur_class)) {
+ rc = PTR_ERR(vmur_class);
+ goto fail_free_dbf;
+ }
+
rc = ccw_driver_register(&ur_driver);
if (rc)
- goto fail_free_dbf;
+ goto fail_class_destroy;
rc = alloc_chrdev_region(&dev, 0, NUM_MINORS, "vmur");
if (rc) {
@@ -1038,18 +1044,13 @@ static int __init ur_init(void)
}
ur_first_dev_maj_min = MKDEV(MAJOR(dev), 0);
- vmur_class = class_create(THIS_MODULE, "vmur");
- if (IS_ERR(vmur_class)) {
- rc = PTR_ERR(vmur_class);
- goto fail_unregister_region;
- }
pr_info("%s loaded.\n", ur_banner);
return 0;
-fail_unregister_region:
- unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS);
fail_unregister_driver:
ccw_driver_unregister(&ur_driver);
+fail_class_destroy:
+ class_destroy(vmur_class);
fail_free_dbf:
debug_unregister(vmur_dbf);
return rc;
@@ -1057,9 +1058,9 @@ fail_free_dbf:
static void __exit ur_exit(void)
{
- class_destroy(vmur_class);
unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS);
ccw_driver_unregister(&ur_driver);
+ class_destroy(vmur_class);
debug_unregister(vmur_dbf);
pr_info("%s unloaded.\n", ur_banner);
}
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 1bbae433fbd..c431198bdbc 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -275,7 +275,7 @@ struct zcore_header {
u32 num_pages;
u32 pad1;
u64 tod;
- cpuid_t cpu_id;
+ struct cpuid cpu_id;
u32 arch_id;
u32 volnr;
u32 build_arch;
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile
index adb3dd30152..fa4c9662f65 100644
--- a/drivers/s390/cio/Makefile
+++ b/drivers/s390/cio/Makefile
@@ -2,7 +2,7 @@
# Makefile for the S/390 common i/o drivers
#
-obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \
+obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \
fcx.o itcw.o crw.o
ccw_device-objs += device.o device_fsm.o device_ops.o
ccw_device-objs += device_id.o device_pgid.o device_status.o
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 3e5f304ad88..40002830d48 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -417,7 +417,8 @@ int chp_new(struct chp_id chpid)
if (ret) {
CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n",
chpid.cssid, chpid.id, ret);
- goto out_free;
+ put_device(&chp->dev);
+ goto out;
}
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
if (ret) {
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 425e8f89a6c..37aa611d4ac 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -37,29 +37,6 @@ struct channel_path_desc {
struct channel_path;
-struct css_general_char {
- u64 : 12;
- u32 dynio : 1; /* bit 12 */
- u32 : 28;
- u32 aif : 1; /* bit 41 */
- u32 : 3;
- u32 mcss : 1; /* bit 45 */
- u32 fcs : 1; /* bit 46 */
- u32 : 1;
- u32 ext_mb : 1; /* bit 48 */
- u32 : 7;
- u32 aif_tdd : 1; /* bit 56 */
- u32 : 1;
- u32 qebsm : 1; /* bit 58 */
- u32 : 8;
- u32 aif_osa : 1; /* bit 67 */
- u32 : 14;
- u32 cib : 1; /* bit 82 */
- u32 : 5;
- u32 fcx : 1; /* bit 88 */
- u32 : 7;
-}__attribute__((packed));
-
struct css_chsc_char {
u64 res;
u64 : 20;
@@ -72,7 +49,6 @@ struct css_chsc_char {
u32 : 19;
}__attribute__((packed));
-extern struct css_general_char css_general_characteristics;
extern struct css_chsc_char css_chsc_characteristics;
struct chsc_ssd_info {
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 5ec7789bd9d..138124fcfca 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -139,12 +139,11 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
__u8 lpm, /* logical path mask */
__u8 key) /* storage key */
{
- char dbf_txt[15];
int ccode;
union orb *orb;
- CIO_TRACE_EVENT(4, "stIO");
- CIO_TRACE_EVENT(4, dev_name(&sch->dev));
+ CIO_TRACE_EVENT(5, "stIO");
+ CIO_TRACE_EVENT(5, dev_name(&sch->dev));
orb = &to_io_private(sch)->orb;
memset(orb, 0, sizeof(union orb));
@@ -169,8 +168,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
ccode = ssch(sch->schid, orb);
/* process condition code */
- sprintf(dbf_txt, "ccode:%d", ccode);
- CIO_TRACE_EVENT(4, dbf_txt);
+ CIO_HEX_EVENT(5, &ccode, sizeof(ccode));
switch (ccode) {
case 0:
@@ -201,16 +199,14 @@ cio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm)
int
cio_resume (struct subchannel *sch)
{
- char dbf_txt[15];
int ccode;
- CIO_TRACE_EVENT (4, "resIO");
+ CIO_TRACE_EVENT(4, "resIO");
CIO_TRACE_EVENT(4, dev_name(&sch->dev));
ccode = rsch (sch->schid);
- sprintf (dbf_txt, "ccode:%d", ccode);
- CIO_TRACE_EVENT (4, dbf_txt);
+ CIO_HEX_EVENT(4, &ccode, sizeof(ccode));
switch (ccode) {
case 0:
@@ -235,13 +231,12 @@ cio_resume (struct subchannel *sch)
int
cio_halt(struct subchannel *sch)
{
- char dbf_txt[15];
int ccode;
if (!sch)
return -ENODEV;
- CIO_TRACE_EVENT (2, "haltIO");
+ CIO_TRACE_EVENT(2, "haltIO");
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
/*
@@ -249,8 +244,7 @@ cio_halt(struct subchannel *sch)
*/
ccode = hsch (sch->schid);
- sprintf (dbf_txt, "ccode:%d", ccode);
- CIO_TRACE_EVENT (2, dbf_txt);
+ CIO_HEX_EVENT(2, &ccode, sizeof(ccode));
switch (ccode) {
case 0:
@@ -270,13 +264,12 @@ cio_halt(struct subchannel *sch)
int
cio_clear(struct subchannel *sch)
{
- char dbf_txt[15];
int ccode;
if (!sch)
return -ENODEV;
- CIO_TRACE_EVENT (2, "clearIO");
+ CIO_TRACE_EVENT(2, "clearIO");
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
/*
@@ -284,8 +277,7 @@ cio_clear(struct subchannel *sch)
*/
ccode = csch (sch->schid);
- sprintf (dbf_txt, "ccode:%d", ccode);
- CIO_TRACE_EVENT (2, dbf_txt);
+ CIO_HEX_EVENT(2, &ccode, sizeof(ccode));
switch (ccode) {
case 0:
@@ -306,19 +298,17 @@ cio_clear(struct subchannel *sch)
int
cio_cancel (struct subchannel *sch)
{
- char dbf_txt[15];
int ccode;
if (!sch)
return -ENODEV;
- CIO_TRACE_EVENT (2, "cancelIO");
+ CIO_TRACE_EVENT(2, "cancelIO");
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
ccode = xsch (sch->schid);
- sprintf (dbf_txt, "ccode:%d", ccode);
- CIO_TRACE_EVENT (2, dbf_txt);
+ CIO_HEX_EVENT(2, &ccode, sizeof(ccode));
switch (ccode) {
case 0: /* success */
@@ -429,11 +419,10 @@ EXPORT_SYMBOL_GPL(cio_update_schib);
*/
int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
{
- char dbf_txt[15];
int retry;
int ret;
- CIO_TRACE_EVENT (2, "ensch");
+ CIO_TRACE_EVENT(2, "ensch");
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
if (sch_is_pseudo_sch(sch))
@@ -460,8 +449,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
} else
break;
}
- sprintf (dbf_txt, "ret:%d", ret);
- CIO_TRACE_EVENT (2, dbf_txt);
+ CIO_HEX_EVENT(2, &ret, sizeof(ret));
return ret;
}
EXPORT_SYMBOL_GPL(cio_enable_subchannel);
@@ -472,11 +460,10 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
*/
int cio_disable_subchannel(struct subchannel *sch)
{
- char dbf_txt[15];
int retry;
int ret;
- CIO_TRACE_EVENT (2, "dissch");
+ CIO_TRACE_EVENT(2, "dissch");
CIO_TRACE_EVENT(2, dev_name(&sch->dev));
if (sch_is_pseudo_sch(sch))
@@ -495,8 +482,7 @@ int cio_disable_subchannel(struct subchannel *sch)
} else
break;
}
- sprintf (dbf_txt, "ret:%d", ret);
- CIO_TRACE_EVENT (2, dbf_txt);
+ CIO_HEX_EVENT(2, &ret, sizeof(ret));
return ret;
}
EXPORT_SYMBOL_GPL(cio_disable_subchannel);
@@ -578,11 +564,6 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
goto out;
}
mutex_init(&sch->reg_mutex);
- /* Set a name for the subchannel */
- if (cio_is_console(schid))
- sch->dev.init_name = cio_get_console_sch_name(schid);
- else
- dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no);
/*
* The first subchannel that is not-operational (ccode==3)
@@ -686,7 +667,6 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
#ifdef CONFIG_CCW_CONSOLE
static struct subchannel console_subchannel;
-static char console_sch_name[10] = "0.x.xxxx";
static struct io_subchannel_private console_priv;
static int console_subchannel_in_use;
@@ -873,12 +853,6 @@ cio_get_console_subchannel(void)
return &console_subchannel;
}
-const char *cio_get_console_sch_name(struct subchannel_id schid)
-{
- snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no);
- return (const char *)console_sch_name;
-}
-
#endif
static int
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 5150fba742a..2e43558c704 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -133,15 +133,11 @@ extern int cio_is_console(struct subchannel_id);
extern struct subchannel *cio_get_console_subchannel(void);
extern spinlock_t * cio_get_console_lock(void);
extern void *cio_get_console_priv(void);
-extern const char *cio_get_console_sch_name(struct subchannel_id schid);
-extern const char *cio_get_console_cdev_name(struct subchannel *sch);
#else
#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
#define cio_get_console_lock() NULL
#define cio_get_console_priv() NULL
-#define cio_get_console_sch_name(schid) NULL
-#define cio_get_console_cdev_name(sch) NULL
#endif
#endif
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 85d43c6bcb6..e995123fd80 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -152,24 +152,15 @@ css_alloc_subchannel(struct subchannel_id schid)
}
static void
-css_free_subchannel(struct subchannel *sch)
-{
- if (sch) {
- /* Reset intparm to zeroes. */
- sch->config.intparm = 0;
- cio_commit_config(sch);
- kfree(sch->lock);
- kfree(sch);
- }
-}
-
-static void
css_subchannel_release(struct device *dev)
{
struct subchannel *sch;
sch = to_subchannel(dev);
if (!cio_is_console(sch->schid)) {
+ /* Reset intparm to zeroes. */
+ sch->config.intparm = 0;
+ cio_commit_config(sch);
kfree(sch->lock);
kfree(sch);
}
@@ -180,6 +171,8 @@ static int css_sch_device_register(struct subchannel *sch)
int ret;
mutex_lock(&sch->reg_mutex);
+ dev_set_name(&sch->dev, "0.%x.%04x", sch->schid.ssid,
+ sch->schid.sch_no);
ret = device_register(&sch->dev);
mutex_unlock(&sch->reg_mutex);
return ret;
@@ -327,7 +320,7 @@ int css_probe_device(struct subchannel_id schid)
return PTR_ERR(sch);
ret = css_register_subchannel(sch);
if (ret)
- css_free_subchannel(sch);
+ put_device(&sch->dev);
return ret;
}
@@ -644,7 +637,10 @@ __init_channel_subsystem(struct subchannel_id schid, void *data)
* not working) so we do it now. This is true e.g. for the
* console subchannel.
*/
- css_register_subchannel(sch);
+ if (css_register_subchannel(sch)) {
+ if (!cio_is_console(schid))
+ put_device(&sch->dev);
+ }
return 0;
}
@@ -661,8 +657,8 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
css->global_pgid.pgid_high.cpu_addr = 0;
#endif
}
- css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
- css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
+ css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident;
+ css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine;
css->global_pgid.tod_high = tod_high;
}
@@ -920,8 +916,10 @@ init_channel_subsystem (void)
goto out_device;
}
ret = device_register(&css->pseudo_subchannel->dev);
- if (ret)
+ if (ret) {
+ put_device(&css->pseudo_subchannel->dev);
goto out_file;
+ }
}
ret = register_reboot_notifier(&css_reboot_notifier);
if (ret)
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index d593bc76afe..0f95405c2c5 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -307,8 +307,11 @@ int ccw_device_is_orphan(struct ccw_device *cdev)
static void ccw_device_unregister(struct ccw_device *cdev)
{
- if (test_and_clear_bit(1, &cdev->private->registered))
+ if (test_and_clear_bit(1, &cdev->private->registered)) {
device_del(&cdev->dev);
+ /* Release reference from device_initialize(). */
+ put_device(&cdev->dev);
+ }
}
static void ccw_device_remove_orphan_cb(struct work_struct *work)
@@ -319,7 +322,6 @@ static void ccw_device_remove_orphan_cb(struct work_struct *work)
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
ccw_device_unregister(cdev);
- put_device(&cdev->dev);
/* Release cdev reference for workqueue processing. */
put_device(&cdev->dev);
}
@@ -333,15 +335,15 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
* Forced offline in disconnected state means
* 'throw away device'.
*/
- /* Get cdev reference for workqueue processing. */
- if (!get_device(&cdev->dev))
- return;
if (ccw_device_is_orphan(cdev)) {
/*
* Deregister ccw device.
* Unfortunately, we cannot do this directly from the
* attribute method.
*/
+ /* Get cdev reference for workqueue processing. */
+ if (!get_device(&cdev->dev))
+ return;
spin_lock_irqsave(cdev->ccwlock, flags);
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
@@ -380,30 +382,34 @@ int ccw_device_set_offline(struct ccw_device *cdev)
}
cdev->online = 0;
spin_lock_irq(cdev->ccwlock);
- ret = ccw_device_offline(cdev);
- if (ret == -ENODEV) {
- if (cdev->private->state != DEV_STATE_NOT_OPER) {
- cdev->private->state = DEV_STATE_OFFLINE;
- dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
- }
+ /* Wait until a final state or DISCONNECTED is reached */
+ while (!dev_fsm_final_state(cdev) &&
+ cdev->private->state != DEV_STATE_DISCONNECTED) {
spin_unlock_irq(cdev->ccwlock);
- /* Give up reference from ccw_device_set_online(). */
- put_device(&cdev->dev);
- return ret;
+ wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) ||
+ cdev->private->state == DEV_STATE_DISCONNECTED));
+ spin_lock_irq(cdev->ccwlock);
}
+ ret = ccw_device_offline(cdev);
+ if (ret)
+ goto error;
spin_unlock_irq(cdev->ccwlock);
- if (ret == 0) {
- wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
- /* Give up reference from ccw_device_set_online(). */
- put_device(&cdev->dev);
- } else {
- CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
- "device 0.%x.%04x\n",
- ret, cdev->private->dev_id.ssid,
- cdev->private->dev_id.devno);
- cdev->online = 1;
- }
- return ret;
+ wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) ||
+ cdev->private->state == DEV_STATE_DISCONNECTED));
+ /* Give up reference from ccw_device_set_online(). */
+ put_device(&cdev->dev);
+ return 0;
+
+error:
+ CIO_MSG_EVENT(0, "ccw_device_offline returned %d, device 0.%x.%04x\n",
+ ret, cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
+ cdev->private->state = DEV_STATE_OFFLINE;
+ dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
+ spin_unlock_irq(cdev->ccwlock);
+ /* Give up reference from ccw_device_set_online(). */
+ put_device(&cdev->dev);
+ return -ENODEV;
}
/**
@@ -421,6 +427,7 @@ int ccw_device_set_offline(struct ccw_device *cdev)
int ccw_device_set_online(struct ccw_device *cdev)
{
int ret;
+ int ret2;
if (!cdev)
return -ENODEV;
@@ -444,28 +451,53 @@ int ccw_device_set_online(struct ccw_device *cdev)
put_device(&cdev->dev);
return ret;
}
- if (cdev->private->state != DEV_STATE_ONLINE) {
+ spin_lock_irq(cdev->ccwlock);
+ /* Check if online processing was successful */
+ if ((cdev->private->state != DEV_STATE_ONLINE) &&
+ (cdev->private->state != DEV_STATE_W4SENSE)) {
+ spin_unlock_irq(cdev->ccwlock);
/* Give up online reference since onlining failed. */
put_device(&cdev->dev);
return -ENODEV;
}
- if (!cdev->drv->set_online || cdev->drv->set_online(cdev) == 0) {
- cdev->online = 1;
- return 0;
- }
+ spin_unlock_irq(cdev->ccwlock);
+ if (cdev->drv->set_online)
+ ret = cdev->drv->set_online(cdev);
+ if (ret)
+ goto rollback;
+ cdev->online = 1;
+ return 0;
+
+rollback:
spin_lock_irq(cdev->ccwlock);
- ret = ccw_device_offline(cdev);
+ /* Wait until a final state or DISCONNECTED is reached */
+ while (!dev_fsm_final_state(cdev) &&
+ cdev->private->state != DEV_STATE_DISCONNECTED) {
+ spin_unlock_irq(cdev->ccwlock);
+ wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) ||
+ cdev->private->state == DEV_STATE_DISCONNECTED));
+ spin_lock_irq(cdev->ccwlock);
+ }
+ ret2 = ccw_device_offline(cdev);
+ if (ret2)
+ goto error;
spin_unlock_irq(cdev->ccwlock);
- if (ret == 0)
- wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
- else
- CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
- "device 0.%x.%04x\n",
- ret, cdev->private->dev_id.ssid,
- cdev->private->dev_id.devno);
+ wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) ||
+ cdev->private->state == DEV_STATE_DISCONNECTED));
/* Give up online reference since onlining failed. */
put_device(&cdev->dev);
- return (ret == 0) ? -ENODEV : ret;
+ return ret;
+
+error:
+ CIO_MSG_EVENT(0, "rollback ccw_device_offline returned %d, "
+ "device 0.%x.%04x\n",
+ ret2, cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
+ cdev->private->state = DEV_STATE_OFFLINE;
+ spin_unlock_irq(cdev->ccwlock);
+ /* Give up online reference since onlining failed. */
+ put_device(&cdev->dev);
+ return ret;
}
static int online_store_handle_offline(struct ccw_device *cdev)
@@ -637,8 +669,12 @@ static int ccw_device_register(struct ccw_device *cdev)
int ret;
dev->bus = &ccw_bus_type;
-
- if ((ret = device_add(dev)))
+ ret = dev_set_name(&cdev->dev, "0.%x.%04x", cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
+ if (ret)
+ return ret;
+ ret = device_add(dev);
+ if (ret)
return ret;
set_bit(1, &cdev->private->registered);
@@ -1024,9 +1060,6 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
return;
sch = to_subchannel(cdev->dev.parent);
css_sch_device_unregister(sch);
- /* Reset intparm to zeroes. */
- sch->config.intparm = 0;
- cio_commit_config(sch);
/* Release cdev reference for workqueue processing.*/
put_device(&cdev->dev);
/* Release subchannel reference for local processing. */
@@ -1035,6 +1068,9 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
void ccw_device_schedule_sch_unregister(struct ccw_device *cdev)
{
+ /* Get cdev reference for workqueue processing. */
+ if (!get_device(&cdev->dev))
+ return;
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_call_sch_unregister);
queue_work(slow_path_wq, &cdev->private->kick_work);
@@ -1055,9 +1091,6 @@ io_subchannel_recog_done(struct ccw_device *cdev)
/* Device did not respond in time. */
case DEV_STATE_NOT_OPER:
cdev->private->flags.recog_done = 1;
- /* Remove device found not operational. */
- if (!get_device(&cdev->dev))
- break;
ccw_device_schedule_sch_unregister(cdev);
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
@@ -1095,13 +1128,6 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
init_waitqueue_head(&priv->wait_q);
init_timer(&priv->timer);
- /* Set an initial name for the device. */
- if (cio_is_console(sch->schid))
- cdev->dev.init_name = cio_get_console_cdev_name(sch);
- else
- dev_set_name(&cdev->dev, "0.%x.%04x",
- sch->schid.ssid, sch->schib.pmcw.dev);
-
/* Increase counter of devices currently in recognition. */
atomic_inc(&ccw_device_init_count);
@@ -1171,8 +1197,8 @@ static void io_subchannel_irq(struct subchannel *sch)
cdev = sch_get_cdev(sch);
- CIO_TRACE_EVENT(3, "IRQ");
- CIO_TRACE_EVENT(3, dev_name(&sch->dev));
+ CIO_TRACE_EVENT(6, "IRQ");
+ CIO_TRACE_EVENT(6, dev_name(&sch->dev));
if (cdev)
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
}
@@ -1210,9 +1236,6 @@ static void io_subchannel_do_unreg(struct work_struct *work)
sch = container_of(work, struct subchannel, work);
css_sch_device_unregister(sch);
- /* Reset intparm to zeroes. */
- sch->config.intparm = 0;
- cio_commit_config(sch);
put_device(&sch->dev);
}
@@ -1334,7 +1357,6 @@ io_subchannel_remove (struct subchannel *sch)
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
ccw_device_unregister(cdev);
- put_device(&cdev->dev);
kfree(sch->private);
sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
return 0;
@@ -1571,8 +1593,6 @@ static int purge_fn(struct device *dev, void *data)
spin_unlock_irq(cdev->ccwlock);
if (!unreg)
goto out;
- if (!get_device(&cdev->dev))
- goto out;
CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
priv->dev_id.devno);
ccw_device_schedule_sch_unregister(cdev);
@@ -1688,10 +1708,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
spin_unlock_irqrestore(sch->lock, flags);
css_sch_device_unregister(sch);
spin_lock_irqsave(sch->lock, flags);
-
- /* Reset intparm to zeroes. */
- sch->config.intparm = 0;
- cio_commit_config(sch);
break;
case REPROBE:
ccw_device_trigger_reprobe(cdev);
@@ -1712,7 +1728,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
#ifdef CONFIG_CCW_CONSOLE
static struct ccw_device console_cdev;
-static char console_cdev_name[10] = "0.x.xxxx";
static struct ccw_device_private console_private;
static int console_cdev_in_use;
@@ -1796,13 +1811,6 @@ int ccw_device_force_console(void)
return ccw_device_pm_restore(&console_cdev.dev);
}
EXPORT_SYMBOL_GPL(ccw_device_force_console);
-
-const char *cio_get_console_cdev_name(struct subchannel *sch)
-{
- snprintf(console_cdev_name, 10, "0.%x.%04x",
- sch->schid.ssid, sch->schib.pmcw.dev);
- return (const char *)console_cdev_name;
-}
#endif
/*
@@ -2020,7 +2028,9 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev)
spin_unlock_irq(sch->lock);
if (ret) {
CIO_MSG_EVENT(0, "Couldn't start recognition for device "
- "%s (ret=%d)\n", dev_name(&cdev->dev), ret);
+ "0.%x.%04x (ret=%d)\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
spin_lock_irq(sch->lock);
cdev->private->state = DEV_STATE_DISCONNECTED;
spin_unlock_irq(sch->lock);
@@ -2083,8 +2093,9 @@ static int ccw_device_pm_restore(struct device *dev)
}
/* check if the device id has changed */
if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
- CIO_MSG_EVENT(0, "resume: sch %s: failed (devno changed from "
- "%04x to %04x)\n", dev_name(&sch->dev),
+ CIO_MSG_EVENT(0, "resume: sch 0.%x.%04x: failed (devno "
+ "changed from %04x to %04x)\n",
+ sch->schid.ssid, sch->schid.sch_no,
cdev->private->dev_id.devno,
sch->schib.pmcw.dev);
goto out_unreg_unlock;
@@ -2117,8 +2128,9 @@ static int ccw_device_pm_restore(struct device *dev)
if (cm_enabled) {
ret = ccw_set_cmf(cdev, 1);
if (ret) {
- CIO_MSG_EVENT(2, "resume: cdev %s: cmf failed "
- "(rc=%d)\n", dev_name(&cdev->dev), ret);
+ CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed "
+ "(rc=%d)\n", cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
ret = 0;
}
}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 3db88c52d28..e728ce447f6 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -394,6 +394,13 @@ ccw_device_done(struct ccw_device *cdev, int state)
ccw_device_schedule_sch_unregister(cdev);
cdev->private->flags.donotify = 0;
}
+ if (state == DEV_STATE_NOT_OPER) {
+ CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n",
+ cdev->private->dev_id.devno, sch->schid.sch_no);
+ if (!ccw_device_notify(cdev, CIO_GONE))
+ ccw_device_schedule_sch_unregister(cdev);
+ cdev->private->flags.donotify = 0;
+ }
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
@@ -731,6 +738,17 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev,
}
/*
+ * Handle path verification event in offline state.
+ */
+static void ccw_device_offline_verify(struct ccw_device *cdev,
+ enum dev_event dev_event)
+{
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
+ css_schedule_eval(sch->schid);
+}
+
+/*
* Handle path verification event.
*/
static void
@@ -887,6 +905,8 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
}
call_handler:
cdev->private->state = DEV_STATE_ONLINE;
+ /* In case sensing interfered with setting the device online */
+ wake_up(&cdev->private->wait_q);
/* Call the handler. */
if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify)
/* Start delayed path verification. */
@@ -1149,7 +1169,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
[DEV_EVENT_NOTOPER] = ccw_device_generic_notoper,
[DEV_EVENT_INTERRUPT] = ccw_device_offline_irq,
[DEV_EVENT_TIMEOUT] = ccw_device_nop,
- [DEV_EVENT_VERIFY] = ccw_device_nop,
+ [DEV_EVENT_VERIFY] = ccw_device_offline_verify,
},
[DEV_STATE_VERIFY] = {
[DEV_EVENT_NOTOPER] = ccw_device_generic_notoper,
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index b1241f8fae8..ff7748a9199 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -1,7 +1,7 @@
/*
* linux/drivers/s390/cio/qdio.h
*
- * Copyright 2000,2008 IBM Corp.
+ * Copyright 2000,2009 IBM Corp.
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
@@ -246,6 +246,7 @@ struct qdio_q {
atomic_t nr_buf_used;
struct qdio_irq *irq_ptr;
+ struct dentry *debugfs_q;
struct tasklet_struct tasklet;
/* error condition during a data transfer */
@@ -267,6 +268,7 @@ struct qdio_irq {
struct qib qib;
u32 *dsci; /* address of device state change indicator */
struct ccw_device *cdev;
+ struct dentry *debugfs_dev;
unsigned long int_parm;
struct subchannel_id schid;
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index b8626d4df11..1b78f639ead 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -1,14 +1,12 @@
/*
* drivers/s390/cio/qdio_debug.c
*
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
*
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
*/
-#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
-#include <asm/qdio.h>
#include <asm/debug.h>
#include "qdio_debug.h"
#include "qdio.h"
@@ -17,10 +15,7 @@ debug_info_t *qdio_dbf_setup;
debug_info_t *qdio_dbf_error;
static struct dentry *debugfs_root;
-#define MAX_DEBUGFS_QUEUES 32
-static struct dentry *debugfs_queues[MAX_DEBUGFS_QUEUES] = { NULL };
-static DEFINE_MUTEX(debugfs_mutex);
-#define QDIO_DEBUGFS_NAME_LEN 40
+#define QDIO_DEBUGFS_NAME_LEN 10
void qdio_allocate_dbf(struct qdio_initialize *init_data,
struct qdio_irq *irq_ptr)
@@ -130,20 +125,6 @@ static int qstat_seq_open(struct inode *inode, struct file *filp)
filp->f_path.dentry->d_inode->i_private);
}
-static void remove_debugfs_entry(struct qdio_q *q)
-{
- int i;
-
- for (i = 0; i < MAX_DEBUGFS_QUEUES; i++) {
- if (!debugfs_queues[i])
- continue;
- if (debugfs_queues[i]->d_inode->i_private == q) {
- debugfs_remove(debugfs_queues[i]);
- debugfs_queues[i] = NULL;
- }
- }
-}
-
static struct file_operations debugfs_fops = {
.owner = THIS_MODULE,
.open = qstat_seq_open,
@@ -155,22 +136,15 @@ static struct file_operations debugfs_fops = {
static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
{
- int i = 0;
char name[QDIO_DEBUGFS_NAME_LEN];
- while (debugfs_queues[i] != NULL) {
- i++;
- if (i >= MAX_DEBUGFS_QUEUES)
- return;
- }
- snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%s_%d",
- dev_name(&cdev->dev),
+ snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
q->is_input_q ? "input" : "output",
q->nr);
- debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
- debugfs_root, q, &debugfs_fops);
- if (IS_ERR(debugfs_queues[i]))
- debugfs_queues[i] = NULL;
+ q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
+ q->irq_ptr->debugfs_dev, q, &debugfs_fops);
+ if (IS_ERR(q->debugfs_q))
+ q->debugfs_q = NULL;
}
void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
@@ -178,12 +152,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
struct qdio_q *q;
int i;
- mutex_lock(&debugfs_mutex);
+ irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev),
+ debugfs_root);
+ if (IS_ERR(irq_ptr->debugfs_dev))
+ irq_ptr->debugfs_dev = NULL;
for_each_input_queue(irq_ptr, q, i)
setup_debugfs_entry(q, cdev);
for_each_output_queue(irq_ptr, q, i)
setup_debugfs_entry(q, cdev);
- mutex_unlock(&debugfs_mutex);
}
void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
@@ -191,17 +167,16 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd
struct qdio_q *q;
int i;
- mutex_lock(&debugfs_mutex);
for_each_input_queue(irq_ptr, q, i)
- remove_debugfs_entry(q);
+ debugfs_remove(q->debugfs_q);
for_each_output_queue(irq_ptr, q, i)
- remove_debugfs_entry(q);
- mutex_unlock(&debugfs_mutex);
+ debugfs_remove(q->debugfs_q);
+ debugfs_remove(irq_ptr->debugfs_dev);
}
int __init qdio_debug_init(void)
{
- debugfs_root = debugfs_create_dir("qdio_queues", NULL);
+ debugfs_root = debugfs_create_dir("qdio", NULL);
qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 0038750ad94..9aef402a5f1 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -798,8 +798,10 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
if (!qdio_inbound_q_done(q)) {
qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop);
- if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
+ if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
tasklet_schedule(&q->tasklet);
+ return;
+ }
}
qdio_stop_polling(q);
diff --git a/drivers/s390/cio/scsw.c b/drivers/s390/cio/scsw.c
deleted file mode 100644
index f8da25ab576..00000000000
--- a/drivers/s390/cio/scsw.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * Helper functions for scsw access.
- *
- * Copyright IBM Corp. 2008
- * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <asm/cio.h>
-#include "css.h"
-#include "chsc.h"
-
-/**
- * scsw_is_tm - check for transport mode scsw
- * @scsw: pointer to scsw
- *
- * Return non-zero if the specified scsw is a transport mode scsw, zero
- * otherwise.
- */
-int scsw_is_tm(union scsw *scsw)
-{
- return css_general_characteristics.fcx && (scsw->tm.x == 1);
-}
-EXPORT_SYMBOL(scsw_is_tm);
-
-/**
- * scsw_key - return scsw key field
- * @scsw: pointer to scsw
- *
- * Return the value of the key field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_key(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.key;
- else
- return scsw->cmd.key;
-}
-EXPORT_SYMBOL(scsw_key);
-
-/**
- * scsw_eswf - return scsw eswf field
- * @scsw: pointer to scsw
- *
- * Return the value of the eswf field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_eswf(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.eswf;
- else
- return scsw->cmd.eswf;
-}
-EXPORT_SYMBOL(scsw_eswf);
-
-/**
- * scsw_cc - return scsw cc field
- * @scsw: pointer to scsw
- *
- * Return the value of the cc field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_cc(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.cc;
- else
- return scsw->cmd.cc;
-}
-EXPORT_SYMBOL(scsw_cc);
-
-/**
- * scsw_ectl - return scsw ectl field
- * @scsw: pointer to scsw
- *
- * Return the value of the ectl field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_ectl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.ectl;
- else
- return scsw->cmd.ectl;
-}
-EXPORT_SYMBOL(scsw_ectl);
-
-/**
- * scsw_pno - return scsw pno field
- * @scsw: pointer to scsw
- *
- * Return the value of the pno field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_pno(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.pno;
- else
- return scsw->cmd.pno;
-}
-EXPORT_SYMBOL(scsw_pno);
-
-/**
- * scsw_fctl - return scsw fctl field
- * @scsw: pointer to scsw
- *
- * Return the value of the fctl field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_fctl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.fctl;
- else
- return scsw->cmd.fctl;
-}
-EXPORT_SYMBOL(scsw_fctl);
-
-/**
- * scsw_actl - return scsw actl field
- * @scsw: pointer to scsw
- *
- * Return the value of the actl field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_actl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.actl;
- else
- return scsw->cmd.actl;
-}
-EXPORT_SYMBOL(scsw_actl);
-
-/**
- * scsw_stctl - return scsw stctl field
- * @scsw: pointer to scsw
- *
- * Return the value of the stctl field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_stctl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.stctl;
- else
- return scsw->cmd.stctl;
-}
-EXPORT_SYMBOL(scsw_stctl);
-
-/**
- * scsw_dstat - return scsw dstat field
- * @scsw: pointer to scsw
- *
- * Return the value of the dstat field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_dstat(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.dstat;
- else
- return scsw->cmd.dstat;
-}
-EXPORT_SYMBOL(scsw_dstat);
-
-/**
- * scsw_cstat - return scsw cstat field
- * @scsw: pointer to scsw
- *
- * Return the value of the cstat field of the specified scsw, regardless of
- * whether it is a transport mode or command mode scsw.
- */
-u32 scsw_cstat(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw->tm.cstat;
- else
- return scsw->cmd.cstat;
-}
-EXPORT_SYMBOL(scsw_cstat);
-
-/**
- * scsw_cmd_is_valid_key - check key field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the key field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_key(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_key);
-
-/**
- * scsw_cmd_is_valid_sctl - check fctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fctl field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_sctl(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_sctl);
-
-/**
- * scsw_cmd_is_valid_eswf - check eswf field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the eswf field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_eswf(union scsw *scsw)
-{
- return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_eswf);
-
-/**
- * scsw_cmd_is_valid_cc - check cc field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the cc field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_cc(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) &&
- (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_cc);
-
-/**
- * scsw_cmd_is_valid_fmt - check fmt field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fmt field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_fmt(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_fmt);
-
-/**
- * scsw_cmd_is_valid_pfch - check pfch field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the pfch field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_pfch(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_pfch);
-
-/**
- * scsw_cmd_is_valid_isic - check isic field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the isic field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_isic(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_isic);
-
-/**
- * scsw_cmd_is_valid_alcc - check alcc field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the alcc field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_alcc(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_alcc);
-
-/**
- * scsw_cmd_is_valid_ssi - check ssi field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the ssi field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_ssi(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_ssi);
-
-/**
- * scsw_cmd_is_valid_zcc - check zcc field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the zcc field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_zcc(union scsw *scsw)
-{
- return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) &&
- (scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_zcc);
-
-/**
- * scsw_cmd_is_valid_ectl - check ectl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the ectl field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_ectl(union scsw *scsw)
-{
- return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
- !(scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) &&
- (scsw->cmd.stctl & SCSW_STCTL_ALERT_STATUS);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_ectl);
-
-/**
- * scsw_cmd_is_valid_pno - check pno field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the pno field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_pno(union scsw *scsw)
-{
- return (scsw->cmd.fctl != 0) &&
- (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
- (!(scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) ||
- ((scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) &&
- (scsw->cmd.actl & SCSW_ACTL_SUSPENDED)));
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_pno);
-
-/**
- * scsw_cmd_is_valid_fctl - check fctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fctl field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_fctl(union scsw *scsw)
-{
- /* Only valid if pmcw.dnv == 1*/
- return 1;
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_fctl);
-
-/**
- * scsw_cmd_is_valid_actl - check actl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the actl field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_actl(union scsw *scsw)
-{
- /* Only valid if pmcw.dnv == 1*/
- return 1;
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_actl);
-
-/**
- * scsw_cmd_is_valid_stctl - check stctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the stctl field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_stctl(union scsw *scsw)
-{
- /* Only valid if pmcw.dnv == 1*/
- return 1;
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_stctl);
-
-/**
- * scsw_cmd_is_valid_dstat - check dstat field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the dstat field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_dstat(union scsw *scsw)
-{
- return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
- (scsw->cmd.cc != 3);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_dstat);
-
-/**
- * scsw_cmd_is_valid_cstat - check cstat field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the cstat field of the specified command mode scsw is
- * valid, zero otherwise.
- */
-int scsw_cmd_is_valid_cstat(union scsw *scsw)
-{
- return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
- (scsw->cmd.cc != 3);
-}
-EXPORT_SYMBOL(scsw_cmd_is_valid_cstat);
-
-/**
- * scsw_tm_is_valid_key - check key field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the key field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_key(union scsw *scsw)
-{
- return (scsw->tm.fctl & SCSW_FCTL_START_FUNC);
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_key);
-
-/**
- * scsw_tm_is_valid_eswf - check eswf field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the eswf field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_eswf(union scsw *scsw)
-{
- return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND);
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_eswf);
-
-/**
- * scsw_tm_is_valid_cc - check cc field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the cc field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_cc(union scsw *scsw)
-{
- return (scsw->tm.fctl & SCSW_FCTL_START_FUNC) &&
- (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND);
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_cc);
-
-/**
- * scsw_tm_is_valid_fmt - check fmt field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fmt field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_fmt(union scsw *scsw)
-{
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_fmt);
-
-/**
- * scsw_tm_is_valid_x - check x field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the x field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_x(union scsw *scsw)
-{
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_x);
-
-/**
- * scsw_tm_is_valid_q - check q field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the q field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_q(union scsw *scsw)
-{
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_q);
-
-/**
- * scsw_tm_is_valid_ectl - check ectl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the ectl field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_ectl(union scsw *scsw)
-{
- return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
- !(scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) &&
- (scsw->tm.stctl & SCSW_STCTL_ALERT_STATUS);
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_ectl);
-
-/**
- * scsw_tm_is_valid_pno - check pno field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the pno field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_pno(union scsw *scsw)
-{
- return (scsw->tm.fctl != 0) &&
- (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
- (!(scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) ||
- ((scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) &&
- (scsw->tm.actl & SCSW_ACTL_SUSPENDED)));
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_pno);
-
-/**
- * scsw_tm_is_valid_fctl - check fctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fctl field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_fctl(union scsw *scsw)
-{
- /* Only valid if pmcw.dnv == 1*/
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_fctl);
-
-/**
- * scsw_tm_is_valid_actl - check actl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the actl field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_actl(union scsw *scsw)
-{
- /* Only valid if pmcw.dnv == 1*/
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_actl);
-
-/**
- * scsw_tm_is_valid_stctl - check stctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the stctl field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_stctl(union scsw *scsw)
-{
- /* Only valid if pmcw.dnv == 1*/
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_stctl);
-
-/**
- * scsw_tm_is_valid_dstat - check dstat field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the dstat field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_dstat(union scsw *scsw)
-{
- return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
- (scsw->tm.cc != 3);
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_dstat);
-
-/**
- * scsw_tm_is_valid_cstat - check cstat field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the cstat field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_cstat(union scsw *scsw)
-{
- return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
- (scsw->tm.cc != 3);
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_cstat);
-
-/**
- * scsw_tm_is_valid_fcxs - check fcxs field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fcxs field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_fcxs(union scsw *scsw)
-{
- return 1;
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_fcxs);
-
-/**
- * scsw_tm_is_valid_schxs - check schxs field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the schxs field of the specified transport mode scsw is
- * valid, zero otherwise.
- */
-int scsw_tm_is_valid_schxs(union scsw *scsw)
-{
- return (scsw->tm.cstat & (SCHN_STAT_PROG_CHECK |
- SCHN_STAT_INTF_CTRL_CHK |
- SCHN_STAT_PROT_CHECK |
- SCHN_STAT_CHN_DATA_CHK));
-}
-EXPORT_SYMBOL(scsw_tm_is_valid_schxs);
-
-/**
- * scsw_is_valid_actl - check actl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the actl field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_actl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_actl(scsw);
- else
- return scsw_cmd_is_valid_actl(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_actl);
-
-/**
- * scsw_is_valid_cc - check cc field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the cc field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_cc(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_cc(scsw);
- else
- return scsw_cmd_is_valid_cc(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_cc);
-
-/**
- * scsw_is_valid_cstat - check cstat field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the cstat field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_cstat(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_cstat(scsw);
- else
- return scsw_cmd_is_valid_cstat(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_cstat);
-
-/**
- * scsw_is_valid_dstat - check dstat field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the dstat field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_dstat(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_dstat(scsw);
- else
- return scsw_cmd_is_valid_dstat(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_dstat);
-
-/**
- * scsw_is_valid_ectl - check ectl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the ectl field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_ectl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_ectl(scsw);
- else
- return scsw_cmd_is_valid_ectl(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_ectl);
-
-/**
- * scsw_is_valid_eswf - check eswf field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the eswf field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_eswf(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_eswf(scsw);
- else
- return scsw_cmd_is_valid_eswf(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_eswf);
-
-/**
- * scsw_is_valid_fctl - check fctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the fctl field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_fctl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_fctl(scsw);
- else
- return scsw_cmd_is_valid_fctl(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_fctl);
-
-/**
- * scsw_is_valid_key - check key field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the key field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_key(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_key(scsw);
- else
- return scsw_cmd_is_valid_key(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_key);
-
-/**
- * scsw_is_valid_pno - check pno field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the pno field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_pno(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_pno(scsw);
- else
- return scsw_cmd_is_valid_pno(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_pno);
-
-/**
- * scsw_is_valid_stctl - check stctl field validity
- * @scsw: pointer to scsw
- *
- * Return non-zero if the stctl field of the specified scsw is valid,
- * regardless of whether it is a transport mode or command mode scsw.
- * Return zero if the field does not contain a valid value.
- */
-int scsw_is_valid_stctl(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_valid_stctl(scsw);
- else
- return scsw_cmd_is_valid_stctl(scsw);
-}
-EXPORT_SYMBOL(scsw_is_valid_stctl);
-
-/**
- * scsw_cmd_is_solicited - check for solicited scsw
- * @scsw: pointer to scsw
- *
- * Return non-zero if the command mode scsw indicates that the associated
- * status condition is solicited, zero if it is unsolicited.
- */
-int scsw_cmd_is_solicited(union scsw *scsw)
-{
- return (scsw->cmd.cc != 0) || (scsw->cmd.stctl !=
- (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS));
-}
-EXPORT_SYMBOL(scsw_cmd_is_solicited);
-
-/**
- * scsw_tm_is_solicited - check for solicited scsw
- * @scsw: pointer to scsw
- *
- * Return non-zero if the transport mode scsw indicates that the associated
- * status condition is solicited, zero if it is unsolicited.
- */
-int scsw_tm_is_solicited(union scsw *scsw)
-{
- return (scsw->tm.cc != 0) || (scsw->tm.stctl !=
- (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS));
-}
-EXPORT_SYMBOL(scsw_tm_is_solicited);
-
-/**
- * scsw_is_solicited - check for solicited scsw
- * @scsw: pointer to scsw
- *
- * Return non-zero if the transport or command mode scsw indicates that the
- * associated status condition is solicited, zero if it is unsolicited.
- */
-int scsw_is_solicited(union scsw *scsw)
-{
- if (scsw_is_tm(scsw))
- return scsw_tm_is_solicited(scsw);
- else
- return scsw_cmd_is_solicited(scsw);
-}
-EXPORT_SYMBOL(scsw_is_solicited);
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index ed3dcdea7fe..090b32a339c 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -648,7 +648,9 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state)
/* Poll on the device until all requests are finished. */
do {
flags = 0;
+ spin_lock_bh(&ap_dev->lock);
__ap_poll_device(ap_dev, &flags);
+ spin_unlock_bh(&ap_dev->lock);
} while ((flags & 1) || (flags & 2));
ap_device_remove(dev);
@@ -1109,12 +1111,15 @@ static void ap_scan_bus(struct work_struct *unused)
ap_dev->device.bus = &ap_bus_type;
ap_dev->device.parent = ap_root_device;
- dev_set_name(&ap_dev->device, "card%02x",
- AP_QID_DEVICE(ap_dev->qid));
+ if (dev_set_name(&ap_dev->device, "card%02x",
+ AP_QID_DEVICE(ap_dev->qid))) {
+ kfree(ap_dev);
+ continue;
+ }
ap_dev->device.release = ap_device_release;
rc = device_register(&ap_dev->device);
if (rc) {
- kfree(ap_dev);
+ put_device(&ap_dev->device);
continue;
}
/* Add device attributes. */
@@ -1407,14 +1412,12 @@ static void ap_reset(struct ap_device *ap_dev)
static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
{
- spin_lock(&ap_dev->lock);
if (!ap_dev->unregistered) {
if (ap_poll_queue(ap_dev, flags))
ap_dev->unregistered = 1;
if (ap_dev->reset == AP_RESET_DO)
ap_reset(ap_dev);
}
- spin_unlock(&ap_dev->lock);
return 0;
}
@@ -1441,7 +1444,9 @@ static void ap_poll_all(unsigned long dummy)
flags = 0;
spin_lock(&ap_device_list_lock);
list_for_each_entry(ap_dev, &ap_device_list, list) {
+ spin_lock(&ap_dev->lock);
__ap_poll_device(ap_dev, &flags);
+ spin_unlock(&ap_dev->lock);
}
spin_unlock(&ap_device_list_lock);
} while (flags & 1);
@@ -1487,7 +1492,9 @@ static int ap_poll_thread(void *data)
flags = 0;
spin_lock_bh(&ap_device_list_lock);
list_for_each_entry(ap_dev, &ap_device_list, list) {
+ spin_lock(&ap_dev->lock);
__ap_poll_device(ap_dev, &flags);
+ spin_unlock(&ap_dev->lock);
}
spin_unlock_bh(&ap_device_list_lock);
}
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index e38e5d306fa..2930fc763ac 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -403,10 +403,14 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count)
return len;
}
-void __init s390_virtio_console_init(void)
+static int __init s390_virtio_console_init(void)
{
- virtio_cons_early_init(early_put_chars);
+ if (!MACHINE_IS_KVM)
+ return -ENODEV;
+ return virtio_cons_early_init(early_put_chars);
}
+console_initcall(s390_virtio_console_init);
+
/*
* We do this after core stuff, but before the drivers.
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index f370f8d460a..c63babefb69 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -350,6 +350,8 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
CLAW_DBF_TEXT_(4, trace, "clawtx%d", rc);
if (rc)
rc = NETDEV_TX_BUSY;
+ else
+ rc = NETDEV_TX_OK;
return rc;
} /* end of claw_tx */
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 222e4739443..c5b83874500 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -164,7 +164,6 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
priv->stats.rx_packets++;
priv->stats.rx_bytes += skblen;
netif_rx_ni(skb);
- dev->last_rx = jiffies;
if (len > 0) {
skb_pull(pskb, header->length);
if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
@@ -880,7 +879,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
"%s(%s): NULL sk_buff passed",
CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
@@ -888,7 +887,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2);
dev_kfree_skb(skb);
priv->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -901,7 +900,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
priv->stats.tx_carrier_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (ctcm_test_and_set_busy(dev))
@@ -910,7 +909,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
return NETDEV_TX_BUSY;
- return 0;
+ return NETDEV_TX_OK;
}
/* unmerged MPC variant of ctcm_tx */
@@ -1008,7 +1007,7 @@ done:
if (do_debug)
MPC_DBF_DEV_NAME(TRACE, dev, "exit");
- return 0; /* handle freeing of skb here */
+ return NETDEV_TX_OK; /* handle freeing of skb here */
}
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 8c675905448..a70de9b4bf2 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1553,24 +1553,24 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
struct net_device *dev)
{
struct lcs_header *header;
- int rc = 0;
+ int rc = NETDEV_TX_OK;
LCS_DBF_TEXT(5, trace, "hardxmit");
if (skb == NULL) {
card->stats.tx_dropped++;
card->stats.tx_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (card->state != DEV_STATE_UP) {
dev_kfree_skb(skb);
card->stats.tx_dropped++;
card->stats.tx_errors++;
card->stats.tx_carrier_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb->protocol == htons(ETH_P_IPV6)) {
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(card->dev);
spin_lock(&card->lock);
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 8c36eafcfbf..9215fbbccc0 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -676,7 +676,6 @@ static void netiucv_unpack_skb(struct iucv_connection *conn,
* we must use netif_rx_ni() instead of netif_rx()
*/
netif_rx_ni(skb);
- dev->last_rx = jiffies;
skb_pull(pskb, header->next);
skb_put(pskb, NETIUCV_HDRLEN);
}
@@ -1376,14 +1375,14 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
if (skb == NULL) {
IUCV_DBF_TEXT(data, 2, "netiucv_tx: skb is NULL\n");
privptr->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb_headroom(skb) < NETIUCV_HDRLEN) {
IUCV_DBF_TEXT(data, 2,
"netiucv_tx: skb_headroom < NETIUCV_HDRLEN\n");
dev_kfree_skb(skb);
privptr->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
/**
@@ -1395,7 +1394,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
privptr->stats.tx_dropped++;
privptr->stats.tx_errors++;
privptr->stats.tx_carrier_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (netiucv_test_and_set_busy(dev)) {
@@ -1839,9 +1838,10 @@ static int netiucv_register_device(struct net_device *ndev)
return -ENOMEM;
ret = device_register(dev);
-
- if (ret)
+ if (ret) {
+ put_device(dev);
return ret;
+ }
ret = netiucv_add_files(dev);
if (ret)
goto out_unreg;
@@ -2226,8 +2226,10 @@ static int __init netiucv_init(void)
netiucv_dev->release = (void (*)(struct device *))kfree;
netiucv_dev->driver = &netiucv_driver;
rc = device_register(netiucv_dev);
- if (rc)
+ if (rc) {
+ put_device(netiucv_dev);
goto out_driver;
+ }
netiucv_banner();
return rc;
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 447e1d19581..31a2b4e502c 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -435,6 +435,7 @@ struct qeth_qdio_out_q {
* index of buffer to be filled by driver; state EMPTY or PACKING
*/
int next_buf_to_fill;
+ int sync_iqdio_error;
/*
* number of buffers that are currently filled (PRIMED)
* -> these buffers are hardware-owned
@@ -685,6 +686,14 @@ struct qeth_mc_mac {
int is_vmac;
};
+struct qeth_skb_data {
+ __u32 magic;
+ int count;
+};
+
+#define QETH_SKB_MAGIC 0x71657468
+#define QETH_SIGA_CC2_RETRIES 3
+
struct qeth_card {
struct list_head list;
enum qeth_card_states state;
@@ -834,7 +843,6 @@ int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
void *reply_param);
-int qeth_get_cast_type(struct qeth_card *, struct sk_buff *);
int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index d53621c4acb..c4a42d97015 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -927,8 +927,8 @@ out:
return;
}
-static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
- struct qeth_qdio_out_buffer *buf)
+static void __qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf, unsigned int qeth_skip_skb)
{
int i;
struct sk_buff *skb;
@@ -937,11 +937,13 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
if (buf->buffer->element[0].flags & 0x40)
atomic_dec(&queue->set_pci_flags_count);
- skb = skb_dequeue(&buf->skb_list);
- while (skb) {
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
+ if (!qeth_skip_skb) {
skb = skb_dequeue(&buf->skb_list);
+ while (skb) {
+ atomic_dec(&skb->users);
+ dev_kfree_skb_any(skb);
+ skb = skb_dequeue(&buf->skb_list);
+ }
}
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
if (buf->buffer->element[i].addr && buf->is_header[i])
@@ -957,6 +959,12 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
}
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf)
+{
+ __qeth_clear_output_buffer(queue, buf, 0);
+}
+
void qeth_clear_qdio_buffers(struct qeth_card *card)
{
int i, j;
@@ -1152,8 +1160,9 @@ static void qeth_core_sl_print(struct seq_file *m, struct service_level *slr)
{
struct qeth_card *card = container_of(slr, struct qeth_card,
qeth_service_level);
- seq_printf(m, "qeth: %s firmware level %s\n", CARD_BUS_ID(card),
- card->info.mcl_level);
+ if (card->info.mcl_level[0])
+ seq_printf(m, "qeth: %s firmware level %s\n",
+ CARD_BUS_ID(card), card->info.mcl_level);
}
static struct qeth_card *qeth_alloc_card(void)
@@ -2685,6 +2694,13 @@ static int qeth_handle_send_error(struct qeth_card *card,
int sbalf15 = buffer->buffer->element[15].flags & 0xff;
QETH_DBF_TEXT(TRACE, 6, "hdsnderr");
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ if (sbalf15 == 0) {
+ qdio_err = 0;
+ } else {
+ qdio_err = 1;
+ }
+ }
qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr");
if (!qdio_err)
@@ -2817,6 +2833,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
}
}
+ queue->sync_iqdio_error = 0;
queue->card->dev->trans_start = jiffies;
if (queue->card->options.performance_stats) {
queue->card->perf_stats.outbound_do_qdio_cnt++;
@@ -2832,6 +2849,10 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
queue->card->perf_stats.outbound_do_qdio_time +=
qeth_get_micros() -
queue->card->perf_stats.outbound_do_qdio_start_time;
+ if (rc > 0) {
+ if (!(rc & QDIO_ERROR_SIGA_BUSY))
+ queue->sync_iqdio_error = rc & 3;
+ }
if (rc) {
queue->card->stats.tx_errors += count;
/* ignore temporary SIGA errors without busy condition */
@@ -2899,6 +2920,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
struct qeth_qdio_out_buffer *buffer;
int i;
+ unsigned qeth_send_err;
QETH_DBF_TEXT(TRACE, 6, "qdouhdl");
if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
@@ -2915,8 +2937,9 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
}
for (i = first_element; i < (first_element + count); ++i) {
buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
- qeth_handle_send_error(card, buffer, qdio_error);
- qeth_clear_output_buffer(queue, buffer);
+ qeth_send_err = qeth_handle_send_error(card, buffer, qdio_error);
+ __qeth_clear_output_buffer(queue, buffer,
+ (qeth_send_err == QETH_SEND_ERROR_RETRY) ? 1 : 0);
}
atomic_sub(count, &queue->used_buffers);
/* check if we need to do something on this outbound queue */
@@ -2930,55 +2953,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
}
EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
-int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
-{
- int cast_type = RTN_UNSPEC;
-
- if (card->info.type == QETH_CARD_TYPE_OSN)
- return cast_type;
-
- if (skb_dst(skb) && skb_dst(skb)->neighbour) {
- cast_type = skb_dst(skb)->neighbour->type;
- if ((cast_type == RTN_BROADCAST) ||
- (cast_type == RTN_MULTICAST) ||
- (cast_type == RTN_ANYCAST))
- return cast_type;
- else
- return RTN_UNSPEC;
- }
- /* try something else */
- if (skb->protocol == ETH_P_IPV6)
- return (skb_network_header(skb)[24] == 0xff) ?
- RTN_MULTICAST : 0;
- else if (skb->protocol == ETH_P_IP)
- return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
- RTN_MULTICAST : 0;
- /* ... */
- if (!memcmp(skb->data, skb->dev->broadcast, 6))
- return RTN_BROADCAST;
- else {
- u16 hdr_mac;
-
- hdr_mac = *((u16 *)skb->data);
- /* tr multicast? */
- switch (card->info.link_type) {
- case QETH_LINK_TYPE_HSTR:
- case QETH_LINK_TYPE_LANE_TR:
- if ((hdr_mac == QETH_TR_MAC_NC) ||
- (hdr_mac == QETH_TR_MAC_C))
- return RTN_MULTICAST;
- break;
- /* eth or so multicast? */
- default:
- if ((hdr_mac == QETH_ETH_MAC_V4) ||
- (hdr_mac == QETH_ETH_MAC_V6))
- return RTN_MULTICAST;
- }
- }
- return cast_type;
-}
-EXPORT_SYMBOL_GPL(qeth_get_cast_type);
-
int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
int ipv, int cast_type)
{
@@ -3159,7 +3133,10 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
int offset, int hd_len)
{
struct qeth_qdio_out_buffer *buffer;
+ struct sk_buff *skb1;
+ struct qeth_skb_data *retry_ctrl;
int index;
+ int rc;
/* spin until we get the queue ... */
while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
@@ -3178,6 +3155,25 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
qeth_flush_buffers(queue, index, 1);
+ if (queue->sync_iqdio_error == 2) {
+ skb1 = skb_dequeue(&buffer->skb_list);
+ while (skb1) {
+ atomic_dec(&skb1->users);
+ skb1 = skb_dequeue(&buffer->skb_list);
+ }
+ retry_ctrl = (struct qeth_skb_data *) &skb->cb[16];
+ if (retry_ctrl->magic != QETH_SKB_MAGIC) {
+ retry_ctrl->magic = QETH_SKB_MAGIC;
+ retry_ctrl->count = 0;
+ }
+ if (retry_ctrl->count < QETH_SIGA_CC2_RETRIES) {
+ retry_ctrl->count++;
+ rc = dev_queue_xmit(skb);
+ } else {
+ dev_kfree_skb_any(skb);
+ QETH_DBF_TEXT(QERR, 2, "qrdrop");
+ }
+ }
return 0;
out:
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 568465d7517..33505c2a0e3 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -364,7 +364,7 @@ static ssize_t qeth_dev_layer2_show(struct device *dev,
if (!card)
return -EINVAL;
- return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
+ return sprintf(buf, "%i\n", card->options.layer2);
}
static ssize_t qeth_dev_layer2_store(struct device *dev,
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 691cecd03b8..f4f3ca1393b 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -216,36 +216,16 @@ static void qeth_l2_del_all_mc(struct qeth_card *card)
spin_unlock_bh(&card->mclock);
}
-static void qeth_l2_get_packet_type(struct qeth_card *card,
- struct qeth_hdr *hdr, struct sk_buff *skb)
+static inline int qeth_l2_get_cast_type(struct qeth_card *card,
+ struct sk_buff *skb)
{
- __u16 hdr_mac;
-
- if (!memcmp(skb->data + QETH_HEADER_SIZE,
- skb->dev->broadcast, 6)) {
- /* broadcast? */
- hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
- return;
- }
- hdr_mac = *((__u16 *)skb->data);
- /* tr multicast? */
- switch (card->info.link_type) {
- case QETH_LINK_TYPE_HSTR:
- case QETH_LINK_TYPE_LANE_TR:
- if ((hdr_mac == QETH_TR_MAC_NC) ||
- (hdr_mac == QETH_TR_MAC_C))
- hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
- else
- hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
- break;
- /* eth or so multicast? */
- default:
- if ((hdr_mac == QETH_ETH_MAC_V4) ||
- (hdr_mac == QETH_ETH_MAC_V6))
- hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
- else
- hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
- }
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return RTN_UNSPEC;
+ if (is_broadcast_ether_addr(skb->data))
+ return RTN_BROADCAST;
+ if (is_multicast_ether_addr(skb->data))
+ return RTN_MULTICAST;
+ return RTN_UNSPEC;
}
static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
@@ -262,7 +242,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
else if (cast_type == RTN_BROADCAST)
hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
else
- qeth_l2_get_packet_type(card, hdr, skb);
+ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
/* VSWITCH relies on the VLAN
@@ -469,7 +449,6 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
continue;
}
- card->dev->last_rx = jiffies;
card->stats.rx_packets++;
card->stats.rx_bytes += len;
}
@@ -672,7 +651,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct qeth_card *card = dev->ml_priv;
struct sk_buff *new_skb = skb;
int ipv = qeth_get_ip_version(skb);
- int cast_type = qeth_get_cast_type(card, skb);
+ int cast_type = qeth_l2_get_cast_type(card, skb);
struct qeth_qdio_out_q *queue = card->qdio.out_qs
[qeth_get_priority_queue(card, skb, ipv, cast_type)];
int tx_bytes = skb->len;
@@ -744,6 +723,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
card->stats.tx_bytes += tx_bytes;
if (new_skb != skb)
dev_kfree_skb_any(skb);
+ rc = NETDEV_TX_OK;
} else {
if (data_offset >= 0)
kmem_cache_free(qeth_core_header_cache, hdr);
@@ -882,7 +862,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
return;
}
-static struct ethtool_ops qeth_l2_ethtool_ops = {
+static const struct ethtool_ops qeth_l2_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_strings = qeth_core_get_strings,
.get_ethtool_stats = qeth_core_get_ethtool_stats,
@@ -891,7 +871,7 @@ static struct ethtool_ops qeth_l2_ethtool_ops = {
.get_settings = qeth_core_ethtool_get_settings,
};
-static struct ethtool_ops qeth_l2_osn_ops = {
+static const struct ethtool_ops qeth_l2_osn_ops = {
.get_strings = qeth_core_get_strings,
.get_ethtool_stats = qeth_core_get_ethtool_stats,
.get_stats_count = qeth_core_get_stats_count,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 54872406864..073b6d35491 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1987,7 +1987,6 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
continue;
}
- card->dev->last_rx = jiffies;
card->stats.rx_packets++;
card->stats.rx_bytes += len;
}
@@ -2525,6 +2524,51 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
+int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
+{
+ int cast_type = RTN_UNSPEC;
+
+ if (skb_dst(skb) && skb_dst(skb)->neighbour) {
+ cast_type = skb_dst(skb)->neighbour->type;
+ if ((cast_type == RTN_BROADCAST) ||
+ (cast_type == RTN_MULTICAST) ||
+ (cast_type == RTN_ANYCAST))
+ return cast_type;
+ else
+ return RTN_UNSPEC;
+ }
+ /* try something else */
+ if (skb->protocol == ETH_P_IPV6)
+ return (skb_network_header(skb)[24] == 0xff) ?
+ RTN_MULTICAST : 0;
+ else if (skb->protocol == ETH_P_IP)
+ return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
+ RTN_MULTICAST : 0;
+ /* ... */
+ if (!memcmp(skb->data, skb->dev->broadcast, 6))
+ return RTN_BROADCAST;
+ else {
+ u16 hdr_mac;
+
+ hdr_mac = *((u16 *)skb->data);
+ /* tr multicast? */
+ switch (card->info.link_type) {
+ case QETH_LINK_TYPE_HSTR:
+ case QETH_LINK_TYPE_LANE_TR:
+ if ((hdr_mac == QETH_TR_MAC_NC) ||
+ (hdr_mac == QETH_TR_MAC_C))
+ return RTN_MULTICAST;
+ break;
+ /* eth or so multicast? */
+ default:
+ if ((hdr_mac == QETH_ETH_MAC_V4) ||
+ (hdr_mac == QETH_ETH_MAC_V6))
+ return RTN_MULTICAST;
+ }
+ }
+ return cast_type;
+}
+
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
@@ -2650,7 +2694,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct qeth_card *card = dev->ml_priv;
struct sk_buff *new_skb = NULL;
int ipv = qeth_get_ip_version(skb);
- int cast_type = qeth_get_cast_type(card, skb);
+ int cast_type = qeth_l3_get_cast_type(card, skb);
struct qeth_qdio_out_q *queue = card->qdio.out_qs
[qeth_get_priority_queue(card, skb, ipv, cast_type)];
int tx_bytes = skb->len;
@@ -2793,6 +2837,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
card->perf_stats.sg_frags_sent += nr_frags + 1;
}
}
+ rc = NETDEV_TX_OK;
} else {
if (data_offset >= 0)
kmem_cache_free(qeth_core_header_cache, hdr);
@@ -2900,7 +2945,7 @@ static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
return 0;
}
-static struct ethtool_ops qeth_l3_ethtool_ops = {
+static const struct ethtool_ops qeth_l3_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = ethtool_op_set_tx_hw_csum,
@@ -3179,6 +3224,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
netif_carrier_on(card->dev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
+ qeth_l3_set_ip_addr_list(card);
if (recover_flag == CARD_STATE_RECOVER) {
if (recovery_mode)
qeth_l3_open(card->dev);
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index e76a320d373..102000d1af6 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -219,13 +219,13 @@ static int __init smsg_init(void)
smsg_dev->driver = &smsg_driver;
rc = device_register(smsg_dev);
if (rc)
- goto out_free_dev;
+ goto out_put;
cpcmd("SET SMSG IUCV", NULL, 0, NULL);
return 0;
-out_free_dev:
- kfree(smsg_dev);
+out_put:
+ put_device(smsg_dev);
out_free_path:
iucv_path_free(smsg_path);
smsg_path = NULL;
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 2ccbd185a5f..1be6bf7e8ce 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -42,6 +42,12 @@ static char *init_device;
module_param_named(device, init_device, charp, 0400);
MODULE_PARM_DESC(device, "specify initial device");
+static struct kmem_cache *zfcp_cache_hw_align(const char *name,
+ unsigned long size)
+{
+ return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL);
+}
+
static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
{
int idx;
@@ -78,7 +84,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
struct zfcp_port *port;
struct zfcp_unit *unit;
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
read_lock_irq(&zfcp_data.config_lock);
adapter = zfcp_get_adapter_by_busid(busid);
if (adapter)
@@ -93,31 +99,23 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
unit = zfcp_unit_enqueue(port, lun);
if (IS_ERR(unit))
goto out_unit;
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
ccw_device_set_online(adapter->ccw_device);
zfcp_erp_wait(adapter);
flush_work(&unit->scsi_work);
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
zfcp_unit_put(unit);
out_unit:
zfcp_port_put(port);
out_port:
zfcp_adapter_put(adapter);
out_adapter:
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
return;
}
-static struct kmem_cache *zfcp_cache_create(int size, char *name)
-{
- int align = 1;
- while ((size - align) > 0)
- align <<= 1;
- return kmem_cache_create(name , size, align, 0, NULL);
-}
-
static void __init zfcp_init_device_setup(char *devstr)
{
char *token;
@@ -158,24 +156,27 @@ static int __init zfcp_module_init(void)
{
int retval = -ENOMEM;
- zfcp_data.fsf_req_qtcb_cache = zfcp_cache_create(
- sizeof(struct zfcp_fsf_req_qtcb), "zfcp_fsf");
- if (!zfcp_data.fsf_req_qtcb_cache)
+ zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn",
+ sizeof(struct ct_iu_gpn_ft_req));
+ if (!zfcp_data.gpn_ft_cache)
goto out;
- zfcp_data.sr_buffer_cache = zfcp_cache_create(
- sizeof(struct fsf_status_read_buffer), "zfcp_sr");
+ zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb",
+ sizeof(struct fsf_qtcb));
+ if (!zfcp_data.qtcb_cache)
+ goto out_qtcb_cache;
+
+ zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr",
+ sizeof(struct fsf_status_read_buffer));
if (!zfcp_data.sr_buffer_cache)
goto out_sr_cache;
- zfcp_data.gid_pn_cache = zfcp_cache_create(
- sizeof(struct zfcp_gid_pn_data), "zfcp_gid");
+ zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid",
+ sizeof(struct zfcp_gid_pn_data));
if (!zfcp_data.gid_pn_cache)
goto out_gid_cache;
- zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq");
-
- sema_init(&zfcp_data.config_sema, 1);
+ mutex_init(&zfcp_data.config_mutex);
rwlock_init(&zfcp_data.config_lock);
zfcp_data.scsi_transport_template =
@@ -209,7 +210,9 @@ out_transport:
out_gid_cache:
kmem_cache_destroy(zfcp_data.sr_buffer_cache);
out_sr_cache:
- kmem_cache_destroy(zfcp_data.fsf_req_qtcb_cache);
+ kmem_cache_destroy(zfcp_data.qtcb_cache);
+out_qtcb_cache:
+ kmem_cache_destroy(zfcp_data.gpn_ft_cache);
out:
return retval;
}
@@ -263,7 +266,7 @@ static void zfcp_sysfs_unit_release(struct device *dev)
* @port: pointer to port where unit is added
* @fcp_lun: FCP LUN of unit to be enqueued
* Returns: pointer to enqueued unit on success, ERR_PTR on error
- * Locks: config_sema must be held to serialize changes to the unit list
+ * Locks: config_mutex must be held to serialize changes to the unit list
*
* Sets up some unit internal structures and creates sysfs entry.
*/
@@ -271,6 +274,13 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
+ read_lock_irq(&zfcp_data.config_lock);
+ if (zfcp_get_unit_by_lun(port, fcp_lun)) {
+ read_unlock_irq(&zfcp_data.config_lock);
+ return ERR_PTR(-EINVAL);
+ }
+ read_unlock_irq(&zfcp_data.config_lock);
+
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
if (!unit)
return ERR_PTR(-ENOMEM);
@@ -282,8 +292,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
unit->port = port;
unit->fcp_lun = fcp_lun;
- dev_set_name(&unit->sysfs_device, "0x%016llx",
- (unsigned long long) fcp_lun);
+ if (dev_set_name(&unit->sysfs_device, "0x%016llx",
+ (unsigned long long) fcp_lun)) {
+ kfree(unit);
+ return ERR_PTR(-ENOMEM);
+ }
unit->sysfs_device.parent = &port->sysfs_device;
unit->sysfs_device.release = zfcp_sysfs_unit_release;
dev_set_drvdata(&unit->sysfs_device, unit);
@@ -299,20 +312,15 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
unit->latencies.cmd.channel.min = 0xFFFFFFFF;
unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
- read_lock_irq(&zfcp_data.config_lock);
- if (zfcp_get_unit_by_lun(port, fcp_lun)) {
- read_unlock_irq(&zfcp_data.config_lock);
- goto err_out_free;
+ if (device_register(&unit->sysfs_device)) {
+ put_device(&unit->sysfs_device);
+ return ERR_PTR(-EINVAL);
}
- read_unlock_irq(&zfcp_data.config_lock);
-
- if (device_register(&unit->sysfs_device))
- goto err_out_free;
if (sysfs_create_group(&unit->sysfs_device.kobj,
&zfcp_sysfs_unit_attrs)) {
device_unregister(&unit->sysfs_device);
- return ERR_PTR(-EIO);
+ return ERR_PTR(-EINVAL);
}
zfcp_unit_get(unit);
@@ -327,10 +335,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
zfcp_port_get(port);
return unit;
-
-err_out_free:
- kfree(unit);
- return ERR_PTR(-EINVAL);
}
/**
@@ -353,37 +357,47 @@ void zfcp_unit_dequeue(struct zfcp_unit *unit)
static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
- /* must only be called with zfcp_data.config_sema taken */
- adapter->pool.fsf_req_erp =
- mempool_create_slab_pool(1, zfcp_data.fsf_req_qtcb_cache);
- if (!adapter->pool.fsf_req_erp)
+ /* must only be called with zfcp_data.config_mutex taken */
+ adapter->pool.erp_req =
+ mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+ if (!adapter->pool.erp_req)
+ return -ENOMEM;
+
+ adapter->pool.gid_pn_req =
+ mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+ if (!adapter->pool.gid_pn_req)
return -ENOMEM;
- adapter->pool.fsf_req_scsi =
- mempool_create_slab_pool(1, zfcp_data.fsf_req_qtcb_cache);
- if (!adapter->pool.fsf_req_scsi)
+ adapter->pool.scsi_req =
+ mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+ if (!adapter->pool.scsi_req)
return -ENOMEM;
- adapter->pool.fsf_req_abort =
- mempool_create_slab_pool(1, zfcp_data.fsf_req_qtcb_cache);
- if (!adapter->pool.fsf_req_abort)
+ adapter->pool.scsi_abort =
+ mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+ if (!adapter->pool.scsi_abort)
return -ENOMEM;
- adapter->pool.fsf_req_status_read =
+ adapter->pool.status_read_req =
mempool_create_kmalloc_pool(FSF_STATUS_READS_RECOM,
sizeof(struct zfcp_fsf_req));
- if (!adapter->pool.fsf_req_status_read)
+ if (!adapter->pool.status_read_req)
return -ENOMEM;
- adapter->pool.data_status_read =
+ adapter->pool.qtcb_pool =
+ mempool_create_slab_pool(4, zfcp_data.qtcb_cache);
+ if (!adapter->pool.qtcb_pool)
+ return -ENOMEM;
+
+ adapter->pool.status_read_data =
mempool_create_slab_pool(FSF_STATUS_READS_RECOM,
zfcp_data.sr_buffer_cache);
- if (!adapter->pool.data_status_read)
+ if (!adapter->pool.status_read_data)
return -ENOMEM;
- adapter->pool.data_gid_pn =
+ adapter->pool.gid_pn_data =
mempool_create_slab_pool(1, zfcp_data.gid_pn_cache);
- if (!adapter->pool.data_gid_pn)
+ if (!adapter->pool.gid_pn_data)
return -ENOMEM;
return 0;
@@ -391,19 +405,21 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
{
- /* zfcp_data.config_sema must be held */
- if (adapter->pool.fsf_req_erp)
- mempool_destroy(adapter->pool.fsf_req_erp);
- if (adapter->pool.fsf_req_scsi)
- mempool_destroy(adapter->pool.fsf_req_scsi);
- if (adapter->pool.fsf_req_abort)
- mempool_destroy(adapter->pool.fsf_req_abort);
- if (adapter->pool.fsf_req_status_read)
- mempool_destroy(adapter->pool.fsf_req_status_read);
- if (adapter->pool.data_status_read)
- mempool_destroy(adapter->pool.data_status_read);
- if (adapter->pool.data_gid_pn)
- mempool_destroy(adapter->pool.data_gid_pn);
+ /* zfcp_data.config_mutex must be held */
+ if (adapter->pool.erp_req)
+ mempool_destroy(adapter->pool.erp_req);
+ if (adapter->pool.scsi_req)
+ mempool_destroy(adapter->pool.scsi_req);
+ if (adapter->pool.scsi_abort)
+ mempool_destroy(adapter->pool.scsi_abort);
+ if (adapter->pool.qtcb_pool)
+ mempool_destroy(adapter->pool.qtcb_pool);
+ if (adapter->pool.status_read_req)
+ mempool_destroy(adapter->pool.status_read_req);
+ if (adapter->pool.status_read_data)
+ mempool_destroy(adapter->pool.status_read_data);
+ if (adapter->pool.gid_pn_data)
+ mempool_destroy(adapter->pool.gid_pn_data);
}
/**
@@ -418,7 +434,7 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
int zfcp_status_read_refill(struct zfcp_adapter *adapter)
{
while (atomic_read(&adapter->stat_miss) > 0)
- if (zfcp_fsf_status_read(adapter)) {
+ if (zfcp_fsf_status_read(adapter->qdio)) {
if (atomic_read(&adapter->stat_miss) >= 16) {
zfcp_erp_adapter_reopen(adapter, 0, "axsref1",
NULL);
@@ -446,6 +462,27 @@ static void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
adapter->fsf_lic_version);
}
+static int zfcp_setup_adapter_work_queue(struct zfcp_adapter *adapter)
+{
+ char name[TASK_COMM_LEN];
+
+ snprintf(name, sizeof(name), "zfcp_q_%s",
+ dev_name(&adapter->ccw_device->dev));
+ adapter->work_queue = create_singlethread_workqueue(name);
+
+ if (adapter->work_queue)
+ return 0;
+ return -ENOMEM;
+}
+
+static void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter)
+{
+ if (adapter->work_queue)
+ destroy_workqueue(adapter->work_queue);
+ adapter->work_queue = NULL;
+
+}
+
/**
* zfcp_adapter_enqueue - enqueue a new adapter to the list
* @ccw_device: pointer to the struct cc_device
@@ -455,7 +492,7 @@ static void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
* Enqueues an adapter at the end of the adapter list in the driver data.
* All adapter internal structures are set up.
* Proc-fs entries are also created.
- * locks: config_sema must be held to serialise changes to the adapter list
+ * locks: config_mutex must be held to serialize changes to the adapter list
*/
int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
{
@@ -463,37 +500,37 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
/*
* Note: It is safe to release the list_lock, as any list changes
- * are protected by the config_sema, which must be held to get here
+ * are protected by the config_mutex, which must be held to get here
*/
adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
if (!adapter)
return -ENOMEM;
- adapter->gs = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL);
- if (!adapter->gs) {
- kfree(adapter);
- return -ENOMEM;
- }
-
ccw_device->handler = NULL;
adapter->ccw_device = ccw_device;
atomic_set(&adapter->refcount, 0);
- if (zfcp_qdio_allocate(adapter))
- goto qdio_allocate_failed;
+ if (zfcp_qdio_setup(adapter))
+ goto qdio_failed;
if (zfcp_allocate_low_mem_buffers(adapter))
- goto failed_low_mem_buffers;
+ goto low_mem_buffers_failed;
if (zfcp_reqlist_alloc(adapter))
- goto failed_low_mem_buffers;
+ goto low_mem_buffers_failed;
- if (zfcp_adapter_debug_register(adapter))
+ if (zfcp_dbf_adapter_register(adapter))
goto debug_register_failed;
+ if (zfcp_setup_adapter_work_queue(adapter))
+ goto work_queue_failed;
+
+ if (zfcp_fc_gs_setup(adapter))
+ goto generic_services_failed;
+
init_waitqueue_head(&adapter->remove_wq);
- init_waitqueue_head(&adapter->erp_thread_wqh);
+ init_waitqueue_head(&adapter->erp_ready_wq);
init_waitqueue_head(&adapter->erp_done_wqh);
INIT_LIST_HEAD(&adapter->port_list_head);
@@ -502,20 +539,14 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
spin_lock_init(&adapter->req_list_lock);
- spin_lock_init(&adapter->hba_dbf_lock);
- spin_lock_init(&adapter->san_dbf_lock);
- spin_lock_init(&adapter->scsi_dbf_lock);
- spin_lock_init(&adapter->rec_dbf_lock);
- spin_lock_init(&adapter->req_q_lock);
- spin_lock_init(&adapter->qdio_stat_lock);
-
rwlock_init(&adapter->erp_lock);
rwlock_init(&adapter->abort_lock);
- sema_init(&adapter->erp_ready_sem, 0);
+ if (zfcp_erp_thread_setup(adapter))
+ goto erp_thread_failed;
INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
- INIT_WORK(&adapter->scan_work, _zfcp_scan_ports_later);
+ INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later);
adapter->service_level.seq_print = zfcp_print_sl;
@@ -529,20 +560,25 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
goto sysfs_failed;
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
- zfcp_fc_wka_ports_init(adapter);
if (!zfcp_adapter_scsi_register(adapter))
return 0;
sysfs_failed:
- zfcp_adapter_debug_unregister(adapter);
+ zfcp_erp_thread_kill(adapter);
+erp_thread_failed:
+ zfcp_fc_gs_destroy(adapter);
+generic_services_failed:
+ zfcp_destroy_adapter_work_queue(adapter);
+work_queue_failed:
+ zfcp_dbf_adapter_unregister(adapter->dbf);
debug_register_failed:
dev_set_drvdata(&ccw_device->dev, NULL);
kfree(adapter->req_list);
-failed_low_mem_buffers:
+low_mem_buffers_failed:
zfcp_free_low_mem_buffers(adapter);
-qdio_allocate_failed:
- zfcp_qdio_free(adapter);
+qdio_failed:
+ zfcp_qdio_destroy(adapter->qdio);
kfree(adapter);
return -ENOMEM;
}
@@ -559,6 +595,7 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
cancel_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
+ zfcp_fc_wka_ports_force_offline(adapter->gs);
zfcp_adapter_scsi_unregister(adapter);
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_adapter_attrs);
@@ -570,13 +607,15 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
if (!retval)
return;
- zfcp_adapter_debug_unregister(adapter);
- zfcp_qdio_free(adapter);
+ zfcp_fc_gs_destroy(adapter);
+ zfcp_erp_thread_kill(adapter);
+ zfcp_destroy_adapter_work_queue(adapter);
+ zfcp_dbf_adapter_unregister(adapter->dbf);
zfcp_free_low_mem_buffers(adapter);
+ zfcp_qdio_destroy(adapter->qdio);
kfree(adapter->req_list);
kfree(adapter->fc_stats);
kfree(adapter->stats_reset_data);
- kfree(adapter->gs);
kfree(adapter);
}
@@ -592,7 +631,7 @@ static void zfcp_sysfs_port_release(struct device *dev)
* @status: initial status for the port
* @d_id: destination id of the remote port to be enqueued
* Returns: pointer to enqueued port on success, ERR_PTR on error
- * Locks: config_sema must be held to serialize changes to the port list
+ * Locks: config_mutex must be held to serialize changes to the port list
*
* All port internal structures are set up and the sysfs entry is generated.
* d_id is used to enqueue ports with a well known address like the Directory
@@ -602,7 +641,13 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
u32 status, u32 d_id)
{
struct zfcp_port *port;
- int retval;
+
+ read_lock_irq(&zfcp_data.config_lock);
+ if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
+ read_unlock_irq(&zfcp_data.config_lock);
+ return ERR_PTR(-EINVAL);
+ }
+ read_unlock_irq(&zfcp_data.config_lock);
port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
if (!port)
@@ -610,7 +655,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
init_waitqueue_head(&port->remove_wq);
INIT_LIST_HEAD(&port->unit_list_head);
- INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);
+ INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
@@ -623,29 +668,24 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set(&port->refcount, 0);
- dev_set_name(&port->sysfs_device, "0x%016llx",
- (unsigned long long)wwpn);
+ if (dev_set_name(&port->sysfs_device, "0x%016llx",
+ (unsigned long long)wwpn)) {
+ kfree(port);
+ return ERR_PTR(-ENOMEM);
+ }
port->sysfs_device.parent = &adapter->ccw_device->dev;
-
port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port);
- read_lock_irq(&zfcp_data.config_lock);
- if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
- read_unlock_irq(&zfcp_data.config_lock);
- goto err_out_free;
+ if (device_register(&port->sysfs_device)) {
+ put_device(&port->sysfs_device);
+ return ERR_PTR(-EINVAL);
}
- read_unlock_irq(&zfcp_data.config_lock);
- if (device_register(&port->sysfs_device))
- goto err_out_free;
-
- retval = sysfs_create_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_port_attrs);
-
- if (retval) {
+ if (sysfs_create_group(&port->sysfs_device.kobj,
+ &zfcp_sysfs_port_attrs)) {
device_unregister(&port->sysfs_device);
- goto err_out;
+ return ERR_PTR(-EINVAL);
}
zfcp_port_get(port);
@@ -659,11 +699,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
zfcp_adapter_get(adapter);
return port;
-
-err_out_free:
- kfree(port);
-err_out:
- return ERR_PTR(-EINVAL);
}
/**
@@ -672,12 +707,11 @@ err_out:
*/
void zfcp_port_dequeue(struct zfcp_port *port)
{
- wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
write_lock_irq(&zfcp_data.config_lock);
list_del(&port->list);
write_unlock_irq(&zfcp_data.config_lock);
- if (port->rport)
- port->rport->dd_data = NULL;
+ wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
+ cancel_work_sync(&port->rport_work); /* usually not necessary */
zfcp_adapter_put(port->adapter);
sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
device_unregister(&port->sysfs_device);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index d9da5c42ccb..0c90f8e7160 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -18,12 +18,15 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev)
{
struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
- down(&zfcp_data.config_sema);
+ if (!adapter)
+ return 0;
+
+ mutex_lock(&zfcp_data.config_mutex);
zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
zfcp_erp_wait(adapter);
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
return 0;
}
@@ -33,6 +36,9 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
{
struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
+ if (!adapter)
+ return 0;
+
zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -63,25 +69,14 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
* zfcp_ccw_probe - probe function of zfcp driver
* @ccw_device: pointer to belonging ccw device
*
- * This function gets called by the common i/o layer and sets up the initial
- * data structures for each fcp adapter, which was detected by the system.
- * Also the sysfs files for this adapter will be created by this function.
- * In addition the nameserver port will be added to the ports of the adapter
- * and its sysfs representation will be created too.
+ * This function gets called by the common i/o layer for each FCP
+ * device found on the current system. This is only a stub to make cio
+ * work: To only allocate adapter resources for devices actually used,
+ * the allocation is deferred to the first call to ccw_set_online.
*/
static int zfcp_ccw_probe(struct ccw_device *ccw_device)
{
- int retval = 0;
-
- down(&zfcp_data.config_sema);
- if (zfcp_adapter_enqueue(ccw_device)) {
- dev_err(&ccw_device->dev,
- "Setting up data structures for the "
- "FCP adapter failed\n");
- retval = -EINVAL;
- }
- up(&zfcp_data.config_sema);
- return retval;
+ return 0;
}
/**
@@ -102,8 +97,11 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
LIST_HEAD(port_remove_lh);
ccw_device_set_offline(ccw_device);
- down(&zfcp_data.config_sema);
+
+ mutex_lock(&zfcp_data.config_mutex);
adapter = dev_get_drvdata(&ccw_device->dev);
+ if (!adapter)
+ goto out;
write_lock_irq(&zfcp_data.config_lock);
list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
@@ -129,29 +127,41 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
zfcp_adapter_dequeue(adapter);
- up(&zfcp_data.config_sema);
+out:
+ mutex_unlock(&zfcp_data.config_mutex);
}
/**
* zfcp_ccw_set_online - set_online function of zfcp driver
* @ccw_device: pointer to belonging ccw device
*
- * This function gets called by the common i/o layer and sets an adapter
- * into state online. Setting an fcp device online means that it will be
- * registered with the SCSI stack, that the QDIO queues will be set up
- * and that the adapter will be opened (asynchronously).
+ * This function gets called by the common i/o layer and sets an
+ * adapter into state online. The first call will allocate all
+ * adapter resources that will be retained until the device is removed
+ * via zfcp_ccw_remove.
+ *
+ * Setting an fcp device online means that it will be registered with
+ * the SCSI stack, that the QDIO queues will be set up and that the
+ * adapter will be opened.
*/
static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
{
struct zfcp_adapter *adapter;
- int retval;
+ int ret = 0;
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
adapter = dev_get_drvdata(&ccw_device->dev);
- retval = zfcp_erp_thread_setup(adapter);
- if (retval)
- goto out;
+ if (!adapter) {
+ ret = zfcp_adapter_enqueue(ccw_device);
+ if (ret) {
+ dev_err(&ccw_device->dev,
+ "Setting up data structures for the "
+ "FCP adapter failed\n");
+ goto out;
+ }
+ adapter = dev_get_drvdata(&ccw_device->dev);
+ }
/* initialize request counter */
BUG_ON(!zfcp_reqlist_isempty(adapter));
@@ -162,13 +172,11 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"ccsonl2", NULL);
zfcp_erp_wait(adapter);
- up(&zfcp_data.config_sema);
- flush_work(&adapter->scan_work);
- return 0;
-
- out:
- up(&zfcp_data.config_sema);
- return retval;
+out:
+ mutex_unlock(&zfcp_data.config_mutex);
+ if (!ret)
+ flush_work(&adapter->scan_work);
+ return ret;
}
/**
@@ -182,12 +190,15 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
{
struct zfcp_adapter *adapter;
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
adapter = dev_get_drvdata(&ccw_device->dev);
+ if (!adapter)
+ goto out;
+
zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
zfcp_erp_wait(adapter);
- zfcp_erp_thread_kill(adapter);
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
+out:
return 0;
}
@@ -240,11 +251,12 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
{
struct zfcp_adapter *adapter;
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
adapter = dev_get_drvdata(&cdev->dev);
zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
zfcp_erp_wait(adapter);
- up(&zfcp_data.config_sema);
+ zfcp_erp_thread_kill(adapter);
+ mutex_unlock(&zfcp_data.config_mutex);
}
static struct ccw_driver zfcp_ccw_driver = {
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index b99b87ce5a3..215b70749e9 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -3,7 +3,7 @@
*
* Debug traces for zfcp.
*
- * Copyright IBM Corporation 2002, 2008
+ * Copyright IBM Corporation 2002, 2009
*/
#define KMSG_COMPONENT "zfcp"
@@ -11,6 +11,7 @@
#include <linux/ctype.h>
#include <asm/debug.h>
+#include "zfcp_dbf.h"
#include "zfcp_ext.h"
static u32 dbfsize = 4;
@@ -37,19 +38,6 @@ static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
}
}
-/* FIXME: this duplicate this code in s390 debug feature */
-static void zfcp_dbf_timestamp(unsigned long long stck, struct timespec *time)
-{
- unsigned long long sec;
-
- stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
- sec = stck >> 12;
- do_div(sec, 1000000);
- time->tv_sec = sec;
- stck -= (sec * 1000000) << 12;
- time->tv_nsec = ((stck * 1000) >> 12);
-}
-
static void zfcp_dbf_tag(char **p, const char *label, const char *tag)
{
int i;
@@ -106,7 +94,7 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
char *p = out_buf;
if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
- zfcp_dbf_timestamp(entry->id.stck, &t);
+ stck_to_timespec(entry->id.stck, &t);
zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu",
t.tv_sec, t.tv_nsec);
zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
@@ -119,13 +107,10 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
return p - out_buf;
}
-/**
- * zfcp_hba_dbf_event_fsf_response - trace event for request completion
- * @fsf_req: request that has been completed
- */
-void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
+ struct zfcp_fsf_req *fsf_req,
+ struct zfcp_dbf *dbf)
{
- struct zfcp_adapter *adapter = fsf_req->adapter;
struct fsf_qtcb *qtcb = fsf_req->qtcb;
union fsf_prot_status_qual *prot_status_qual =
&qtcb->prefix.prot_status_qual;
@@ -134,33 +119,14 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
struct zfcp_port *port;
struct zfcp_unit *unit;
struct zfcp_send_els *send_els;
- struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
- struct zfcp_hba_dbf_record_response *response = &rec->u.response;
- int level;
+ struct zfcp_dbf_hba_record *rec = &dbf->hba_buf;
+ struct zfcp_dbf_hba_record_response *response = &rec->u.response;
unsigned long flags;
- spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->hba_lock, flags);
memset(rec, 0, sizeof(*rec));
strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
-
- if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
- (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
- strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE);
- level = 1;
- } else if (qtcb->header.fsf_status != FSF_GOOD) {
- strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE);
- level = 1;
- } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
- (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
- strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
- level = 4;
- } else if (qtcb->header.log_length) {
- strncpy(rec->tag2, "qtcb", ZFCP_DBF_TAG_SIZE);
- level = 5;
- } else {
- strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
- level = 6;
- }
+ strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
response->fsf_command = fsf_req->fsf_command;
response->fsf_reqid = fsf_req->req_id;
@@ -173,9 +139,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
memcpy(response->fsf_status_qual,
fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
response->fsf_req_status = fsf_req->status;
- response->sbal_first = fsf_req->sbal_first;
- response->sbal_last = fsf_req->sbal_last;
- response->sbal_response = fsf_req->sbal_response;
+ response->sbal_first = fsf_req->queue_req.sbal_first;
+ response->sbal_last = fsf_req->queue_req.sbal_last;
+ response->sbal_response = fsf_req->queue_req.sbal_response;
response->pool = fsf_req->pool != NULL;
response->erp_action = (unsigned long)fsf_req->erp_action;
@@ -224,7 +190,7 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
break;
}
- debug_event(adapter->hba_dbf, level, rec, sizeof(*rec));
+ debug_event(dbf->hba, level, rec, sizeof(*rec));
/* have fcp channel microcode fixed to use as little as possible */
if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) {
@@ -232,31 +198,25 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
char *buf = (char *)qtcb + qtcb->header.log_start;
int len = qtcb->header.log_length;
for (; len && !buf[len - 1]; len--);
- zfcp_dbf_hexdump(adapter->hba_dbf, rec, sizeof(*rec), level,
- buf, len);
+ zfcp_dbf_hexdump(dbf->hba, rec, sizeof(*rec), level, buf,
+ len);
}
- spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ spin_unlock_irqrestore(&dbf->hba_lock, flags);
}
-/**
- * zfcp_hba_dbf_event_fsf_unsol - trace event for an unsolicited status buffer
- * @tag: tag indicating which kind of unsolicited status has been received
- * @adapter: adapter that has issued the unsolicited status buffer
- * @status_buffer: buffer containing payload of unsolicited status
- */
-void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
- struct fsf_status_read_buffer *status_buffer)
+void _zfcp_dbf_hba_fsf_unsol(const char *tag, int level, struct zfcp_dbf *dbf,
+ struct fsf_status_read_buffer *status_buffer)
{
- struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+ struct zfcp_dbf_hba_record *rec = &dbf->hba_buf;
unsigned long flags;
- spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->hba_lock, flags);
memset(rec, 0, sizeof(*rec));
strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
- rec->u.status.failed = atomic_read(&adapter->stat_miss);
+ rec->u.status.failed = atomic_read(&dbf->adapter->stat_miss);
if (status_buffer != NULL) {
rec->u.status.status_type = status_buffer->status_type;
rec->u.status.status_subtype = status_buffer->status_subtype;
@@ -293,63 +253,61 @@ void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
&status_buffer->payload, rec->u.status.payload_size);
}
- debug_event(adapter->hba_dbf, 2, rec, sizeof(*rec));
- spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ debug_event(dbf->hba, level, rec, sizeof(*rec));
+ spin_unlock_irqrestore(&dbf->hba_lock, flags);
}
/**
- * zfcp_hba_dbf_event_qdio - trace event for QDIO related failure
- * @adapter: adapter affected by this QDIO related event
+ * zfcp_dbf_hba_qdio - trace event for QDIO related failure
+ * @qdio: qdio structure affected by this QDIO related event
* @qdio_error: as passed by qdio module
* @sbal_index: first buffer with error condition, as passed by qdio module
* @sbal_count: number of buffers affected, as passed by qdio module
*/
-void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter,
- unsigned int qdio_error, int sbal_index,
- int sbal_count)
+void zfcp_dbf_hba_qdio(struct zfcp_dbf *dbf, unsigned int qdio_error,
+ int sbal_index, int sbal_count)
{
- struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+ struct zfcp_dbf_hba_record *r = &dbf->hba_buf;
unsigned long flags;
- spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->hba_lock, flags);
memset(r, 0, sizeof(*r));
strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
r->u.qdio.qdio_error = qdio_error;
r->u.qdio.sbal_index = sbal_index;
r->u.qdio.sbal_count = sbal_count;
- debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
- spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ debug_event(dbf->hba, 0, r, sizeof(*r));
+ spin_unlock_irqrestore(&dbf->hba_lock, flags);
}
/**
- * zfcp_hba_dbf_event_berr - trace event for bit error threshold
- * @adapter: adapter affected by this QDIO related event
+ * zfcp_dbf_hba_berr - trace event for bit error threshold
+ * @dbf: dbf structure affected by this QDIO related event
* @req: fsf request
*/
-void zfcp_hba_dbf_event_berr(struct zfcp_adapter *adapter,
- struct zfcp_fsf_req *req)
+void zfcp_dbf_hba_berr(struct zfcp_dbf *dbf, struct zfcp_fsf_req *req)
{
- struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+ struct zfcp_dbf_hba_record *r = &dbf->hba_buf;
struct fsf_status_read_buffer *sr_buf = req->data;
struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
unsigned long flags;
- spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->hba_lock, flags);
memset(r, 0, sizeof(*r));
strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE);
memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload));
- debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
- spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ debug_event(dbf->hba, 0, r, sizeof(*r));
+ spin_unlock_irqrestore(&dbf->hba_lock, flags);
}
-static void zfcp_hba_dbf_view_response(char **p,
- struct zfcp_hba_dbf_record_response *r)
+static void zfcp_dbf_hba_view_response(char **p,
+ struct zfcp_dbf_hba_record_response *r)
{
struct timespec t;
zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command);
zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno);
- zfcp_dbf_timestamp(r->fsf_issued, &t);
+ stck_to_timespec(r->fsf_issued, &t);
zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status);
zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status);
@@ -403,8 +361,8 @@ static void zfcp_hba_dbf_view_response(char **p,
}
}
-static void zfcp_hba_dbf_view_status(char **p,
- struct zfcp_hba_dbf_record_status *r)
+static void zfcp_dbf_hba_view_status(char **p,
+ struct zfcp_dbf_hba_record_status *r)
{
zfcp_dbf_out(p, "failed", "0x%02x", r->failed);
zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type);
@@ -416,14 +374,14 @@ static void zfcp_hba_dbf_view_status(char **p,
r->payload_size);
}
-static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
+static void zfcp_dbf_hba_view_qdio(char **p, struct zfcp_dbf_hba_record_qdio *r)
{
zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
}
-static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r)
+static void zfcp_dbf_hba_view_berr(char **p, struct fsf_bit_error_payload *r)
{
zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count);
zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count);
@@ -447,10 +405,10 @@ static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r)
r->current_transmit_b2b_credit);
}
-static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_hba_view_format(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
- struct zfcp_hba_dbf_record *r = (struct zfcp_hba_dbf_record *)in_buf;
+ struct zfcp_dbf_hba_record *r = (struct zfcp_dbf_hba_record *)in_buf;
char *p = out_buf;
if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
@@ -461,45 +419,42 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_tag(&p, "tag2", r->tag2);
if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
- zfcp_hba_dbf_view_response(&p, &r->u.response);
+ zfcp_dbf_hba_view_response(&p, &r->u.response);
else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
- zfcp_hba_dbf_view_status(&p, &r->u.status);
+ zfcp_dbf_hba_view_status(&p, &r->u.status);
else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
- zfcp_hba_dbf_view_qdio(&p, &r->u.qdio);
+ zfcp_dbf_hba_view_qdio(&p, &r->u.qdio);
else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
- zfcp_hba_dbf_view_berr(&p, &r->u.berr);
+ zfcp_dbf_hba_view_berr(&p, &r->u.berr);
if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0)
p += sprintf(p, "\n");
return p - out_buf;
}
-static struct debug_view zfcp_hba_dbf_view = {
- "structured",
- NULL,
- &zfcp_dbf_view_header,
- &zfcp_hba_dbf_view_format,
- NULL,
- NULL
+static struct debug_view zfcp_dbf_hba_view = {
+ .name = "structured",
+ .header_proc = zfcp_dbf_view_header,
+ .format_proc = zfcp_dbf_hba_view_format,
};
-static const char *zfcp_rec_dbf_tags[] = {
+static const char *zfcp_dbf_rec_tags[] = {
[ZFCP_REC_DBF_ID_THREAD] = "thread",
[ZFCP_REC_DBF_ID_TARGET] = "target",
[ZFCP_REC_DBF_ID_TRIGGER] = "trigger",
[ZFCP_REC_DBF_ID_ACTION] = "action",
};
-static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_rec_view_format(debug_info_t *id, struct debug_view *view,
char *buf, const char *_rec)
{
- struct zfcp_rec_dbf_record *r = (struct zfcp_rec_dbf_record *)_rec;
+ struct zfcp_dbf_rec_record *r = (struct zfcp_dbf_rec_record *)_rec;
char *p = buf;
char hint[ZFCP_DBF_ID_SIZE + 1];
memcpy(hint, r->id2, ZFCP_DBF_ID_SIZE);
hint[ZFCP_DBF_ID_SIZE] = 0;
- zfcp_dbf_outs(&p, "tag", zfcp_rec_dbf_tags[r->id]);
+ zfcp_dbf_outs(&p, "tag", zfcp_dbf_rec_tags[r->id]);
zfcp_dbf_outs(&p, "hint", hint);
switch (r->id) {
case ZFCP_REC_DBF_ID_THREAD:
@@ -537,24 +492,22 @@ static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
return p - buf;
}
-static struct debug_view zfcp_rec_dbf_view = {
- "structured",
- NULL,
- &zfcp_dbf_view_header,
- &zfcp_rec_dbf_view_format,
- NULL,
- NULL
+static struct debug_view zfcp_dbf_rec_view = {
+ .name = "structured",
+ .header_proc = zfcp_dbf_view_header,
+ .format_proc = zfcp_dbf_rec_view_format,
};
/**
- * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
+ * zfcp_dbf_rec_thread - trace event related to recovery thread operation
* @id2: identifier for event
- * @adapter: adapter
+ * @dbf: reference to dbf structure
* This function assumes that the caller is holding erp_lock.
*/
-void zfcp_rec_dbf_event_thread(char *id2, struct zfcp_adapter *adapter)
+void zfcp_dbf_rec_thread(char *id2, struct zfcp_dbf *dbf)
{
- struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+ struct zfcp_adapter *adapter = dbf->adapter;
+ struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
unsigned long flags = 0;
struct list_head *entry;
unsigned ready = 0, running = 0, total;
@@ -565,41 +518,41 @@ void zfcp_rec_dbf_event_thread(char *id2, struct zfcp_adapter *adapter)
running++;
total = adapter->erp_total_count;
- spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->rec_lock, flags);
memset(r, 0, sizeof(*r));
r->id = ZFCP_REC_DBF_ID_THREAD;
memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
r->u.thread.total = total;
r->u.thread.ready = ready;
r->u.thread.running = running;
- debug_event(adapter->rec_dbf, 6, r, sizeof(*r));
- spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+ debug_event(dbf->rec, 6, r, sizeof(*r));
+ spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
/**
- * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
+ * zfcp_dbf_rec_thread - trace event related to recovery thread operation
* @id2: identifier for event
* @adapter: adapter
* This function assumes that the caller does not hold erp_lock.
*/
-void zfcp_rec_dbf_event_thread_lock(char *id2, struct zfcp_adapter *adapter)
+void zfcp_dbf_rec_thread_lock(char *id2, struct zfcp_dbf *dbf)
{
+ struct zfcp_adapter *adapter = dbf->adapter;
unsigned long flags;
read_lock_irqsave(&adapter->erp_lock, flags);
- zfcp_rec_dbf_event_thread(id2, adapter);
+ zfcp_dbf_rec_thread(id2, dbf);
read_unlock_irqrestore(&adapter->erp_lock, flags);
}
-static void zfcp_rec_dbf_event_target(char *id2, void *ref,
- struct zfcp_adapter *adapter,
- atomic_t *status, atomic_t *erp_count,
- u64 wwpn, u32 d_id, u64 fcp_lun)
+static void zfcp_dbf_rec_target(char *id2, void *ref, struct zfcp_dbf *dbf,
+ atomic_t *status, atomic_t *erp_count, u64 wwpn,
+ u32 d_id, u64 fcp_lun)
{
- struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+ struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
unsigned long flags;
- spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->rec_lock, flags);
memset(r, 0, sizeof(*r));
r->id = ZFCP_REC_DBF_ID_TARGET;
memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
@@ -609,56 +562,57 @@ static void zfcp_rec_dbf_event_target(char *id2, void *ref,
r->u.target.d_id = d_id;
r->u.target.fcp_lun = fcp_lun;
r->u.target.erp_count = atomic_read(erp_count);
- debug_event(adapter->rec_dbf, 3, r, sizeof(*r));
- spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+ debug_event(dbf->rec, 3, r, sizeof(*r));
+ spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
/**
- * zfcp_rec_dbf_event_adapter - trace event for adapter state change
+ * zfcp_dbf_rec_adapter - trace event for adapter state change
* @id: identifier for trigger of state change
* @ref: additional reference (e.g. request)
- * @adapter: adapter
+ * @dbf: reference to dbf structure
*/
-void zfcp_rec_dbf_event_adapter(char *id, void *ref,
- struct zfcp_adapter *adapter)
+void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf)
{
- zfcp_rec_dbf_event_target(id, ref, adapter, &adapter->status,
+ struct zfcp_adapter *adapter = dbf->adapter;
+
+ zfcp_dbf_rec_target(id, ref, dbf, &adapter->status,
&adapter->erp_counter, 0, 0, 0);
}
/**
- * zfcp_rec_dbf_event_port - trace event for port state change
+ * zfcp_dbf_rec_port - trace event for port state change
* @id: identifier for trigger of state change
* @ref: additional reference (e.g. request)
* @port: port
*/
-void zfcp_rec_dbf_event_port(char *id, void *ref, struct zfcp_port *port)
+void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port)
{
- struct zfcp_adapter *adapter = port->adapter;
+ struct zfcp_dbf *dbf = port->adapter->dbf;
- zfcp_rec_dbf_event_target(id, ref, adapter, &port->status,
+ zfcp_dbf_rec_target(id, ref, dbf, &port->status,
&port->erp_counter, port->wwpn, port->d_id,
0);
}
/**
- * zfcp_rec_dbf_event_unit - trace event for unit state change
+ * zfcp_dbf_rec_unit - trace event for unit state change
* @id: identifier for trigger of state change
* @ref: additional reference (e.g. request)
* @unit: unit
*/
-void zfcp_rec_dbf_event_unit(char *id, void *ref, struct zfcp_unit *unit)
+void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
{
struct zfcp_port *port = unit->port;
- struct zfcp_adapter *adapter = port->adapter;
+ struct zfcp_dbf *dbf = port->adapter->dbf;
- zfcp_rec_dbf_event_target(id, ref, adapter, &unit->status,
+ zfcp_dbf_rec_target(id, ref, dbf, &unit->status,
&unit->erp_counter, port->wwpn, port->d_id,
unit->fcp_lun);
}
/**
- * zfcp_rec_dbf_event_trigger - trace event for triggered error recovery
+ * zfcp_dbf_rec_trigger - trace event for triggered error recovery
* @id2: identifier for error recovery trigger
* @ref: additional reference (e.g. request)
* @want: originally requested error recovery action
@@ -668,14 +622,15 @@ void zfcp_rec_dbf_event_unit(char *id, void *ref, struct zfcp_unit *unit)
* @port: port
* @unit: unit
*/
-void zfcp_rec_dbf_event_trigger(char *id2, void *ref, u8 want, u8 need,
- void *action, struct zfcp_adapter *adapter,
- struct zfcp_port *port, struct zfcp_unit *unit)
+void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
+ struct zfcp_adapter *adapter, struct zfcp_port *port,
+ struct zfcp_unit *unit)
{
- struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
unsigned long flags;
- spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->rec_lock, flags);
memset(r, 0, sizeof(*r));
r->id = ZFCP_REC_DBF_ID_TRIGGER;
memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
@@ -692,22 +647,22 @@ void zfcp_rec_dbf_event_trigger(char *id2, void *ref, u8 want, u8 need,
r->u.trigger.us = atomic_read(&unit->status);
r->u.trigger.fcp_lun = unit->fcp_lun;
}
- debug_event(adapter->rec_dbf, action ? 1 : 4, r, sizeof(*r));
- spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+ debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
+ spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
/**
- * zfcp_rec_dbf_event_action - trace event showing progress of recovery action
+ * zfcp_dbf_rec_action - trace event showing progress of recovery action
* @id2: identifier
* @erp_action: error recovery action struct pointer
*/
-void zfcp_rec_dbf_event_action(char *id2, struct zfcp_erp_action *erp_action)
+void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action)
{
- struct zfcp_adapter *adapter = erp_action->adapter;
- struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+ struct zfcp_dbf *dbf = erp_action->adapter->dbf;
+ struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
unsigned long flags;
- spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->rec_lock, flags);
memset(r, 0, sizeof(*r));
r->id = ZFCP_REC_DBF_ID_ACTION;
memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
@@ -715,26 +670,27 @@ void zfcp_rec_dbf_event_action(char *id2, struct zfcp_erp_action *erp_action)
r->u.action.status = erp_action->status;
r->u.action.step = erp_action->step;
r->u.action.fsf_req = (unsigned long)erp_action->fsf_req;
- debug_event(adapter->rec_dbf, 5, r, sizeof(*r));
- spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+ debug_event(dbf->rec, 5, r, sizeof(*r));
+ spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
/**
- * zfcp_san_dbf_event_ct_request - trace event for issued CT request
+ * zfcp_dbf_san_ct_request - trace event for issued CT request
* @fsf_req: request containing issued CT data
*/
-void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
struct zfcp_wka_port *wka_port = ct->wka_port;
struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_dbf *dbf = adapter->dbf;
struct ct_hdr *hdr = sg_virt(ct->req);
- struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
- struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
+ struct zfcp_dbf_san_record *r = &dbf->san_buf;
+ struct zfcp_dbf_san_record_ct_request *oct = &r->u.ct_req;
int level = 3;
unsigned long flags;
- spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->san_lock, flags);
memset(r, 0, sizeof(*r));
strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
r->fsf_reqid = fsf_req->req_id;
@@ -749,28 +705,29 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
oct->max_res_size = hdr->max_res_size;
oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
ZFCP_DBF_SAN_MAX_PAYLOAD);
- debug_event(adapter->san_dbf, level, r, sizeof(*r));
- zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+ debug_event(dbf->san, level, r, sizeof(*r));
+ zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
(void *)hdr + sizeof(struct ct_hdr), oct->len);
- spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ spin_unlock_irqrestore(&dbf->san_lock, flags);
}
/**
- * zfcp_san_dbf_event_ct_response - trace event for completion of CT request
+ * zfcp_dbf_san_ct_response - trace event for completion of CT request
* @fsf_req: request containing CT response
*/
-void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
struct zfcp_wka_port *wka_port = ct->wka_port;
struct zfcp_adapter *adapter = wka_port->adapter;
struct ct_hdr *hdr = sg_virt(ct->resp);
- struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
- struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_san_record *r = &dbf->san_buf;
+ struct zfcp_dbf_san_record_ct_response *rct = &r->u.ct_resp;
int level = 3;
unsigned long flags;
- spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->san_lock, flags);
memset(r, 0, sizeof(*r));
strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
r->fsf_reqid = fsf_req->req_id;
@@ -785,22 +742,22 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
rct->max_res_size = hdr->max_res_size;
rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
ZFCP_DBF_SAN_MAX_PAYLOAD);
- debug_event(adapter->san_dbf, level, r, sizeof(*r));
- zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+ debug_event(dbf->san, level, r, sizeof(*r));
+ zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
(void *)hdr + sizeof(struct ct_hdr), rct->len);
- spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ spin_unlock_irqrestore(&dbf->san_lock, flags);
}
-static void zfcp_san_dbf_event_els(const char *tag, int level,
- struct zfcp_fsf_req *fsf_req, u32 s_id,
- u32 d_id, u8 ls_code, void *buffer,
- int buflen)
+static void zfcp_dbf_san_els(const char *tag, int level,
+ struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id,
+ u8 ls_code, void *buffer, int buflen)
{
struct zfcp_adapter *adapter = fsf_req->adapter;
- struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_san_record *rec = &dbf->san_buf;
unsigned long flags;
- spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->san_lock, flags);
memset(rec, 0, sizeof(*rec));
strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
rec->fsf_reqid = fsf_req->req_id;
@@ -808,45 +765,45 @@ static void zfcp_san_dbf_event_els(const char *tag, int level,
rec->s_id = s_id;
rec->d_id = d_id;
rec->u.els.ls_code = ls_code;
- debug_event(adapter->san_dbf, level, rec, sizeof(*rec));
- zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level,
+ debug_event(dbf->san, level, rec, sizeof(*rec));
+ zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level,
buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD));
- spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ spin_unlock_irqrestore(&dbf->san_lock, flags);
}
/**
- * zfcp_san_dbf_event_els_request - trace event for issued ELS
+ * zfcp_dbf_san_els_request - trace event for issued ELS
* @fsf_req: request containing issued ELS
*/
-void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
- zfcp_san_dbf_event_els("oels", 2, fsf_req,
+ zfcp_dbf_san_els("oels", 2, fsf_req,
fc_host_port_id(els->adapter->scsi_host),
els->d_id, *(u8 *) sg_virt(els->req),
sg_virt(els->req), els->req->length);
}
/**
- * zfcp_san_dbf_event_els_response - trace event for completed ELS
+ * zfcp_dbf_san_els_response - trace event for completed ELS
* @fsf_req: request containing ELS response
*/
-void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
- zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
+ zfcp_dbf_san_els("rels", 2, fsf_req, els->d_id,
fc_host_port_id(els->adapter->scsi_host),
*(u8 *)sg_virt(els->req), sg_virt(els->resp),
els->resp->length);
}
/**
- * zfcp_san_dbf_event_incoming_els - trace event for incomig ELS
+ * zfcp_dbf_san_incoming_els - trace event for incomig ELS
* @fsf_req: request containing unsolicited status buffer with incoming ELS
*/
-void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_adapter *adapter = fsf_req->adapter;
struct fsf_status_read_buffer *buf =
@@ -854,16 +811,16 @@ void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
int length = (int)buf->length -
(int)((void *)&buf->payload - (void *)buf);
- zfcp_san_dbf_event_els("iels", 1, fsf_req, buf->d_id,
+ zfcp_dbf_san_els("iels", 1, fsf_req, buf->d_id,
fc_host_port_id(adapter->scsi_host),
buf->payload.data[0], (void *)buf->payload.data,
length);
}
-static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
- struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
+ struct zfcp_dbf_san_record *r = (struct zfcp_dbf_san_record *)in_buf;
char *p = out_buf;
if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
@@ -876,7 +833,7 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "d_id", "0x%06x", r->d_id);
if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
- struct zfcp_san_dbf_record_ct_request *ct = &r->u.ct_req;
+ struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req;
zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code);
zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type);
@@ -884,7 +841,7 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
} else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
- struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
+ struct zfcp_dbf_san_record_ct_response *ct = &r->u.ct_resp;
zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
@@ -894,35 +851,30 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
} else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
- struct zfcp_san_dbf_record_els *els = &r->u.els;
+ struct zfcp_dbf_san_record_els *els = &r->u.els;
zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
}
return p - out_buf;
}
-static struct debug_view zfcp_san_dbf_view = {
- "structured",
- NULL,
- &zfcp_dbf_view_header,
- &zfcp_san_dbf_view_format,
- NULL,
- NULL
+static struct debug_view zfcp_dbf_san_view = {
+ .name = "structured",
+ .header_proc = zfcp_dbf_view_header,
+ .format_proc = zfcp_dbf_san_view_format,
};
-static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
- struct zfcp_adapter *adapter,
- struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *fsf_req,
- unsigned long old_req_id)
+void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
+ struct zfcp_dbf *dbf, struct scsi_cmnd *scsi_cmnd,
+ struct zfcp_fsf_req *fsf_req, unsigned long old_req_id)
{
- struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
+ struct zfcp_dbf_scsi_record *rec = &dbf->scsi_buf;
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
unsigned long flags;
struct fcp_rsp_iu *fcp_rsp;
char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
int offset = 0, buflen = 0;
- spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
+ spin_lock_irqsave(&dbf->scsi_lock, flags);
do {
memset(rec, 0, sizeof(*rec));
if (offset == 0) {
@@ -976,68 +928,20 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
dump->offset = offset;
dump->size = min(buflen - offset,
(int)sizeof(struct
- zfcp_scsi_dbf_record) -
+ zfcp_dbf_scsi_record) -
(int)sizeof(struct zfcp_dbf_dump));
memcpy(dump->data, fcp_sns_info + offset, dump->size);
offset += dump->size;
}
- debug_event(adapter->scsi_dbf, level, rec, sizeof(*rec));
+ debug_event(dbf->scsi, level, rec, sizeof(*rec));
} while (offset < buflen);
- spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
-}
-
-/**
- * zfcp_scsi_dbf_event_result - trace event for SCSI command completion
- * @tag: tag indicating success or failure of SCSI command
- * @level: trace level applicable for this event
- * @adapter: adapter that has been used to issue the SCSI command
- * @scsi_cmnd: SCSI command pointer
- * @fsf_req: request used to issue SCSI command (might be NULL)
- */
-void zfcp_scsi_dbf_event_result(const char *tag, int level,
- struct zfcp_adapter *adapter,
- struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *fsf_req)
-{
- zfcp_scsi_dbf_event("rslt", tag, level, adapter, scsi_cmnd, fsf_req, 0);
+ spin_unlock_irqrestore(&dbf->scsi_lock, flags);
}
-/**
- * zfcp_scsi_dbf_event_abort - trace event for SCSI command abort
- * @tag: tag indicating success or failure of abort operation
- * @adapter: adapter thas has been used to issue SCSI command to be aborted
- * @scsi_cmnd: SCSI command to be aborted
- * @new_fsf_req: request containing abort (might be NULL)
- * @old_req_id: identifier of request containg SCSI command to be aborted
- */
-void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
- struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req,
- unsigned long old_req_id)
-{
- zfcp_scsi_dbf_event("abrt", tag, 1, adapter, scsi_cmnd, new_fsf_req,
- old_req_id);
-}
-
-/**
- * zfcp_scsi_dbf_event_devreset - trace event for Logical Unit or Target Reset
- * @tag: tag indicating success or failure of reset operation
- * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
- * @unit: unit that needs reset
- * @scsi_cmnd: SCSI command which caused this error recovery
- */
-void zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag,
- struct zfcp_unit *unit,
- struct scsi_cmnd *scsi_cmnd)
-{
- zfcp_scsi_dbf_event(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
- unit->port->adapter, scsi_cmnd, NULL, 0);
-}
-
-static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
- struct zfcp_scsi_dbf_record *r = (struct zfcp_scsi_dbf_record *)in_buf;
+ struct zfcp_dbf_scsi_record *r = (struct zfcp_dbf_scsi_record *)in_buf;
struct timespec t;
char *p = out_buf;
@@ -1059,7 +963,7 @@ static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid);
zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
- zfcp_dbf_timestamp(r->fsf_issued, &t);
+ stck_to_timespec(r->fsf_issued, &t);
zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
@@ -1078,84 +982,96 @@ static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
return p - out_buf;
}
-static struct debug_view zfcp_scsi_dbf_view = {
- "structured",
- NULL,
- &zfcp_dbf_view_header,
- &zfcp_scsi_dbf_view_format,
- NULL,
- NULL
+static struct debug_view zfcp_dbf_scsi_view = {
+ .name = "structured",
+ .header_proc = zfcp_dbf_view_header,
+ .format_proc = zfcp_dbf_scsi_view_format,
};
+static debug_info_t *zfcp_dbf_reg(const char *name, int level,
+ struct debug_view *view, int size)
+{
+ struct debug_info *d;
+
+ d = debug_register(name, dbfsize, level, size);
+ if (!d)
+ return NULL;
+
+ debug_register_view(d, &debug_hex_ascii_view);
+ debug_register_view(d, view);
+ debug_set_level(d, level);
+
+ return d;
+}
+
/**
* 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)
+int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter)
{
char dbf_name[DEBUG_MAX_NAME_LEN];
+ struct zfcp_dbf *dbf;
+
+ dbf = kmalloc(sizeof(struct zfcp_dbf), GFP_KERNEL);
+ if (!dbf)
+ return -ENOMEM;
+
+ dbf->adapter = adapter;
+
+ spin_lock_init(&dbf->hba_lock);
+ spin_lock_init(&dbf->san_lock);
+ spin_lock_init(&dbf->scsi_lock);
+ spin_lock_init(&dbf->rec_lock);
/* debug feature area which records recovery activity */
sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev));
- adapter->rec_dbf = debug_register(dbf_name, dbfsize, 1,
- sizeof(struct zfcp_rec_dbf_record));
- if (!adapter->rec_dbf)
- goto failed;
- debug_register_view(adapter->rec_dbf, &debug_hex_ascii_view);
- debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view);
- debug_set_level(adapter->rec_dbf, 3);
+ dbf->rec = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_rec_view,
+ sizeof(struct zfcp_dbf_rec_record));
+ if (!dbf->rec)
+ goto err_out;
/* debug feature area which records HBA (FSF and QDIO) conditions */
sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev));
- adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
- sizeof(struct zfcp_hba_dbf_record));
- if (!adapter->hba_dbf)
- goto failed;
- debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view);
- debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view);
- debug_set_level(adapter->hba_dbf, 3);
+ dbf->hba = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_hba_view,
+ sizeof(struct zfcp_dbf_hba_record));
+ if (!dbf->hba)
+ goto err_out;
/* debug feature area which records SAN command failures and recovery */
sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev));
- adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
- sizeof(struct zfcp_san_dbf_record));
- if (!adapter->san_dbf)
- goto failed;
- debug_register_view(adapter->san_dbf, &debug_hex_ascii_view);
- debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view);
- debug_set_level(adapter->san_dbf, 6);
+ dbf->san = zfcp_dbf_reg(dbf_name, 6, &zfcp_dbf_san_view,
+ sizeof(struct zfcp_dbf_san_record));
+ if (!dbf->san)
+ goto err_out;
/* debug feature area which records SCSI command failures and recovery */
sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev));
- adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
- sizeof(struct zfcp_scsi_dbf_record));
- if (!adapter->scsi_dbf)
- goto failed;
- debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view);
- debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view);
- debug_set_level(adapter->scsi_dbf, 3);
+ dbf->scsi = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_scsi_view,
+ sizeof(struct zfcp_dbf_scsi_record));
+ if (!dbf->scsi)
+ goto err_out;
+ adapter->dbf = dbf;
return 0;
- failed:
- zfcp_adapter_debug_unregister(adapter);
-
+err_out:
+ zfcp_dbf_adapter_unregister(dbf);
return -ENOMEM;
}
/**
* zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
- * @adapter: pointer to adapter for which debug features should be unregistered
+ * @dbf: pointer to dbf for which debug features should be unregistered
*/
-void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf)
{
- debug_unregister(adapter->scsi_dbf);
- debug_unregister(adapter->san_dbf);
- debug_unregister(adapter->hba_dbf);
- debug_unregister(adapter->rec_dbf);
- adapter->scsi_dbf = NULL;
- adapter->san_dbf = NULL;
- adapter->hba_dbf = NULL;
- adapter->rec_dbf = NULL;
+ debug_unregister(dbf->scsi);
+ debug_unregister(dbf->san);
+ debug_unregister(dbf->hba);
+ debug_unregister(dbf->rec);
+ dbf->adapter->dbf = NULL;
+ kfree(dbf);
}
+
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index a573f7344dd..6b1461e8f84 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -2,7 +2,7 @@
* This file is part of the zfcp device driver for
* FCP adapters for IBM System z9 and zSeries.
*
- * Copyright IBM Corp. 2008, 2008
+ * Copyright IBM Corp. 2008, 2009
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,7 +22,9 @@
#ifndef ZFCP_DBF_H
#define ZFCP_DBF_H
+#include "zfcp_ext.h"
#include "zfcp_fsf.h"
+#include "zfcp_def.h"
#define ZFCP_DBF_TAG_SIZE 4
#define ZFCP_DBF_ID_SIZE 7
@@ -35,13 +37,13 @@ struct zfcp_dbf_dump {
u8 data[]; /* dump data */
} __attribute__ ((packed));
-struct zfcp_rec_dbf_record_thread {
+struct zfcp_dbf_rec_record_thread {
u32 total;
u32 ready;
u32 running;
};
-struct zfcp_rec_dbf_record_target {
+struct zfcp_dbf_rec_record_target {
u64 ref;
u32 status;
u32 d_id;
@@ -50,7 +52,7 @@ struct zfcp_rec_dbf_record_target {
u32 erp_count;
};
-struct zfcp_rec_dbf_record_trigger {
+struct zfcp_dbf_rec_record_trigger {
u8 want;
u8 need;
u32 as;
@@ -62,21 +64,21 @@ struct zfcp_rec_dbf_record_trigger {
u64 fcp_lun;
};
-struct zfcp_rec_dbf_record_action {
+struct zfcp_dbf_rec_record_action {
u32 status;
u32 step;
u64 action;
u64 fsf_req;
};
-struct zfcp_rec_dbf_record {
+struct zfcp_dbf_rec_record {
u8 id;
char id2[7];
union {
- struct zfcp_rec_dbf_record_action action;
- struct zfcp_rec_dbf_record_thread thread;
- struct zfcp_rec_dbf_record_target target;
- struct zfcp_rec_dbf_record_trigger trigger;
+ struct zfcp_dbf_rec_record_action action;
+ struct zfcp_dbf_rec_record_thread thread;
+ struct zfcp_dbf_rec_record_target target;
+ struct zfcp_dbf_rec_record_trigger trigger;
} u;
};
@@ -87,7 +89,7 @@ enum {
ZFCP_REC_DBF_ID_TRIGGER,
};
-struct zfcp_hba_dbf_record_response {
+struct zfcp_dbf_hba_record_response {
u32 fsf_command;
u64 fsf_reqid;
u32 fsf_seqno;
@@ -125,7 +127,7 @@ struct zfcp_hba_dbf_record_response {
} u;
} __attribute__ ((packed));
-struct zfcp_hba_dbf_record_status {
+struct zfcp_dbf_hba_record_status {
u8 failed;
u32 status_type;
u32 status_subtype;
@@ -139,24 +141,24 @@ struct zfcp_hba_dbf_record_status {
u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
} __attribute__ ((packed));
-struct zfcp_hba_dbf_record_qdio {
+struct zfcp_dbf_hba_record_qdio {
u32 qdio_error;
u8 sbal_index;
u8 sbal_count;
} __attribute__ ((packed));
-struct zfcp_hba_dbf_record {
+struct zfcp_dbf_hba_record {
u8 tag[ZFCP_DBF_TAG_SIZE];
u8 tag2[ZFCP_DBF_TAG_SIZE];
union {
- struct zfcp_hba_dbf_record_response response;
- struct zfcp_hba_dbf_record_status status;
- struct zfcp_hba_dbf_record_qdio qdio;
+ struct zfcp_dbf_hba_record_response response;
+ struct zfcp_dbf_hba_record_status status;
+ struct zfcp_dbf_hba_record_qdio qdio;
struct fsf_bit_error_payload berr;
} u;
} __attribute__ ((packed));
-struct zfcp_san_dbf_record_ct_request {
+struct zfcp_dbf_san_record_ct_request {
u16 cmd_req_code;
u8 revision;
u8 gs_type;
@@ -166,7 +168,7 @@ struct zfcp_san_dbf_record_ct_request {
u32 len;
} __attribute__ ((packed));
-struct zfcp_san_dbf_record_ct_response {
+struct zfcp_dbf_san_record_ct_response {
u16 cmd_rsp_code;
u8 revision;
u8 reason_code;
@@ -176,27 +178,27 @@ struct zfcp_san_dbf_record_ct_response {
u32 len;
} __attribute__ ((packed));
-struct zfcp_san_dbf_record_els {
+struct zfcp_dbf_san_record_els {
u8 ls_code;
u32 len;
} __attribute__ ((packed));
-struct zfcp_san_dbf_record {
+struct zfcp_dbf_san_record {
u8 tag[ZFCP_DBF_TAG_SIZE];
u64 fsf_reqid;
u32 fsf_seqno;
u32 s_id;
u32 d_id;
union {
- struct zfcp_san_dbf_record_ct_request ct_req;
- struct zfcp_san_dbf_record_ct_response ct_resp;
- struct zfcp_san_dbf_record_els els;
+ struct zfcp_dbf_san_record_ct_request ct_req;
+ struct zfcp_dbf_san_record_ct_response ct_resp;
+ struct zfcp_dbf_san_record_els els;
} u;
#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
u8 payload[32];
} __attribute__ ((packed));
-struct zfcp_scsi_dbf_record {
+struct zfcp_dbf_scsi_record {
u8 tag[ZFCP_DBF_TAG_SIZE];
u8 tag2[ZFCP_DBF_TAG_SIZE];
u32 scsi_id;
@@ -222,4 +224,127 @@ struct zfcp_scsi_dbf_record {
u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
} __attribute__ ((packed));
+struct zfcp_dbf {
+ debug_info_t *rec;
+ debug_info_t *hba;
+ debug_info_t *san;
+ debug_info_t *scsi;
+ spinlock_t rec_lock;
+ spinlock_t hba_lock;
+ spinlock_t san_lock;
+ spinlock_t scsi_lock;
+ struct zfcp_dbf_rec_record rec_buf;
+ struct zfcp_dbf_hba_record hba_buf;
+ struct zfcp_dbf_san_record san_buf;
+ struct zfcp_dbf_scsi_record scsi_buf;
+ struct zfcp_adapter *adapter;
+};
+
+static inline
+void zfcp_dbf_hba_fsf_resp(const char *tag2, int level,
+ struct zfcp_fsf_req *req, struct zfcp_dbf *dbf)
+{
+ if (level <= dbf->hba->level)
+ _zfcp_dbf_hba_fsf_response(tag2, level, req, dbf);
+}
+
+/**
+ * zfcp_dbf_hba_fsf_response - trace event for request completion
+ * @fsf_req: request that has been completed
+ */
+static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
+{
+ struct zfcp_dbf *dbf = req->adapter->dbf;
+ struct fsf_qtcb *qtcb = req->qtcb;
+
+ if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+ (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
+ zfcp_dbf_hba_fsf_resp("perr", 1, req, dbf);
+
+ } else if (qtcb->header.fsf_status != FSF_GOOD) {
+ zfcp_dbf_hba_fsf_resp("ferr", 1, req, dbf);
+
+ } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
+ (req->fsf_command == FSF_QTCB_OPEN_LUN)) {
+ zfcp_dbf_hba_fsf_resp("open", 4, req, dbf);
+
+ } else if (qtcb->header.log_length) {
+ zfcp_dbf_hba_fsf_resp("qtcb", 5, req, dbf);
+
+ } else {
+ zfcp_dbf_hba_fsf_resp("norm", 6, req, dbf);
+ }
+ }
+
+/**
+ * zfcp_dbf_hba_fsf_unsol - trace event for an unsolicited status buffer
+ * @tag: tag indicating which kind of unsolicited status has been received
+ * @dbf: reference to dbf structure
+ * @status_buffer: buffer containing payload of unsolicited status
+ */
+static inline
+void zfcp_dbf_hba_fsf_unsol(const char *tag, struct zfcp_dbf *dbf,
+ struct fsf_status_read_buffer *buf)
+{
+ int level = 2;
+
+ if (level <= dbf->hba->level)
+ _zfcp_dbf_hba_fsf_unsol(tag, level, dbf, buf);
+}
+
+static inline
+void zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
+ struct zfcp_dbf *dbf, struct scsi_cmnd *scmd,
+ struct zfcp_fsf_req *req, unsigned long old_id)
+{
+ if (level <= dbf->scsi->level)
+ _zfcp_dbf_scsi(tag, tag2, level, dbf, scmd, req, old_id);
+}
+
+/**
+ * zfcp_dbf_scsi_result - trace event for SCSI command completion
+ * @tag: tag indicating success or failure of SCSI command
+ * @level: trace level applicable for this event
+ * @adapter: adapter that has been used to issue the SCSI command
+ * @scmd: SCSI command pointer
+ * @fsf_req: request used to issue SCSI command (might be NULL)
+ */
+static inline
+void zfcp_dbf_scsi_result(const char *tag, int level, struct zfcp_dbf *dbf,
+ struct scsi_cmnd *scmd, struct zfcp_fsf_req *fsf_req)
+{
+ zfcp_dbf_scsi("rslt", tag, level, dbf, scmd, fsf_req, 0);
+}
+
+/**
+ * zfcp_dbf_scsi_abort - trace event for SCSI command abort
+ * @tag: tag indicating success or failure of abort operation
+ * @adapter: adapter thas has been used to issue SCSI command to be aborted
+ * @scmd: SCSI command to be aborted
+ * @new_req: request containing abort (might be NULL)
+ * @old_id: identifier of request containg SCSI command to be aborted
+ */
+static inline
+void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf,
+ struct scsi_cmnd *scmd, struct zfcp_fsf_req *new_req,
+ unsigned long old_id)
+{
+ zfcp_dbf_scsi("abrt", tag, 1, dbf, scmd, new_req, old_id);
+}
+
+/**
+ * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset
+ * @tag: tag indicating success or failure of reset operation
+ * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
+ * @unit: unit that needs reset
+ * @scsi_cmnd: SCSI command which caused this error recovery
+ */
+static inline
+void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
+ struct scsi_cmnd *scsi_cmnd)
+{
+ zfcp_dbf_scsi(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
+ unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
+}
+
#endif /* ZFCP_DBF_H */
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 49d0532bca1..7da2fad8f51 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -37,10 +37,8 @@
#include <asm/debug.h>
#include <asm/ebcdic.h>
#include <asm/sysinfo.h>
-#include "zfcp_dbf.h"
#include "zfcp_fsf.h"
-
/********************* GENERAL DEFINES *********************************/
#define REQUEST_LIST_SIZE 128
@@ -75,9 +73,6 @@
/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
-/* timeout for name-server lookup (in seconds) */
-#define ZFCP_NS_GID_PN_TIMEOUT 10
-
/* task attribute values in FCP-2 FCP_CMND IU */
#define SIMPLE_Q 0
#define HEAD_OF_Q 1
@@ -224,8 +219,6 @@ struct zfcp_ls_adisc {
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010
-#define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020
-#define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080
#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
@@ -234,6 +227,7 @@ struct zfcp_ls_adisc {
/* remote port status */
#define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001
+#define ZFCP_STATUS_PORT_LINK_TEST 0x00000002
/* well known address (WKA) port status*/
enum zfcp_wka_status {
@@ -249,7 +243,6 @@ enum zfcp_wka_status {
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
-#define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004
#define ZFCP_STATUS_FSFREQ_ERROR 0x00000008
#define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010
#define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040
@@ -266,12 +259,14 @@ struct zfcp_fsf_req;
/* holds various memory pools of an adapter */
struct zfcp_adapter_mempool {
- mempool_t *fsf_req_erp;
- mempool_t *fsf_req_scsi;
- mempool_t *fsf_req_abort;
- mempool_t *fsf_req_status_read;
- mempool_t *data_status_read;
- mempool_t *data_gid_pn;
+ mempool_t *erp_req;
+ mempool_t *gid_pn_req;
+ mempool_t *scsi_req;
+ mempool_t *scsi_abort;
+ mempool_t *status_read_req;
+ mempool_t *status_read_data;
+ mempool_t *gid_pn_data;
+ mempool_t *qtcb_pool;
};
/*
@@ -305,6 +300,15 @@ struct ct_iu_gid_pn_resp {
u32 d_id;
} __attribute__ ((packed));
+struct ct_iu_gpn_ft_req {
+ struct ct_hdr header;
+ u8 flags;
+ u8 domain_id_scope;
+ u8 area_id_scope;
+ u8 fc4_type;
+} __attribute__ ((packed));
+
+
/**
* struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
* @wka_port: port where the request is sent to
@@ -312,7 +316,6 @@ struct ct_iu_gid_pn_resp {
* @resp: scatter-gather list for response
* @handler: handler function (called for response to the request)
* @handler_data: data passed to handler function
- * @timeout: FSF timeout for this request
* @completion: completion for synchronization purposes
* @status: used to pass error status to calling function
*/
@@ -322,7 +325,6 @@ struct zfcp_send_ct {
struct scatterlist *resp;
void (*handler)(unsigned long);
unsigned long handler_data;
- int timeout;
struct completion *completion;
int status;
};
@@ -420,6 +422,29 @@ struct zfcp_latencies {
spinlock_t lock;
};
+/** struct zfcp_qdio - basic QDIO data structure
+ * @resp_q: response queue
+ * @req_q: request queue
+ * @stat_lock: lock to protect req_q_util and req_q_time
+ * @req_q_lock; lock to serialize access to request queue
+ * @req_q_time: time of last fill level change
+ * @req_q_util: used for accounting
+ * @req_q_full: queue full incidents
+ * @req_q_wq: used to wait for SBAL availability
+ * @adapter: adapter used in conjunction with this QDIO structure
+ */
+struct zfcp_qdio {
+ struct zfcp_qdio_queue resp_q;
+ struct zfcp_qdio_queue req_q;
+ spinlock_t stat_lock;
+ spinlock_t req_q_lock;
+ unsigned long long req_q_time;
+ u64 req_q_util;
+ atomic_t req_q_full;
+ wait_queue_head_t req_q_wq;
+ struct zfcp_adapter *adapter;
+};
+
struct zfcp_adapter {
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
@@ -428,6 +453,7 @@ struct zfcp_adapter {
u64 peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
+ struct zfcp_qdio *qdio;
u32 hydra_version; /* Hydra version */
u32 fsf_lic_version;
u32 adapter_features; /* FCP channel features */
@@ -439,15 +465,7 @@ struct zfcp_adapter {
unsigned long req_no; /* unique FSF req number */
struct list_head *req_list; /* list of pending reqs */
spinlock_t req_list_lock; /* request list lock */
- struct zfcp_qdio_queue req_q; /* request queue */
- spinlock_t req_q_lock; /* for operations on queue */
- ktime_t req_q_time; /* time of last fill level change */
- u64 req_q_util; /* for accounting */
- spinlock_t qdio_stat_lock;
u32 fsf_req_seq_no; /* FSF cmnd seq number */
- wait_queue_head_t request_wq; /* can be used to wait for
- more avaliable SBALs */
- struct zfcp_qdio_queue resp_q; /* response queue */
rwlock_t abort_lock; /* Protects against SCSI
stack abort/command
completion races */
@@ -456,10 +474,9 @@ struct zfcp_adapter {
atomic_t status; /* status of this adapter */
struct list_head erp_ready_head; /* error recovery for this
adapter/devices */
+ wait_queue_head_t erp_ready_wq;
struct list_head erp_running_head;
rwlock_t erp_lock;
- struct semaphore erp_ready_sem;
- wait_queue_head_t erp_thread_wqh;
wait_queue_head_t erp_done_wqh;
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
@@ -467,27 +484,16 @@ struct zfcp_adapter {
actions */
u32 erp_low_mem_count; /* nr of erp actions waiting
for memory */
+ struct task_struct *erp_thread;
struct zfcp_wka_ports *gs; /* generic services */
- debug_info_t *rec_dbf;
- debug_info_t *hba_dbf;
- debug_info_t *san_dbf; /* debug feature areas */
- debug_info_t *scsi_dbf;
- spinlock_t rec_dbf_lock;
- spinlock_t hba_dbf_lock;
- spinlock_t san_dbf_lock;
- spinlock_t scsi_dbf_lock;
- struct zfcp_rec_dbf_record rec_dbf_buf;
- struct zfcp_hba_dbf_record hba_dbf_buf;
- struct zfcp_san_dbf_record san_dbf_buf;
- struct zfcp_scsi_dbf_record scsi_dbf_buf;
+ struct zfcp_dbf *dbf; /* debug traces */
struct zfcp_adapter_mempool pool; /* Adapter memory pools */
- struct qdio_initialize qdio_init_data; /* for qdio_establish */
struct fc_host_statistics *fc_stats;
struct fsf_qtcb_bottom_port *stats_reset_data;
unsigned long stats_reset;
struct work_struct scan_work;
struct service_level service_level;
- atomic_t qdio_outb_full; /* queue full incidents */
+ struct workqueue_struct *work_queue;
};
struct zfcp_port {
@@ -531,36 +537,64 @@ struct zfcp_unit {
struct work_struct scsi_work;
};
-/* FSF request */
+/**
+ * struct zfcp_queue_req - queue related values for a request
+ * @sbal_number: number of free SBALs
+ * @sbal_first: first SBAL for this request
+ * @sbal_last: last SBAL for this request
+ * @sbal_limit: last possible SBAL for this request
+ * @sbale_curr: current SBALE at creation of this request
+ * @sbal_response: SBAL used in interrupt
+ * @qdio_outb_usage: usage of outbound queue
+ * @qdio_inb_usage: usage of inbound queue
+ */
+struct zfcp_queue_req {
+ u8 sbal_number;
+ u8 sbal_first;
+ u8 sbal_last;
+ u8 sbal_limit;
+ u8 sbale_curr;
+ u8 sbal_response;
+ u16 qdio_outb_usage;
+ u16 qdio_inb_usage;
+};
+
+/**
+ * struct zfcp_fsf_req - basic FSF request structure
+ * @list: list of FSF requests
+ * @req_id: unique request ID
+ * @adapter: adapter this request belongs to
+ * @queue_req: queue related values
+ * @completion: used to signal the completion of the request
+ * @status: status of the request
+ * @fsf_command: FSF command issued
+ * @qtcb: associated QTCB
+ * @seq_no: sequence number of this request
+ * @data: private data
+ * @timer: timer data of this request
+ * @erp_action: reference to erp action if request issued on behalf of ERP
+ * @pool: reference to memory pool if used for this request
+ * @issued: time when request was send (STCK)
+ * @unit: reference to unit if this request is a SCSI request
+ * @handler: handler which should be called to process response
+ */
struct zfcp_fsf_req {
- struct list_head list; /* list of FSF requests */
- unsigned long req_id; /* unique request ID */
- struct zfcp_adapter *adapter; /* adapter request belongs to */
- u8 sbal_number; /* nr of SBALs free for use */
- u8 sbal_first; /* first SBAL for this request */
- u8 sbal_last; /* last SBAL for this request */
- u8 sbal_limit; /* last possible SBAL for
- this reuest */
- u8 sbale_curr; /* current SBALE during creation
- of request */
- u8 sbal_response; /* SBAL used in interrupt */
- wait_queue_head_t completion_wq; /* can be used by a routine
- to wait for completion */
- u32 status; /* status of this request */
- u32 fsf_command; /* FSF Command copy */
- struct fsf_qtcb *qtcb; /* address of associated QTCB */
- u32 seq_no; /* Sequence number of request */
- void *data; /* private data of request */
- struct timer_list timer; /* used for erp or scsi er */
- struct zfcp_erp_action *erp_action; /* used if this request is
- issued on behalf of erp */
- mempool_t *pool; /* used if request was alloacted
- from emergency pool */
- unsigned long long issued; /* request sent time (STCK) */
- struct zfcp_unit *unit;
+ struct list_head list;
+ unsigned long req_id;
+ struct zfcp_adapter *adapter;
+ struct zfcp_queue_req queue_req;
+ struct completion completion;
+ u32 status;
+ u32 fsf_command;
+ struct fsf_qtcb *qtcb;
+ u32 seq_no;
+ void *data;
+ struct timer_list timer;
+ struct zfcp_erp_action *erp_action;
+ mempool_t *pool;
+ unsigned long long issued;
+ struct zfcp_unit *unit;
void (*handler)(struct zfcp_fsf_req *);
- u16 qdio_outb_usage;/* usage of outbound queue */
- u16 qdio_inb_usage; /* usage of inbound queue */
};
/* driver data */
@@ -570,18 +604,11 @@ struct zfcp_data {
rwlock_t config_lock; /* serialises changes
to adapter/port/unit
lists */
- struct semaphore config_sema; /* serialises configuration
- changes */
- struct kmem_cache *fsf_req_qtcb_cache;
+ struct mutex config_mutex;
+ struct kmem_cache *gpn_ft_cache;
+ struct kmem_cache *qtcb_cache;
struct kmem_cache *sr_buffer_cache;
struct kmem_cache *gid_pn_cache;
- struct workqueue_struct *work_queue;
-};
-
-/* struct used by memory pools for fsf_requests */
-struct zfcp_fsf_req_qtcb {
- struct zfcp_fsf_req fsf_req;
- struct fsf_qtcb qtcb;
};
/********************** ZFCP SPECIFIC DEFINES ********************************/
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index c75d6f35cb5..73d366ba31e 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -9,6 +9,7 @@
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/kthread.h>
#include "zfcp_ext.h"
#define ZFCP_MAX_ERPS 3
@@ -26,7 +27,6 @@ enum zfcp_erp_steps {
ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
- ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400,
ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000,
ZFCP_ERP_STEP_UNIT_OPENING = 0x2000,
@@ -75,9 +75,9 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
struct zfcp_adapter *adapter = act->adapter;
list_move(&act->list, &act->adapter->erp_ready_head);
- zfcp_rec_dbf_event_action("erardy1", act);
- up(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread("erardy2", adapter);
+ zfcp_dbf_rec_action("erardy1", act);
+ wake_up(&adapter->erp_ready_wq);
+ zfcp_dbf_rec_thread("erardy2", adapter->dbf);
}
static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
@@ -150,6 +150,9 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
a_status = atomic_read(&adapter->status);
if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
return 0;
+ if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
+ !(a_status & ZFCP_STATUS_COMMON_OPEN))
+ return 0; /* shutdown requested for closed adapter */
}
return need;
@@ -213,8 +216,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
int retval = 1, need;
struct zfcp_erp_action *act = NULL;
- if (!(atomic_read(&adapter->status) &
- ZFCP_STATUS_ADAPTER_ERP_THREAD_UP))
+ if (!adapter->erp_thread)
return -EIO;
need = zfcp_erp_required_act(want, adapter, port, unit);
@@ -227,12 +229,11 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
goto out;
++adapter->erp_total_count;
list_add_tail(&act->list, &adapter->erp_ready_head);
- up(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread("eracte1", adapter);
+ wake_up(&adapter->erp_ready_wq);
+ zfcp_dbf_rec_thread("eracte1", adapter->dbf);
retval = 0;
out:
- zfcp_rec_dbf_event_trigger(id, ref, want, need, act,
- adapter, port, unit);
+ zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
return retval;
}
@@ -443,28 +444,28 @@ static int status_change_clear(unsigned long mask, atomic_t *status)
static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
{
if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
- zfcp_rec_dbf_event_adapter("eraubl1", NULL, adapter);
+ zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf);
atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
}
static void zfcp_erp_port_unblock(struct zfcp_port *port)
{
if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
- zfcp_rec_dbf_event_port("erpubl1", NULL, port);
+ zfcp_dbf_rec_port("erpubl1", NULL, port);
atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
}
static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
{
if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
- zfcp_rec_dbf_event_unit("eruubl1", NULL, unit);
+ zfcp_dbf_rec_unit("eruubl1", NULL, unit);
atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
}
static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
{
list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
- zfcp_rec_dbf_event_action("erator1", erp_action);
+ zfcp_dbf_rec_action("erator1", erp_action);
}
static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
@@ -480,13 +481,12 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
ZFCP_STATUS_ERP_TIMEDOUT)) {
act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
- zfcp_rec_dbf_event_action("erscf_1", act);
+ zfcp_dbf_rec_action("erscf_1", act);
act->fsf_req->erp_action = NULL;
}
if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
- zfcp_rec_dbf_event_action("erscf_2", act);
- if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
- ZFCP_STATUS_FSFREQ_DISMISSED))
+ zfcp_dbf_rec_action("erscf_2", act);
+ if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
act->fsf_req = NULL;
} else
act->fsf_req = NULL;
@@ -604,9 +604,11 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
{
- if (zfcp_qdio_open(act->adapter))
+ struct zfcp_qdio *qdio = act->adapter->qdio;
+
+ if (zfcp_qdio_open(qdio))
return ZFCP_ERP_FAILED;
- init_waitqueue_head(&act->adapter->request_wq);
+ init_waitqueue_head(&qdio->req_q_wq);
atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
return ZFCP_ERP_SUCCEEDED;
}
@@ -641,9 +643,10 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
return ZFCP_ERP_FAILED;
}
- zfcp_rec_dbf_event_thread_lock("erasfx1", adapter);
- down(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock("erasfx2", adapter);
+ zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf);
+ wait_event(adapter->erp_ready_wq,
+ !list_empty(&adapter->erp_ready_head));
+ zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf);
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
break;
@@ -682,9 +685,10 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
if (ret)
return ZFCP_ERP_FAILED;
- zfcp_rec_dbf_event_thread_lock("erasox1", adapter);
- down(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock("erasox2", adapter);
+ zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf);
+ wait_event(adapter->erp_ready_wq,
+ !list_empty(&adapter->erp_ready_head));
+ zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf);
if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
return ZFCP_ERP_FAILED;
@@ -711,10 +715,10 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
struct zfcp_adapter *adapter = act->adapter;
/* close queues to ensure that buffers are not accessed by adapter */
- zfcp_qdio_close(adapter);
+ zfcp_qdio_close(adapter->qdio);
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
- zfcp_fc_wka_port_force_offline(&adapter->gs->ds);
+ zfcp_fc_wka_ports_force_offline(adapter->gs);
/* all ports and units are closed */
zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
@@ -841,27 +845,6 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
return zfcp_erp_port_strategy_open_port(act);
}
-void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
-{
- int retval;
- struct zfcp_port *port = container_of(work, struct zfcp_port,
- gid_pn_work);
-
- retval = zfcp_fc_ns_gid_pn(&port->erp_action);
- if (!retval) {
- port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
- goto out;
- }
- if (retval == -ENOMEM) {
- zfcp_erp_notify(&port->erp_action, ZFCP_STATUS_ERP_LOWMEM);
- goto out;
- }
- /* all other error condtions */
- zfcp_erp_notify(&port->erp_action, 0);
-out:
- zfcp_port_put(port);
-}
-
static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
{
struct zfcp_adapter *adapter = act->adapter;
@@ -876,15 +859,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
return zfcp_erp_open_ptp_port(act);
if (!port->d_id) {
zfcp_port_get(port);
- if (!queue_work(zfcp_data.work_queue,
+ if (!queue_work(adapter->work_queue,
&port->gid_pn_work))
zfcp_port_put(port);
- return ZFCP_ERP_CONTINUES;
+ return ZFCP_ERP_EXIT;
}
- /* fall through */
- case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
- if (!port->d_id)
- return ZFCP_ERP_FAILED;
return zfcp_erp_port_strategy_open_port(act);
case ZFCP_ERP_STEP_PORT_OPENING:
@@ -1163,7 +1142,7 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
}
list_del(&erp_action->list);
- zfcp_rec_dbf_event_action("eractd1", erp_action);
+ zfcp_dbf_rec_action("eractd1", erp_action);
switch (erp_action->action) {
case ZFCP_ERP_ACTION_REOPEN_UNIT:
@@ -1311,20 +1290,16 @@ static int zfcp_erp_thread(void *data)
struct list_head *next;
struct zfcp_erp_action *act;
unsigned long flags;
- int ignore;
-
- daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev));
- /* Block all signals */
- siginitsetinv(&current->blocked, 0);
- atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
- wake_up(&adapter->erp_thread_wqh);
- while (!(atomic_read(&adapter->status) &
- ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) {
+ for (;;) {
+ zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf);
+ wait_event_interruptible(adapter->erp_ready_wq,
+ !list_empty(&adapter->erp_ready_head) ||
+ kthread_should_stop());
+ zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf);
- zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
- ignore = down_interruptible(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
+ if (kthread_should_stop())
+ break;
write_lock_irqsave(&adapter->erp_lock, flags);
next = adapter->erp_ready_head.next;
@@ -1339,9 +1314,6 @@ static int zfcp_erp_thread(void *data)
}
}
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
- wake_up(&adapter->erp_thread_wqh);
-
return 0;
}
@@ -1353,18 +1325,17 @@ static int zfcp_erp_thread(void *data)
*/
int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
{
- int retval;
+ struct task_struct *thread;
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
- retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
- if (retval < 0) {
+ thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
+ dev_name(&adapter->ccw_device->dev));
+ if (IS_ERR(thread)) {
dev_err(&adapter->ccw_device->dev,
"Creating an ERP thread for the FCP device failed.\n");
- return retval;
+ return PTR_ERR(thread);
}
- wait_event(adapter->erp_thread_wqh,
- atomic_read(&adapter->status) &
- ZFCP_STATUS_ADAPTER_ERP_THREAD_UP);
+
+ adapter->erp_thread = thread;
return 0;
}
@@ -1379,16 +1350,10 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
*/
void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
{
- atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
- up(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock("erthrk1", adapter);
-
- wait_event(adapter->erp_thread_wqh,
- !(atomic_read(&adapter->status) &
- ZFCP_STATUS_ADAPTER_ERP_THREAD_UP));
-
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
- &adapter->status);
+ kthread_stop(adapter->erp_thread);
+ adapter->erp_thread = NULL;
+ WARN_ON(!list_empty(&adapter->erp_ready_head));
+ WARN_ON(!list_empty(&adapter->erp_running_head));
}
/**
@@ -1456,11 +1421,11 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
if (set_or_clear == ZFCP_SET) {
if (status_change_set(mask, &adapter->status))
- zfcp_rec_dbf_event_adapter(id, ref, adapter);
+ zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
atomic_set_mask(mask, &adapter->status);
} else {
if (status_change_clear(mask, &adapter->status))
- zfcp_rec_dbf_event_adapter(id, ref, adapter);
+ zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
atomic_clear_mask(mask, &adapter->status);
if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
atomic_set(&adapter->erp_counter, 0);
@@ -1490,11 +1455,11 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
if (set_or_clear == ZFCP_SET) {
if (status_change_set(mask, &port->status))
- zfcp_rec_dbf_event_port(id, ref, port);
+ zfcp_dbf_rec_port(id, ref, port);
atomic_set_mask(mask, &port->status);
} else {
if (status_change_clear(mask, &port->status))
- zfcp_rec_dbf_event_port(id, ref, port);
+ zfcp_dbf_rec_port(id, ref, port);
atomic_clear_mask(mask, &port->status);
if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
atomic_set(&port->erp_counter, 0);
@@ -1519,11 +1484,11 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
{
if (set_or_clear == ZFCP_SET) {
if (status_change_set(mask, &unit->status))
- zfcp_rec_dbf_event_unit(id, ref, unit);
+ zfcp_dbf_rec_unit(id, ref, unit);
atomic_set_mask(mask, &unit->status);
} else {
if (status_change_clear(mask, &unit->status))
- zfcp_rec_dbf_event_unit(id, ref, unit);
+ zfcp_dbf_rec_unit(id, ref, unit);
atomic_clear_mask(mask, &unit->status);
if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
atomic_set(&unit->erp_counter, 0);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 3044c601030..36935bc0818 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -34,37 +34,31 @@ extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
extern struct miscdevice zfcp_cfdc_misc;
/* zfcp_dbf.c */
-extern int zfcp_adapter_debug_register(struct zfcp_adapter *);
-extern void zfcp_adapter_debug_unregister(struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_thread(char *, struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_thread_lock(char *, struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_adapter(char *, void *, struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_port(char *, void *, struct zfcp_port *);
-extern void zfcp_rec_dbf_event_unit(char *, void *, struct zfcp_unit *);
-extern void zfcp_rec_dbf_event_trigger(char *, void *, u8, u8, void *,
- struct zfcp_adapter *,
- struct zfcp_port *, struct zfcp_unit *);
-extern void zfcp_rec_dbf_event_action(char *, struct zfcp_erp_action *);
-extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
-extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
- struct fsf_status_read_buffer *);
-extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int,
- int);
-extern void zfcp_hba_dbf_event_berr(struct zfcp_adapter *,
- struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
-extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
- struct scsi_cmnd *,
- struct zfcp_fsf_req *);
-extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
- struct scsi_cmnd *, struct zfcp_fsf_req *,
- unsigned long);
-extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
- struct scsi_cmnd *);
+extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
+extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *);
+extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *);
+extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
+extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
+extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
+extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *);
+extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
+ struct zfcp_adapter *, struct zfcp_port *,
+ struct zfcp_unit *);
+extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
+extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
+ struct zfcp_dbf *);
+extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *,
+ struct fsf_status_read_buffer *);
+extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int);
+extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *);
+extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *,
+ struct scsi_cmnd *, struct zfcp_fsf_req *,
+ unsigned long);
/* zfcp_erp.c */
extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *,
@@ -96,22 +90,20 @@ extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
void *);
extern void zfcp_erp_timeout_handler(unsigned long);
-extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *);
/* zfcp_fc.c */
-extern int zfcp_scan_ports(struct zfcp_adapter *);
-extern void _zfcp_scan_ports_later(struct work_struct *);
+extern int zfcp_fc_scan_ports(struct zfcp_adapter *);
+extern void _zfcp_fc_scan_ports_later(struct work_struct *);
extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
-extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *);
+extern void zfcp_fc_port_did_lookup(struct work_struct *);
extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
-extern void zfcp_test_link(struct zfcp_port *);
+extern void zfcp_fc_test_link(struct zfcp_port *);
extern void zfcp_fc_link_test_work(struct work_struct *);
-extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
-extern void zfcp_fc_wka_ports_init(struct zfcp_adapter *);
+extern void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *);
+extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
+extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
extern int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *);
extern int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *);
-extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
-
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
@@ -122,37 +114,39 @@ extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
-extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *,
+extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *,
struct fsf_qtcb_bottom_config *);
extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *);
-extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *,
+extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *,
struct fsf_qtcb_bottom_port *);
extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *,
struct zfcp_fsf_cfdc *);
extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
-extern int zfcp_fsf_status_read(struct zfcp_adapter *);
+extern int zfcp_fsf_status_read(struct zfcp_qdio *);
extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
-extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
- struct zfcp_erp_action *);
+extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *);
extern int zfcp_fsf_send_els(struct zfcp_send_els *);
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
struct scsi_cmnd *);
-extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
struct zfcp_unit *);
+extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
/* zfcp_qdio.c */
-extern int zfcp_qdio_allocate(struct zfcp_adapter *);
-extern void zfcp_qdio_free(struct zfcp_adapter *);
-extern int zfcp_qdio_send(struct zfcp_fsf_req *);
-extern struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *);
-extern struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *);
-extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long,
+extern int zfcp_qdio_setup(struct zfcp_adapter *);
+extern void zfcp_qdio_destroy(struct zfcp_qdio *);
+extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_queue_req *);
+extern struct qdio_buffer_element
+ *zfcp_qdio_sbale_req(struct zfcp_qdio *, struct zfcp_queue_req *);
+extern struct qdio_buffer_element
+ *zfcp_qdio_sbale_curr(struct zfcp_qdio *, struct zfcp_queue_req *);
+extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *,
+ struct zfcp_queue_req *, unsigned long,
struct scatterlist *, int);
-extern int zfcp_qdio_open(struct zfcp_adapter *);
-extern void zfcp_qdio_close(struct zfcp_adapter *);
+extern int zfcp_qdio_open(struct zfcp_qdio *);
+extern void zfcp_qdio_close(struct zfcp_qdio *);
/* zfcp_scsi.c */
extern struct zfcp_data zfcp_data;
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 47daebfa7e5..722f22de875 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -25,14 +25,6 @@ static u32 rscn_range_mask[] = {
[RSCN_FABRIC_ADDRESS] = 0x000000,
};
-struct ct_iu_gpn_ft_req {
- struct ct_hdr header;
- u8 flags;
- u8 domain_id_scope;
- u8 area_id_scope;
- u8 fc4_type;
-} __attribute__ ((packed));
-
struct gpn_ft_resp_acc {
u8 control;
u8 port_id[3];
@@ -65,7 +57,7 @@ struct zfcp_fc_ns_handler_data {
unsigned long handler_data;
};
-static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
+static int zfcp_fc_wka_port_get(struct zfcp_wka_port *wka_port)
{
if (mutex_lock_interruptible(&wka_port->mutex))
return -ERESTARTSYS;
@@ -90,7 +82,7 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
return -EIO;
}
-static void zfcp_wka_port_offline(struct work_struct *work)
+static void zfcp_fc_wka_port_offline(struct work_struct *work)
{
struct delayed_work *dw = to_delayed_work(work);
struct zfcp_wka_port *wka_port =
@@ -110,7 +102,7 @@ out:
mutex_unlock(&wka_port->mutex);
}
-static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port)
+static void zfcp_fc_wka_port_put(struct zfcp_wka_port *wka_port)
{
if (atomic_dec_return(&wka_port->refcount) != 0)
return;
@@ -129,10 +121,10 @@ static void zfcp_fc_wka_port_init(struct zfcp_wka_port *wka_port, u32 d_id,
wka_port->status = ZFCP_WKA_PORT_OFFLINE;
atomic_set(&wka_port->refcount, 0);
mutex_init(&wka_port->mutex);
- INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
+ INIT_DELAYED_WORK(&wka_port->work, zfcp_fc_wka_port_offline);
}
-void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
+static void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
{
cancel_delayed_work_sync(&wka->work);
mutex_lock(&wka->mutex);
@@ -140,15 +132,13 @@ void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
mutex_unlock(&wka->mutex);
}
-void zfcp_fc_wka_ports_init(struct zfcp_adapter *adapter)
+void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *gs)
{
- struct zfcp_wka_ports *gs = adapter->gs;
-
- zfcp_fc_wka_port_init(&gs->ms, FC_FID_MGMT_SERV, adapter);
- zfcp_fc_wka_port_init(&gs->ts, FC_FID_TIME_SERV, adapter);
- zfcp_fc_wka_port_init(&gs->ds, FC_FID_DIR_SERV, adapter);
- zfcp_fc_wka_port_init(&gs->as, FC_FID_ALIASES, adapter);
- zfcp_fc_wka_port_init(&gs->ks, FC_FID_SEC_KEY, adapter);
+ zfcp_fc_wka_port_force_offline(&gs->ms);
+ zfcp_fc_wka_port_force_offline(&gs->ts);
+ zfcp_fc_wka_port_force_offline(&gs->ds);
+ zfcp_fc_wka_port_force_offline(&gs->as);
+ zfcp_fc_wka_port_force_offline(&gs->ks);
}
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
@@ -160,7 +150,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
if ((port->d_id & range) == (elem->nport_did & range))
- zfcp_test_link(port);
+ zfcp_fc_test_link(port);
if (!port->d_id)
zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -241,7 +231,7 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req)
(struct fsf_status_read_buffer *) fsf_req->data;
unsigned int els_type = status_buffer->payload.data[0];
- zfcp_san_dbf_event_incoming_els(fsf_req);
+ zfcp_dbf_san_incoming_els(fsf_req);
if (els_type == LS_PLOGI)
zfcp_fc_incoming_plogi(fsf_req);
else if (els_type == LS_LOGO)
@@ -281,19 +271,18 @@ static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
}
-int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
+static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
struct zfcp_gid_pn_data *gid_pn)
{
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_adapter *adapter = port->adapter;
struct zfcp_fc_ns_handler_data compl_rec;
int ret;
/* setup parameters for send generic command */
- gid_pn->port = erp_action->port;
+ gid_pn->port = port;
gid_pn->ct.wka_port = &adapter->gs->ds;
gid_pn->ct.handler = zfcp_fc_ns_handler;
gid_pn->ct.handler_data = (unsigned long) &compl_rec;
- gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
gid_pn->ct.req = &gid_pn->req;
gid_pn->ct.resp = &gid_pn->resp;
sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req,
@@ -308,13 +297,12 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS;
gid_pn->ct_iu_req.header.cmd_rsp_code = ZFCP_CT_GID_PN;
gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_SIZE_ONE_PAGE / 4;
- gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
+ gid_pn->ct_iu_req.wwpn = port->wwpn;
init_completion(&compl_rec.done);
compl_rec.handler = zfcp_fc_ns_gid_pn_eval;
compl_rec.handler_data = (unsigned long) gid_pn;
- ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
- erp_action);
+ ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.gid_pn_req);
if (!ret)
wait_for_completion(&compl_rec.done);
return ret;
@@ -322,33 +310,56 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
/**
* zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
- * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
+ * @port: port where GID_PN request is needed
* return: -ENOMEM on error, 0 otherwise
*/
-int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action)
+static int zfcp_fc_ns_gid_pn(struct zfcp_port *port)
{
int ret;
struct zfcp_gid_pn_data *gid_pn;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_adapter *adapter = port->adapter;
- gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
+ gid_pn = mempool_alloc(adapter->pool.gid_pn_data, GFP_ATOMIC);
if (!gid_pn)
return -ENOMEM;
memset(gid_pn, 0, sizeof(*gid_pn));
- ret = zfcp_wka_port_get(&adapter->gs->ds);
+ ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
if (ret)
goto out;
- ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn);
+ ret = zfcp_fc_ns_gid_pn_request(port, gid_pn);
- zfcp_wka_port_put(&adapter->gs->ds);
+ zfcp_fc_wka_port_put(&adapter->gs->ds);
out:
- mempool_free(gid_pn, adapter->pool.data_gid_pn);
+ mempool_free(gid_pn, adapter->pool.gid_pn_data);
return ret;
}
+void zfcp_fc_port_did_lookup(struct work_struct *work)
+{
+ int ret;
+ struct zfcp_port *port = container_of(work, struct zfcp_port,
+ gid_pn_work);
+
+ ret = zfcp_fc_ns_gid_pn(port);
+ if (ret) {
+ /* could not issue gid_pn for some reason */
+ zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1", NULL);
+ goto out;
+ }
+
+ if (!port->d_id) {
+ zfcp_erp_port_failed(port, "fcgpn_2", NULL);
+ goto out;
+ }
+
+ zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL);
+out:
+ zfcp_port_put(port);
+}
+
/**
* zfcp_fc_plogi_evaluate - evaluate PLOGI playload
* @port: zfcp_port structure
@@ -404,6 +415,7 @@ static void zfcp_fc_adisc_handler(unsigned long data)
/* port is good, unblock rport without going through erp */
zfcp_scsi_schedule_rport_register(port);
out:
+ atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
zfcp_port_put(port);
kfree(adisc);
}
@@ -450,28 +462,36 @@ void zfcp_fc_link_test_work(struct work_struct *work)
port->rport_task = RPORT_DEL;
zfcp_scsi_rport_work(&port->rport_work);
+ /* only issue one test command at one time per port */
+ if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
+ goto out;
+
+ atomic_set_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
+
retval = zfcp_fc_adisc(port);
if (retval == 0)
return;
/* send of ADISC was not possible */
+ atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL);
+out:
zfcp_port_put(port);
}
/**
- * zfcp_test_link - lightweight link test procedure
+ * zfcp_fc_test_link - lightweight link test procedure
* @port: port to be tested
*
* Test status of a link to a remote port using the ELS command ADISC.
* If there is a problem with the remote port, error recovery steps
* will be triggered.
*/
-void zfcp_test_link(struct zfcp_port *port)
+void zfcp_fc_test_link(struct zfcp_port *port)
{
zfcp_port_get(port);
- if (!queue_work(zfcp_data.work_queue, &port->test_link_work))
+ if (!queue_work(port->adapter->work_queue, &port->test_link_work))
zfcp_port_put(port);
}
@@ -479,7 +499,7 @@ static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num)
{
struct scatterlist *sg = &gpn_ft->sg_req;
- kfree(sg_virt(sg)); /* free request buffer */
+ kmem_cache_free(zfcp_data.gpn_ft_cache, sg_virt(sg));
zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
kfree(gpn_ft);
@@ -494,7 +514,7 @@ static struct zfcp_gpn_ft *zfcp_alloc_sg_env(int buf_num)
if (!gpn_ft)
return NULL;
- req = kzalloc(sizeof(struct ct_iu_gpn_ft_req), GFP_KERNEL);
+ req = kmem_cache_alloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
if (!req) {
kfree(gpn_ft);
gpn_ft = NULL;
@@ -511,9 +531,8 @@ out:
}
-static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
- struct zfcp_adapter *adapter,
- int max_bytes)
+static int zfcp_fc_send_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
+ struct zfcp_adapter *adapter, int max_bytes)
{
struct zfcp_send_ct *ct = &gpn_ft->ct;
struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
@@ -536,19 +555,18 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
ct->wka_port = &adapter->gs->ds;
ct->handler = zfcp_fc_ns_handler;
ct->handler_data = (unsigned long)&compl_rec;
- ct->timeout = 10;
ct->req = &gpn_ft->sg_req;
ct->resp = gpn_ft->sg_resp;
init_completion(&compl_rec.done);
compl_rec.handler = NULL;
- ret = zfcp_fsf_send_ct(ct, NULL, NULL);
+ ret = zfcp_fsf_send_ct(ct, NULL);
if (!ret)
wait_for_completion(&compl_rec.done);
return ret;
}
-static void zfcp_validate_port(struct zfcp_port *port)
+static void zfcp_fc_validate_port(struct zfcp_port *port)
{
struct zfcp_adapter *adapter = port->adapter;
@@ -568,7 +586,7 @@ static void zfcp_validate_port(struct zfcp_port *port)
zfcp_port_dequeue(port);
}
-static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
+static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
{
struct zfcp_send_ct *ct = &gpn_ft->ct;
struct scatterlist *sg = gpn_ft->sg_resp;
@@ -595,7 +613,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
return -E2BIG;
}
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
/* first entry is the header */
for (x = 1; x < max_entries && !last; x++) {
@@ -628,16 +646,16 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
zfcp_erp_wait(adapter);
list_for_each_entry_safe(port, tmp, &adapter->port_list_head, list)
- zfcp_validate_port(port);
- up(&zfcp_data.config_sema);
+ zfcp_fc_validate_port(port);
+ mutex_unlock(&zfcp_data.config_mutex);
return ret;
}
/**
- * zfcp_scan_ports - scan remote ports and attach new ports
+ * zfcp_fc_scan_ports - scan remote ports and attach new ports
* @adapter: pointer to struct zfcp_adapter
*/
-int zfcp_scan_ports(struct zfcp_adapter *adapter)
+int zfcp_fc_scan_ports(struct zfcp_adapter *adapter)
{
int ret, i;
struct zfcp_gpn_ft *gpn_ft;
@@ -652,7 +670,7 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
return 0;
- ret = zfcp_wka_port_get(&adapter->gs->ds);
+ ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
if (ret)
return ret;
@@ -663,9 +681,9 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
}
for (i = 0; i < 3; i++) {
- ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter, max_bytes);
+ ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes);
if (!ret) {
- ret = zfcp_scan_eval_gpn_ft(gpn_ft, max_entries);
+ ret = zfcp_fc_eval_gpn_ft(gpn_ft, max_entries);
if (ret == -EAGAIN)
ssleep(1);
else
@@ -674,14 +692,14 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
}
zfcp_free_sg_env(gpn_ft, buf_num);
out:
- zfcp_wka_port_put(&adapter->gs->ds);
+ zfcp_fc_wka_port_put(&adapter->gs->ds);
return ret;
}
-void _zfcp_scan_ports_later(struct work_struct *work)
+void _zfcp_fc_scan_ports_later(struct work_struct *work)
{
- zfcp_scan_ports(container_of(work, struct zfcp_adapter, scan_work));
+ zfcp_fc_scan_ports(container_of(work, struct zfcp_adapter, scan_work));
}
struct zfcp_els_fc_job {
@@ -732,7 +750,7 @@ int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job)
els_fc_job->els.adapter = adapter;
if (rport) {
read_lock_irq(&zfcp_data.config_lock);
- port = rport->dd_data;
+ port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
if (port)
els_fc_job->els.d_id = port->d_id;
read_unlock_irq(&zfcp_data.config_lock);
@@ -771,7 +789,7 @@ static void zfcp_fc_generic_ct_handler(unsigned long data)
job->state_flags = FC_RQST_STATE_DONE;
job->job_done(job);
- zfcp_wka_port_put(ct_fc_job->ct.wka_port);
+ zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port);
kfree(ct_fc_job);
}
@@ -817,7 +835,7 @@ int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job)
return -EINVAL; /* no such service */
}
- ret = zfcp_wka_port_get(ct_fc_job->ct.wka_port);
+ ret = zfcp_fc_wka_port_get(ct_fc_job->ct.wka_port);
if (ret) {
kfree(ct_fc_job);
return ret;
@@ -825,16 +843,40 @@ int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job)
ct_fc_job->ct.req = job->request_payload.sg_list;
ct_fc_job->ct.resp = job->reply_payload.sg_list;
- ct_fc_job->ct.timeout = ZFCP_FSF_REQUEST_TIMEOUT;
ct_fc_job->ct.handler = zfcp_fc_generic_ct_handler;
ct_fc_job->ct.handler_data = (unsigned long) ct_fc_job;
ct_fc_job->ct.completion = NULL;
ct_fc_job->job = job;
- ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL, NULL);
+ ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL);
if (ret) {
kfree(ct_fc_job);
- zfcp_wka_port_put(ct_fc_job->ct.wka_port);
+ zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port);
}
return ret;
}
+
+int zfcp_fc_gs_setup(struct zfcp_adapter *adapter)
+{
+ struct zfcp_wka_ports *wka_ports;
+
+ wka_ports = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL);
+ if (!wka_ports)
+ return -ENOMEM;
+
+ adapter->gs = wka_ports;
+ zfcp_fc_wka_port_init(&wka_ports->ms, FC_FID_MGMT_SERV, adapter);
+ zfcp_fc_wka_port_init(&wka_ports->ts, FC_FID_TIME_SERV, adapter);
+ zfcp_fc_wka_port_init(&wka_ports->ds, FC_FID_DIR_SERV, adapter);
+ zfcp_fc_wka_port_init(&wka_ports->as, FC_FID_ALIASES, adapter);
+ zfcp_fc_wka_port_init(&wka_ports->ks, FC_FID_SEC_KEY, adapter);
+
+ return 0;
+}
+
+void zfcp_fc_gs_destroy(struct zfcp_adapter *adapter)
+{
+ kfree(adapter->gs);
+ adapter->gs = NULL;
+}
+
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 47795fbf081..f09c863dc6b 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -11,9 +11,7 @@
#include <linux/blktrace_api.h>
#include "zfcp_ext.h"
-
-#define ZFCP_REQ_AUTO_CLEANUP 0x00000002
-#define ZFCP_REQ_NO_QTCB 0x00000008
+#include "zfcp_dbf.h"
static void zfcp_fsf_request_timeout_handler(unsigned long data)
{
@@ -111,43 +109,15 @@ static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
{
if (likely(req->pool)) {
+ if (likely(req->qtcb))
+ mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
mempool_free(req, req->pool);
return;
}
- if (req->qtcb) {
- kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, req);
- return;
- }
-}
-
-/**
- * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
- * @adapter: pointer to struct zfcp_adapter
- *
- * Never ever call this without shutting down the adapter first.
- * Otherwise the adapter would continue using and corrupting s390 storage.
- * Included BUG_ON() call to ensure this is done.
- * ERP is supposed to be the only user of this function.
- */
-void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
-{
- struct zfcp_fsf_req *req, *tmp;
- unsigned long flags;
- LIST_HEAD(remove_queue);
- unsigned int i;
-
- BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
- spin_lock_irqsave(&adapter->req_list_lock, flags);
- for (i = 0; i < REQUEST_LIST_SIZE; i++)
- list_splice_init(&adapter->req_list[i], &remove_queue);
- spin_unlock_irqrestore(&adapter->req_list_lock, flags);
-
- list_for_each_entry_safe(req, tmp, &remove_queue, list) {
- list_del(&req->list);
- req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
- zfcp_fsf_req_complete(req);
- }
+ if (likely(req->qtcb))
+ kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
+ kfree(req);
}
static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
@@ -278,13 +248,13 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
struct fsf_status_read_buffer *sr_buf = req->data;
if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
- zfcp_hba_dbf_event_fsf_unsol("dism", adapter, sr_buf);
- mempool_free(sr_buf, adapter->pool.data_status_read);
+ zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
+ mempool_free(sr_buf, adapter->pool.status_read_data);
zfcp_fsf_req_free(req);
return;
}
- zfcp_hba_dbf_event_fsf_unsol("read", adapter, sr_buf);
+ zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf);
switch (sr_buf->status_type) {
case FSF_STATUS_READ_PORT_CLOSED:
@@ -299,7 +269,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
dev_warn(&adapter->ccw_device->dev,
"The error threshold for checksum statistics "
"has been exceeded\n");
- zfcp_hba_dbf_event_berr(adapter, req);
+ zfcp_dbf_hba_berr(adapter->dbf, req);
break;
case FSF_STATUS_READ_LINK_DOWN:
zfcp_fsf_status_read_link_down(req);
@@ -331,11 +301,11 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
break;
}
- mempool_free(sr_buf, adapter->pool.data_status_read);
+ mempool_free(sr_buf, adapter->pool.status_read_data);
zfcp_fsf_req_free(req);
atomic_inc(&adapter->stat_miss);
- queue_work(zfcp_data.work_queue, &adapter->stat_work);
+ queue_work(adapter->work_queue, &adapter->stat_work);
}
static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
@@ -385,7 +355,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
struct fsf_qtcb *qtcb = req->qtcb;
union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual;
- zfcp_hba_dbf_event_fsf_response(req);
+ zfcp_dbf_hba_fsf_response(req);
if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
req->status |= ZFCP_STATUS_FSFREQ_ERROR |
@@ -458,7 +428,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
* is called to process the completion status and trigger further
* events related to the FSF request.
*/
-void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
+static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
{
if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
zfcp_fsf_status_read_handler(req);
@@ -472,23 +442,40 @@ void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
if (req->erp_action)
zfcp_erp_notify(req->erp_action, 0);
- req->status |= ZFCP_STATUS_FSFREQ_COMPLETED;
if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
zfcp_fsf_req_free(req);
else
- /* notify initiator waiting for the requests completion */
- /*
- * FIXME: Race! We must not access fsf_req here as it might have been
- * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED
- * flag. It's an improbable case. But, we have the same paranoia for
- * the cleanup flag already.
- * Might better be handled using complete()?
- * (setting the flag and doing wakeup ought to be atomic
- * with regard to checking the flag as long as waitqueue is
- * part of the to be released structure)
- */
- wake_up(&req->completion_wq);
+ complete(&req->completion);
+}
+
+/**
+ * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
+ * @adapter: pointer to struct zfcp_adapter
+ *
+ * Never ever call this without shutting down the adapter first.
+ * Otherwise the adapter would continue using and corrupting s390 storage.
+ * Included BUG_ON() call to ensure this is done.
+ * ERP is supposed to be the only user of this function.
+ */
+void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
+{
+ struct zfcp_fsf_req *req, *tmp;
+ unsigned long flags;
+ LIST_HEAD(remove_queue);
+ unsigned int i;
+
+ BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
+ for (i = 0; i < REQUEST_LIST_SIZE; i++)
+ list_splice_init(&adapter->req_list[i], &remove_queue);
+ spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+ list_for_each_entry_safe(req, tmp, &remove_queue, list) {
+ list_del(&req->list);
+ req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
+ zfcp_fsf_req_complete(req);
+ }
}
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
@@ -650,79 +637,77 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
}
}
-static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter)
+static int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
{
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
+ struct zfcp_qdio_queue *req_q = &qdio->req_q;
- spin_lock_bh(&adapter->req_q_lock);
+ spin_lock_bh(&qdio->req_q_lock);
if (atomic_read(&req_q->count))
return 1;
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return 0;
}
-static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
+static int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
{
+ struct zfcp_adapter *adapter = qdio->adapter;
long ret;
- spin_unlock_bh(&adapter->req_q_lock);
- ret = wait_event_interruptible_timeout(adapter->request_wq,
- zfcp_fsf_sbal_check(adapter), 5 * HZ);
+ spin_unlock_bh(&qdio->req_q_lock);
+ ret = wait_event_interruptible_timeout(qdio->req_q_wq,
+ zfcp_fsf_sbal_check(qdio), 5 * HZ);
if (ret > 0)
return 0;
if (!ret) {
- atomic_inc(&adapter->qdio_outb_full);
+ atomic_inc(&qdio->req_q_full);
/* assume hanging outbound queue, try queue recovery */
zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
}
- spin_lock_bh(&adapter->req_q_lock);
+ spin_lock_bh(&qdio->req_q_lock);
return -EIO;
}
-static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool)
+static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
{
struct zfcp_fsf_req *req;
- req = mempool_alloc(pool, GFP_ATOMIC);
- if (!req)
+
+ if (likely(pool))
+ req = mempool_alloc(pool, GFP_ATOMIC);
+ else
+ req = kmalloc(sizeof(*req), GFP_ATOMIC);
+
+ if (unlikely(!req))
return NULL;
+
memset(req, 0, sizeof(*req));
req->pool = pool;
return req;
}
-static struct zfcp_fsf_req *zfcp_fsf_alloc_qtcb(mempool_t *pool)
+static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
{
- struct zfcp_fsf_req_qtcb *qtcb;
+ struct fsf_qtcb *qtcb;
if (likely(pool))
qtcb = mempool_alloc(pool, GFP_ATOMIC);
else
- qtcb = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
- GFP_ATOMIC);
+ qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);
+
if (unlikely(!qtcb))
return NULL;
memset(qtcb, 0, sizeof(*qtcb));
- qtcb->fsf_req.qtcb = &qtcb->qtcb;
- qtcb->fsf_req.pool = pool;
-
- return &qtcb->fsf_req;
+ return qtcb;
}
-static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
- u32 fsf_cmd, int req_flags,
- mempool_t *pool)
+static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
+ u32 fsf_cmd, mempool_t *pool)
{
struct qdio_buffer_element *sbale;
-
- struct zfcp_fsf_req *req;
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
-
- if (req_flags & ZFCP_REQ_NO_QTCB)
- req = zfcp_fsf_alloc_noqtcb(pool);
- else
- req = zfcp_fsf_alloc_qtcb(pool);
+ struct zfcp_qdio_queue *req_q = &qdio->req_q;
+ struct zfcp_adapter *adapter = qdio->adapter;
+ struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
if (unlikely(!req))
return ERR_PTR(-ENOMEM);
@@ -732,22 +717,32 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
INIT_LIST_HEAD(&req->list);
init_timer(&req->timer);
- init_waitqueue_head(&req->completion_wq);
+ init_completion(&req->completion);
req->adapter = adapter;
req->fsf_command = fsf_cmd;
req->req_id = adapter->req_no;
- req->sbal_number = 1;
- req->sbal_first = req_q->first;
- req->sbal_last = req_q->first;
- req->sbale_curr = 1;
+ req->queue_req.sbal_number = 1;
+ req->queue_req.sbal_first = req_q->first;
+ req->queue_req.sbal_last = req_q->first;
+ req->queue_req.sbale_curr = 1;
- sbale = zfcp_qdio_sbale_req(req);
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].addr = (void *) req->req_id;
sbale[0].flags |= SBAL_FLAGS0_COMMAND;
- if (likely(req->qtcb)) {
- req->qtcb->prefix.req_seq_no = req->adapter->fsf_req_seq_no;
+ if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
+ if (likely(pool))
+ req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
+ else
+ req->qtcb = zfcp_qtcb_alloc(NULL);
+
+ if (unlikely(!req->qtcb)) {
+ zfcp_fsf_req_free(req);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
req->qtcb->prefix.req_id = req->req_id;
req->qtcb->prefix.ulp_info = 26;
req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command];
@@ -765,15 +760,13 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
return ERR_PTR(-EIO);
}
- if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP))
- req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-
return req;
}
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
+ struct zfcp_qdio *qdio = adapter->qdio;
unsigned long flags;
int idx;
int with_qtcb = (req->qtcb != NULL);
@@ -784,9 +777,9 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
list_add_tail(&req->list, &adapter->req_list[idx]);
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
- req->qdio_outb_usage = atomic_read(&adapter->req_q.count);
+ req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
req->issued = get_clock();
- if (zfcp_qdio_send(req)) {
+ if (zfcp_qdio_send(qdio, &req->queue_req)) {
del_timer(&req->timer);
spin_lock_irqsave(&adapter->req_list_lock, flags);
/* lookup request again, list might have changed */
@@ -811,38 +804,37 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
* @req_flags: request flags
* Returns: 0 on success, ERROR otherwise
*/
-int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
+int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
{
+ struct zfcp_adapter *adapter = qdio->adapter;
struct zfcp_fsf_req *req;
struct fsf_status_read_buffer *sr_buf;
struct qdio_buffer_element *sbale;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS,
- ZFCP_REQ_NO_QTCB,
- adapter->pool.fsf_req_status_read);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
+ adapter->pool.status_read_req);
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
- sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
- req->sbale_curr = 2;
+ req->queue_req.sbale_curr = 2;
- sr_buf = mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC);
+ sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
if (!sr_buf) {
retval = -ENOMEM;
goto failed_buf;
}
memset(sr_buf, 0, sizeof(*sr_buf));
req->data = sr_buf;
- sbale = zfcp_qdio_sbale_curr(req);
+ sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req);
sbale->addr = (void *) sr_buf;
sbale->length = sizeof(*sr_buf);
@@ -853,12 +845,12 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
goto out;
failed_req_send:
- mempool_free(sr_buf, adapter->pool.data_status_read);
+ mempool_free(sr_buf, adapter->pool.status_read_data);
failed_buf:
zfcp_fsf_req_free(req);
- zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
+ zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -900,7 +892,7 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (fsq->word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_test_link(unit->port);
+ zfcp_fc_test_link(unit->port);
/* fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -925,13 +917,13 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
{
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
- struct zfcp_adapter *adapter = unit->port->adapter;
+ struct zfcp_qdio *qdio = unit->port->adapter->qdio;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
- 0, adapter->pool.fsf_req_abort);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
+ qdio->adapter->pool.scsi_abort);
if (IS_ERR(req)) {
req = NULL;
goto out;
@@ -941,7 +933,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
ZFCP_STATUS_COMMON_UNBLOCKED)))
goto out_error_free;
- sbale = zfcp_qdio_sbale_req(req);
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -959,7 +951,7 @@ out_error_free:
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return req;
}
@@ -976,7 +968,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
switch (header->fsf_status) {
case FSF_GOOD:
- zfcp_san_dbf_event_ct_response(req);
+ zfcp_dbf_san_ct_response(req);
send_ct->status = 0;
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1035,8 +1027,10 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
struct scatterlist *sg_resp,
int max_sbals)
{
- struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req);
- u32 feat = req->adapter->adapter_features;
+ struct zfcp_adapter *adapter = req->adapter;
+ struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
+ &req->queue_req);
+ u32 feat = adapter->adapter_features;
int bytes;
if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
@@ -1053,18 +1047,25 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
return 0;
}
- bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
+ bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
+ SBAL_FLAGS0_TYPE_WRITE_READ,
sg_req, max_sbals);
if (bytes <= 0)
return -EIO;
req->qtcb->bottom.support.req_buf_length = bytes;
- req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
+ req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
- bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
+ bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
+ SBAL_FLAGS0_TYPE_WRITE_READ,
sg_resp, max_sbals);
if (bytes <= 0)
return -EIO;
+
+ /* common settings for ct/gs and els requests */
req->qtcb->bottom.support.resp_buf_length = bytes;
+ req->qtcb->bottom.support.service_class = FSF_CLASS_3;
+ req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
+ zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10);
return 0;
}
@@ -1073,27 +1074,26 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
* zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
* @ct: pointer to struct zfcp_send_ct with data for request
* @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
- * @erp_action: if non-null the Generic Service request sent within ERP
*/
-int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
- struct zfcp_erp_action *erp_action)
+int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
{
struct zfcp_wka_port *wka_port = ct->wka_port;
- struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_qdio *qdio = wka_port->adapter->qdio;
struct zfcp_fsf_req *req;
int ret = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,
- ZFCP_REQ_AUTO_CLEANUP, pool);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool);
+
if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
FSF_MAX_SBALS_PER_REQ);
if (ret)
@@ -1101,18 +1101,9 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
req->handler = zfcp_fsf_send_ct_handler;
req->qtcb->header.port_handle = wka_port->handle;
- req->qtcb->bottom.support.service_class = FSF_CLASS_3;
- req->qtcb->bottom.support.timeout = ct->timeout;
req->data = ct;
- zfcp_san_dbf_event_ct_request(req);
-
- if (erp_action) {
- erp_action->fsf_req = req;
- req->erp_action = erp_action;
- zfcp_fsf_start_erp_timer(req);
- } else
- zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
+ zfcp_dbf_san_ct_request(req);
ret = zfcp_fsf_req_send(req);
if (ret)
@@ -1122,10 +1113,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
failed_send:
zfcp_fsf_req_free(req);
- if (erp_action)
- erp_action->fsf_req = NULL;
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return ret;
}
@@ -1142,7 +1131,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
switch (header->fsf_status) {
case FSF_GOOD:
- zfcp_san_dbf_event_els_response(req);
+ zfcp_dbf_san_els_response(req);
send_els->status = 0;
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1152,7 +1141,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
switch (header->fsf_status_qual.word[0]){
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
if (port && (send_els->ls_code != ZFCP_LS_ADISC))
- zfcp_test_link(port);
+ zfcp_fc_test_link(port);
/*fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
case FSF_SQ_RETRY_IF_POSSIBLE:
@@ -1188,35 +1177,32 @@ skip_fsfstatus:
int zfcp_fsf_send_els(struct zfcp_send_els *els)
{
struct zfcp_fsf_req *req;
- struct zfcp_adapter *adapter = els->adapter;
- struct fsf_qtcb_bottom_support *bottom;
+ struct zfcp_qdio *qdio = els->adapter->qdio;
int ret = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
- ZFCP_REQ_AUTO_CLEANUP, NULL);
+
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL);
+
if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
if (ret)
goto failed_send;
- bottom = &req->qtcb->bottom.support;
+ req->qtcb->bottom.support.d_id = els->d_id;
req->handler = zfcp_fsf_send_els_handler;
- bottom->d_id = els->d_id;
- bottom->service_class = FSF_CLASS_3;
- bottom->timeout = 2 * R_A_TOV;
req->data = els;
- zfcp_san_dbf_event_els_request(req);
+ zfcp_dbf_san_els_request(req);
- zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
ret = zfcp_fsf_req_send(req);
if (ret)
goto failed_send;
@@ -1226,7 +1212,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
failed_send:
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return ret;
}
@@ -1234,22 +1220,23 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
{
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_qdio *qdio = erp_action->adapter->qdio;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter,
- FSF_QTCB_EXCHANGE_CONFIG_DATA,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
+ qdio->adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1269,29 +1256,29 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
-int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
+int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
struct fsf_qtcb_bottom_config *data)
{
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out_unlock;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
- 0, NULL);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out_unlock;
}
- sbale = zfcp_qdio_sbale_req(req);
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
req->handler = zfcp_fsf_exchange_config_data_handler;
@@ -1307,16 +1294,15 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
if (!retval)
- wait_event(req->completion_wq,
- req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&req->completion);
zfcp_fsf_req_free(req);
return retval;
out_unlock:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1327,26 +1313,28 @@ out_unlock:
*/
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
{
+ struct zfcp_qdio *qdio = erp_action->adapter->qdio;
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
- struct zfcp_adapter *adapter = erp_action->adapter;
int retval = -EIO;
- if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
+ if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
+ qdio->adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1361,32 +1349,32 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
/**
* zfcp_fsf_exchange_port_data_sync - request information about local port
- * @adapter: pointer to struct zfcp_adapter
+ * @qdio: pointer to struct zfcp_qdio
* @data: pointer to struct fsf_qtcb_bottom_port
* Returns: 0 on success, error otherwise
*/
-int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
+int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
struct fsf_qtcb_bottom_port *data)
{
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
- if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
+ if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out_unlock;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
- NULL);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out_unlock;
@@ -1395,24 +1383,24 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
if (data)
req->data = data;
- sbale = zfcp_qdio_sbale_req(req);
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
req->handler = zfcp_fsf_exchange_port_data_handler;
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
if (!retval)
- wait_event(req->completion_wq,
- req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&req->completion);
+
zfcp_fsf_req_free(req);
return retval;
out_unlock:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1498,25 +1486,25 @@ out:
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
{
struct qdio_buffer_element *sbale;
- struct zfcp_adapter *adapter = erp_action->adapter;
- struct zfcp_fsf_req *req;
+ struct zfcp_qdio *qdio = erp_action->adapter->qdio;
struct zfcp_port *port = erp_action->port;
+ struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter,
- FSF_QTCB_OPEN_PORT_WITH_DID,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
+ qdio->adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1535,7 +1523,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
zfcp_port_put(port);
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1569,23 +1557,24 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
{
struct qdio_buffer_element *sbale;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_qdio *qdio = erp_action->adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
+ qdio->adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1602,7 +1591,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1645,24 +1634,24 @@ out:
int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
{
struct qdio_buffer_element *sbale;
- struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_qdio *qdio = wka_port->adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter,
- FSF_QTCB_OPEN_PORT_WITH_DID,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
+ qdio->adapter->pool.erp_req);
+
if (unlikely(IS_ERR(req))) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1675,7 +1664,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
if (retval)
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1700,23 +1689,24 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
{
struct qdio_buffer_element *sbale;
- struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_qdio *qdio = wka_port->adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
+ qdio->adapter->pool.erp_req);
+
if (unlikely(IS_ERR(req))) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1729,7 +1719,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
if (retval)
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1791,23 +1781,24 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
{
struct qdio_buffer_element *sbale;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_qdio *qdio = erp_action->adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
+ qdio->adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1824,7 +1815,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -1895,7 +1886,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (header->fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_test_link(unit->port);
+ zfcp_fc_test_link(unit->port);
/* fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1964,22 +1955,24 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
{
struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_qdio *qdio = adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
+ adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -2000,7 +1993,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -2028,7 +2021,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (req->qtcb->header.fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_test_link(unit->port);
+ zfcp_fc_test_link(unit->port);
/* fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -2049,22 +2042,24 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
{
struct qdio_buffer_element *sbale;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_qdio *qdio = erp_action->adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_erp);
+
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
+ qdio->adapter->pool.erp_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
- sbale = zfcp_qdio_sbale_req(req);
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -2082,7 +2077,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return retval;
}
@@ -2141,8 +2136,8 @@ static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
}
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
trace.flags |= ZFCP_BLK_REQ_ERROR;
- trace.inb_usage = fsf_req->qdio_inb_usage;
- trace.outb_usage = fsf_req->qdio_outb_usage;
+ trace.inb_usage = fsf_req->queue_req.qdio_inb_usage;
+ trace.outb_usage = fsf_req->queue_req.qdio_outb_usage;
blk_add_driver_data(req->q, req, &trace, sizeof(trace));
}
@@ -2215,11 +2210,11 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
}
skip_fsfstatus:
if (scpnt->result != 0)
- zfcp_scsi_dbf_event_result("erro", 3, req->adapter, scpnt, req);
+ zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
else if (scpnt->retries > 0)
- zfcp_scsi_dbf_event_result("retr", 4, req->adapter, scpnt, req);
+ zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req);
else
- zfcp_scsi_dbf_event_result("norm", 6, req->adapter, scpnt, req);
+ zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req);
scpnt->host_scribble = NULL;
(scpnt->scsi_done) (scpnt);
@@ -2309,7 +2304,7 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
if (header->fsf_status_qual.word[0] ==
FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
- zfcp_test_link(unit->port);
+ zfcp_fc_test_link(unit->port);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
@@ -2350,24 +2345,27 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
int real_bytes, retval = -EIO;
struct zfcp_adapter *adapter = unit->port->adapter;
+ struct zfcp_qdio *qdio = adapter->qdio;
if (unlikely(!(atomic_read(&unit->status) &
ZFCP_STATUS_COMMON_UNBLOCKED)))
return -EBUSY;
- spin_lock(&adapter->req_q_lock);
- if (atomic_read(&adapter->req_q.count) <= 0) {
- atomic_inc(&adapter->qdio_outb_full);
+ spin_lock(&qdio->req_q_lock);
+ if (atomic_read(&qdio->req_q.count) <= 0) {
+ atomic_inc(&qdio->req_q_full);
goto out;
}
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND,
- ZFCP_REQ_AUTO_CLEANUP,
- adapter->pool.fsf_req_scsi);
+
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
+ adapter->pool.scsi_req);
+
if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
+ req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
zfcp_unit_get(unit);
req->unit = unit;
req->data = scsi_cmnd;
@@ -2419,11 +2417,11 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
- real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype,
+ real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
scsi_sglist(scsi_cmnd),
FSF_MAX_SBALS_PER_REQ);
if (unlikely(real_bytes < 0)) {
- if (req->sbal_number >= FSF_MAX_SBALS_PER_REQ) {
+ if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
dev_err(&adapter->ccw_device->dev,
"Oversize data package, unit 0x%016Lx "
"on port 0x%016Lx closed\n",
@@ -2448,7 +2446,7 @@ failed_scsi_cmnd:
zfcp_fsf_req_free(req);
scsi_cmnd->host_scribble = NULL;
out:
- spin_unlock(&adapter->req_q_lock);
+ spin_unlock(&qdio->req_q_lock);
return retval;
}
@@ -2463,17 +2461,19 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
struct fcp_cmnd_iu *fcp_cmnd_iu;
- struct zfcp_adapter *adapter = unit->port->adapter;
+ struct zfcp_qdio *qdio = unit->port->adapter->qdio;
if (unlikely(!(atomic_read(&unit->status) &
ZFCP_STATUS_COMMON_UNBLOCKED)))
return NULL;
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0,
- adapter->pool.fsf_req_scsi);
+
+ req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
+ qdio->adapter->pool.scsi_req);
+
if (IS_ERR(req)) {
req = NULL;
goto out;
@@ -2489,7 +2489,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
sizeof(u32);
- sbale = zfcp_qdio_sbale_req(req);
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -2504,7 +2504,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
return req;
}
@@ -2522,6 +2522,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_fsf_cfdc *fsf_cfdc)
{
struct qdio_buffer_element *sbale;
+ struct zfcp_qdio *qdio = adapter->qdio;
struct zfcp_fsf_req *req = NULL;
struct fsf_qtcb_bottom_support *bottom;
int direction, retval = -EIO, bytes;
@@ -2540,11 +2541,11 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
return ERR_PTR(-EINVAL);
}
- spin_lock_bh(&adapter->req_q_lock);
- if (zfcp_fsf_req_sbal_get(adapter))
+ spin_lock_bh(&qdio->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(qdio))
goto out;
- req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL);
+ req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
if (IS_ERR(req)) {
retval = -EPERM;
goto out;
@@ -2552,14 +2553,15 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
req->handler = zfcp_fsf_control_file_handler;
- sbale = zfcp_qdio_sbale_req(req);
+ sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
sbale[0].flags |= direction;
bottom = &req->qtcb->bottom.support;
bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
bottom->option = fsf_cfdc->option;
- bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg,
+ bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
+ direction, fsf_cfdc->sg,
FSF_MAX_SBALS_PER_REQ);
if (bytes != ZFCP_CFDC_MAX_SIZE) {
zfcp_fsf_req_free(req);
@@ -2569,12 +2571,53 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock_bh(&adapter->req_q_lock);
+ spin_unlock_bh(&qdio->req_q_lock);
if (!retval) {
- wait_event(req->completion_wq,
- req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&req->completion);
return req;
}
return ERR_PTR(retval);
}
+
+/**
+ * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
+ * @adapter: pointer to struct zfcp_adapter
+ * @sbal_idx: response queue index of SBAL to be processed
+ */
+void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
+{
+ struct zfcp_adapter *adapter = qdio->adapter;
+ struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
+ struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
+ unsigned long flags, req_id;
+ int idx;
+
+ for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
+
+ sbale = &sbal->element[idx];
+ req_id = (unsigned long) sbale->addr;
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
+ fsf_req = zfcp_reqlist_find(adapter, req_id);
+
+ if (!fsf_req)
+ /*
+ * Unknown request means that we have potentially memory
+ * corruption and must stop the machine immediately.
+ */
+ panic("error: unknown req_id (%lx) on adapter %s.\n",
+ req_id, dev_name(&adapter->ccw_device->dev));
+
+ list_del(&fsf_req->list);
+ spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+ fsf_req->queue_req.sbal_response = sbal_idx;
+ fsf_req->queue_req.qdio_inb_usage =
+ atomic_read(&qdio->resp_q.count);
+ zfcp_fsf_req_complete(fsf_req);
+
+ if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
+ break;
+ }
+}
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index df7f232faba..dcc7c1dbcf5 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -3,13 +3,14 @@
*
* Interface to the FSF support functions.
*
- * Copyright IBM Corporation 2002, 2008
+ * Copyright IBM Corporation 2002, 2009
*/
#ifndef FSF_H
#define FSF_H
#include <linux/pfn.h>
+#include <linux/scatterlist.h>
#define FSF_QTCB_CURRENT_VERSION 0x00000001
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index e0a215309df..6c5228b627f 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -3,7 +3,7 @@
*
* Setup and helper functions to access QDIO.
*
- * Copyright IBM Corporation 2002, 2008
+ * Copyright IBM Corporation 2002, 2009
*/
#define KMSG_COMPONENT "zfcp"
@@ -34,29 +34,10 @@ zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
return &q->sbal[sbal_idx]->element[sbale_idx];
}
-/**
- * zfcp_qdio_free - free memory used by request- and resposne queue
- * @adapter: pointer to the zfcp_adapter structure
- */
-void zfcp_qdio_free(struct zfcp_adapter *adapter)
+static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id)
{
- struct qdio_buffer **sbal_req, **sbal_resp;
- int p;
-
- if (adapter->ccw_device)
- qdio_free(adapter->ccw_device);
-
- sbal_req = adapter->req_q.sbal;
- sbal_resp = adapter->resp_q.sbal;
-
- for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
- free_page((unsigned long) sbal_req[p]);
- free_page((unsigned long) sbal_resp[p]);
- }
-}
+ struct zfcp_adapter *adapter = qdio->adapter;
-static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, char *id)
-{
dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
zfcp_erp_adapter_reopen(adapter,
@@ -75,72 +56,47 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
}
/* this needs to be called prior to updating the queue fill level */
-static void zfcp_qdio_account(struct zfcp_adapter *adapter)
+static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
{
- ktime_t now;
- s64 span;
+ unsigned long long now, span;
int free, used;
- spin_lock(&adapter->qdio_stat_lock);
- now = ktime_get();
- span = ktime_us_delta(now, adapter->req_q_time);
- free = max(0, atomic_read(&adapter->req_q.count));
+ spin_lock(&qdio->stat_lock);
+ now = get_clock_monotonic();
+ span = (now - qdio->req_q_time) >> 12;
+ free = atomic_read(&qdio->req_q.count);
used = QDIO_MAX_BUFFERS_PER_Q - free;
- adapter->req_q_util += used * span;
- adapter->req_q_time = now;
- spin_unlock(&adapter->qdio_stat_lock);
+ qdio->req_q_util += used * span;
+ qdio->req_q_time = now;
+ spin_unlock(&qdio->stat_lock);
}
static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
int queue_no, int first, int count,
unsigned long parm)
{
- struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
- struct zfcp_qdio_queue *queue = &adapter->req_q;
+ struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
+ struct zfcp_qdio_queue *queue = &qdio->req_q;
if (unlikely(qdio_err)) {
- zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
- zfcp_qdio_handler_error(adapter, "qdireq1");
+ zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first,
+ count);
+ zfcp_qdio_handler_error(qdio, "qdireq1");
return;
}
/* cleanup all SBALs being program-owned now */
zfcp_qdio_zero_sbals(queue->sbal, first, count);
- zfcp_qdio_account(adapter);
+ zfcp_qdio_account(qdio);
atomic_add(count, &queue->count);
- wake_up(&adapter->request_wq);
-}
-
-static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
- unsigned long req_id, int sbal_idx)
-{
- struct zfcp_fsf_req *fsf_req;
- unsigned long flags;
-
- spin_lock_irqsave(&adapter->req_list_lock, flags);
- fsf_req = zfcp_reqlist_find(adapter, req_id);
-
- if (!fsf_req)
- /*
- * Unknown request means that we have potentially memory
- * corruption and must stop the machine immediatly.
- */
- panic("error: unknown request id (%lx) on adapter %s.\n",
- req_id, dev_name(&adapter->ccw_device->dev));
-
- zfcp_reqlist_remove(adapter, fsf_req);
- spin_unlock_irqrestore(&adapter->req_list_lock, flags);
-
- fsf_req->sbal_response = sbal_idx;
- fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
- zfcp_fsf_req_complete(fsf_req);
+ wake_up(&qdio->req_q_wq);
}
-static void zfcp_qdio_resp_put_back(struct zfcp_adapter *adapter, int processed)
+static void zfcp_qdio_resp_put_back(struct zfcp_qdio *qdio, int processed)
{
- struct zfcp_qdio_queue *queue = &adapter->resp_q;
- struct ccw_device *cdev = adapter->ccw_device;
+ struct zfcp_qdio_queue *queue = &qdio->resp_q;
+ struct ccw_device *cdev = qdio->adapter->ccw_device;
u8 count, start = queue->first;
unsigned int retval;
@@ -162,14 +118,13 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
int queue_no, int first, int count,
unsigned long parm)
{
- struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
- struct zfcp_qdio_queue *queue = &adapter->resp_q;
- struct qdio_buffer_element *sbale;
- int sbal_idx, sbale_idx, sbal_no;
+ struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
+ int sbal_idx, sbal_no;
if (unlikely(qdio_err)) {
- zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
- zfcp_qdio_handler_error(adapter, "qdires1");
+ zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first,
+ count);
+ zfcp_qdio_handler_error(qdio, "qdires1");
return;
}
@@ -179,39 +134,27 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
*/
for (sbal_no = 0; sbal_no < count; sbal_no++) {
sbal_idx = (first + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
-
/* go through all SBALEs of SBAL */
- for (sbale_idx = 0; sbale_idx < QDIO_MAX_ELEMENTS_PER_BUFFER;
- sbale_idx++) {
- sbale = zfcp_qdio_sbale(queue, sbal_idx, sbale_idx);
- zfcp_qdio_reqid_check(adapter,
- (unsigned long) sbale->addr,
- sbal_idx);
- if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
- break;
- };
-
- if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
- dev_warn(&adapter->ccw_device->dev,
- "A QDIO protocol error occurred, "
- "operations continue\n");
+ zfcp_fsf_reqid_check(qdio, sbal_idx);
}
/*
* put range of SBALs back to response queue
* (including SBALs which have already been free before)
*/
- zfcp_qdio_resp_put_back(adapter, count);
+ zfcp_qdio_resp_put_back(qdio, count);
}
/**
* zfcp_qdio_sbale_req - return ptr to SBALE of req_q for a struct zfcp_fsf_req
- * @fsf_req: pointer to struct fsf_req
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_rec: pointer to struct zfcp_queue_rec
* Returns: pointer to qdio_buffer_element (SBALE) structure
*/
-struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_qdio *qdio,
+ struct zfcp_queue_req *q_req)
{
- return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0);
+ return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, 0);
}
/**
@@ -219,74 +162,80 @@ struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
* @fsf_req: pointer to struct fsf_req
* Returns: pointer to qdio_buffer_element (SBALE) structure
*/
-struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio,
+ struct zfcp_queue_req *q_req)
{
- return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last,
- req->sbale_curr);
+ return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last,
+ q_req->sbale_curr);
}
-static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
+static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio,
+ struct zfcp_queue_req *q_req, int max_sbals)
{
- int count = atomic_read(&fsf_req->adapter->req_q.count);
+ int count = atomic_read(&qdio->req_q.count);
count = min(count, max_sbals);
- fsf_req->sbal_limit = (fsf_req->sbal_first + count - 1)
+ q_req->sbal_limit = (q_req->sbal_first + count - 1)
% QDIO_MAX_BUFFERS_PER_Q;
}
static struct qdio_buffer_element *
-zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
+zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
+ unsigned long sbtype)
{
struct qdio_buffer_element *sbale;
/* set last entry flag in current SBALE of current SBAL */
- sbale = zfcp_qdio_sbale_curr(fsf_req);
+ sbale = zfcp_qdio_sbale_curr(qdio, q_req);
sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
/* don't exceed last allowed SBAL */
- if (fsf_req->sbal_last == fsf_req->sbal_limit)
+ if (q_req->sbal_last == q_req->sbal_limit)
return NULL;
/* set chaining flag in first SBALE of current SBAL */
- sbale = zfcp_qdio_sbale_req(fsf_req);
+ sbale = zfcp_qdio_sbale_req(qdio, q_req);
sbale->flags |= SBAL_FLAGS0_MORE_SBALS;
/* calculate index of next SBAL */
- fsf_req->sbal_last++;
- fsf_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
+ q_req->sbal_last++;
+ q_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
/* keep this requests number of SBALs up-to-date */
- fsf_req->sbal_number++;
+ q_req->sbal_number++;
/* start at first SBALE of new SBAL */
- fsf_req->sbale_curr = 0;
+ q_req->sbale_curr = 0;
/* set storage-block type for new SBAL */
- sbale = zfcp_qdio_sbale_curr(fsf_req);
+ sbale = zfcp_qdio_sbale_curr(qdio, q_req);
sbale->flags |= sbtype;
return sbale;
}
static struct qdio_buffer_element *
-zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
+zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
+ unsigned int sbtype)
{
- if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
- return zfcp_qdio_sbal_chain(fsf_req, sbtype);
- fsf_req->sbale_curr++;
- return zfcp_qdio_sbale_curr(fsf_req);
+ if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
+ return zfcp_qdio_sbal_chain(qdio, q_req, sbtype);
+ q_req->sbale_curr++;
+ return zfcp_qdio_sbale_curr(qdio, q_req);
}
-static void zfcp_qdio_undo_sbals(struct zfcp_fsf_req *fsf_req)
+static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
+ struct zfcp_queue_req *q_req)
{
- struct qdio_buffer **sbal = fsf_req->adapter->req_q.sbal;
- int first = fsf_req->sbal_first;
- int last = fsf_req->sbal_last;
+ struct qdio_buffer **sbal = qdio->req_q.sbal;
+ int first = q_req->sbal_first;
+ int last = q_req->sbal_last;
int count = (last - first + QDIO_MAX_BUFFERS_PER_Q) %
QDIO_MAX_BUFFERS_PER_Q + 1;
zfcp_qdio_zero_sbals(sbal, first, count);
}
-static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
+static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
+ struct zfcp_queue_req *q_req,
unsigned int sbtype, void *start_addr,
unsigned int total_length)
{
@@ -297,10 +246,10 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
/* split segment up */
for (addr = start_addr, remaining = total_length; remaining > 0;
addr += length, remaining -= length) {
- sbale = zfcp_qdio_sbale_next(fsf_req, sbtype);
+ sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
if (!sbale) {
- atomic_inc(&fsf_req->adapter->qdio_outb_full);
- zfcp_qdio_undo_sbals(fsf_req);
+ atomic_inc(&qdio->req_q_full);
+ zfcp_qdio_undo_sbals(qdio, q_req);
return -EINVAL;
}
@@ -322,29 +271,31 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
* @max_sbals: upper bound for number of SBALs to be used
* Returns: number of bytes, or error (negativ)
*/
-int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
- struct scatterlist *sg, int max_sbals)
+int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio,
+ struct zfcp_queue_req *q_req,
+ unsigned long sbtype, struct scatterlist *sg,
+ int max_sbals)
{
struct qdio_buffer_element *sbale;
int retval, bytes = 0;
/* figure out last allowed SBAL */
- zfcp_qdio_sbal_limit(fsf_req, max_sbals);
+ zfcp_qdio_sbal_limit(qdio, q_req, max_sbals);
/* set storage-block type for this request */
- sbale = zfcp_qdio_sbale_req(fsf_req);
+ sbale = zfcp_qdio_sbale_req(qdio, q_req);
sbale->flags |= sbtype;
for (; sg; sg = sg_next(sg)) {
- retval = zfcp_qdio_fill_sbals(fsf_req, sbtype, sg_virt(sg),
- sg->length);
+ retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype,
+ sg_virt(sg), sg->length);
if (retval < 0)
return retval;
bytes += sg->length;
}
/* assume that no other SBALEs are to follow in the same SBAL */
- sbale = zfcp_qdio_sbale_curr(fsf_req);
+ sbale = zfcp_qdio_sbale_curr(qdio, q_req);
sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
return bytes;
@@ -352,21 +303,22 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
/**
* zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
- * @fsf_req: pointer to struct zfcp_fsf_req
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: pointer to struct zfcp_queue_req
* Returns: 0 on success, error otherwise
*/
-int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
+int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req)
{
- struct zfcp_adapter *adapter = fsf_req->adapter;
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
- int first = fsf_req->sbal_first;
- int count = fsf_req->sbal_number;
+ struct zfcp_qdio_queue *req_q = &qdio->req_q;
+ int first = q_req->sbal_first;
+ int count = q_req->sbal_number;
int retval;
unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
- zfcp_qdio_account(adapter);
+ zfcp_qdio_account(qdio);
- retval = do_QDIO(adapter->ccw_device, qdio_flags, 0, first, count);
+ retval = do_QDIO(qdio->adapter->ccw_device, qdio_flags, 0, first,
+ count);
if (unlikely(retval)) {
zfcp_qdio_zero_sbals(req_q->sbal, first, count);
return retval;
@@ -379,63 +331,69 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
return 0;
}
+
+static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
+ struct zfcp_qdio *qdio)
+{
+
+ id->cdev = qdio->adapter->ccw_device;
+ id->q_format = QDIO_ZFCP_QFMT;
+ memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
+ ASCEBC(id->adapter_name, 8);
+ id->qib_param_field_format = 0;
+ id->qib_param_field = NULL;
+ id->input_slib_elements = NULL;
+ id->output_slib_elements = NULL;
+ id->no_input_qs = 1;
+ id->no_output_qs = 1;
+ id->input_handler = zfcp_qdio_int_resp;
+ id->output_handler = zfcp_qdio_int_req;
+ id->int_parm = (unsigned long) qdio;
+ id->flags = QDIO_INBOUND_0COPY_SBALS |
+ QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
+ id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal);
+ id->output_sbal_addr_array = (void **) (qdio->req_q.sbal);
+
+}
/**
* zfcp_qdio_allocate - allocate queue memory and initialize QDIO data
* @adapter: pointer to struct zfcp_adapter
* Returns: -ENOMEM on memory allocation error or return value from
* qdio_allocate
*/
-int zfcp_qdio_allocate(struct zfcp_adapter *adapter)
+static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
{
- struct qdio_initialize *init_data;
+ struct qdio_initialize init_data;
- if (zfcp_qdio_buffers_enqueue(adapter->req_q.sbal) ||
- zfcp_qdio_buffers_enqueue(adapter->resp_q.sbal))
+ if (zfcp_qdio_buffers_enqueue(qdio->req_q.sbal) ||
+ zfcp_qdio_buffers_enqueue(qdio->resp_q.sbal))
return -ENOMEM;
- init_data = &adapter->qdio_init_data;
-
- init_data->cdev = adapter->ccw_device;
- init_data->q_format = QDIO_ZFCP_QFMT;
- memcpy(init_data->adapter_name, dev_name(&adapter->ccw_device->dev), 8);
- ASCEBC(init_data->adapter_name, 8);
- init_data->qib_param_field_format = 0;
- init_data->qib_param_field = NULL;
- init_data->input_slib_elements = NULL;
- init_data->output_slib_elements = NULL;
- init_data->no_input_qs = 1;
- init_data->no_output_qs = 1;
- init_data->input_handler = zfcp_qdio_int_resp;
- init_data->output_handler = zfcp_qdio_int_req;
- init_data->int_parm = (unsigned long) adapter;
- init_data->flags = QDIO_INBOUND_0COPY_SBALS |
- QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
- init_data->input_sbal_addr_array =
- (void **) (adapter->resp_q.sbal);
- init_data->output_sbal_addr_array =
- (void **) (adapter->req_q.sbal);
-
- return qdio_allocate(init_data);
+ zfcp_qdio_setup_init_data(&init_data, qdio);
+
+ return qdio_allocate(&init_data);
}
/**
* zfcp_close_qdio - close qdio queues for an adapter
+ * @qdio: pointer to structure zfcp_qdio
*/
-void zfcp_qdio_close(struct zfcp_adapter *adapter)
+void zfcp_qdio_close(struct zfcp_qdio *qdio)
{
struct zfcp_qdio_queue *req_q;
int first, count;
- if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
+ if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return;
/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
- req_q = &adapter->req_q;
- spin_lock_bh(&adapter->req_q_lock);
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
- spin_unlock_bh(&adapter->req_q_lock);
+ req_q = &qdio->req_q;
+ spin_lock_bh(&qdio->req_q_lock);
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
+ spin_unlock_bh(&qdio->req_q_lock);
- qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+ qdio_shutdown(qdio->adapter->ccw_device,
+ QDIO_FLAG_CLEANUP_USING_CLEAR);
/* cleanup used outbound sbals */
count = atomic_read(&req_q->count);
@@ -446,50 +404,99 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
}
req_q->first = 0;
atomic_set(&req_q->count, 0);
- adapter->resp_q.first = 0;
- atomic_set(&adapter->resp_q.count, 0);
+ qdio->resp_q.first = 0;
+ atomic_set(&qdio->resp_q.count, 0);
}
/**
* zfcp_qdio_open - prepare and initialize response queue
- * @adapter: pointer to struct zfcp_adapter
+ * @qdio: pointer to struct zfcp_qdio
* Returns: 0 on success, otherwise -EIO
*/
-int zfcp_qdio_open(struct zfcp_adapter *adapter)
+int zfcp_qdio_open(struct zfcp_qdio *qdio)
{
struct qdio_buffer_element *sbale;
+ struct qdio_initialize init_data;
+ struct ccw_device *cdev = qdio->adapter->ccw_device;
int cc;
- if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
+ if (atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
return -EIO;
- if (qdio_establish(&adapter->qdio_init_data))
+ zfcp_qdio_setup_init_data(&init_data, qdio);
+
+ if (qdio_establish(&init_data))
goto failed_establish;
- if (qdio_activate(adapter->ccw_device))
+ if (qdio_activate(cdev))
goto failed_qdio;
for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
- sbale = &(adapter->resp_q.sbal[cc]->element[0]);
+ sbale = &(qdio->resp_q.sbal[cc]->element[0]);
sbale->length = 0;
sbale->flags = SBAL_FLAGS_LAST_ENTRY;
sbale->addr = NULL;
}
- if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0,
+ if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0,
QDIO_MAX_BUFFERS_PER_Q))
goto failed_qdio;
/* set index of first avalable SBALS / number of available SBALS */
- adapter->req_q.first = 0;
- atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
+ qdio->req_q.first = 0;
+ atomic_set(&qdio->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
return 0;
failed_qdio:
- qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+ qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
failed_establish:
- dev_err(&adapter->ccw_device->dev,
+ dev_err(&cdev->dev,
"Setting up the QDIO connection to the FCP adapter failed\n");
return -EIO;
}
+
+void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
+{
+ struct qdio_buffer **sbal_req, **sbal_resp;
+ int p;
+
+ if (!qdio)
+ return;
+
+ if (qdio->adapter->ccw_device)
+ qdio_free(qdio->adapter->ccw_device);
+
+ sbal_req = qdio->req_q.sbal;
+ sbal_resp = qdio->resp_q.sbal;
+
+ for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
+ free_page((unsigned long) sbal_req[p]);
+ free_page((unsigned long) sbal_resp[p]);
+ }
+
+ kfree(qdio);
+}
+
+int zfcp_qdio_setup(struct zfcp_adapter *adapter)
+{
+ struct zfcp_qdio *qdio;
+
+ qdio = kzalloc(sizeof(struct zfcp_qdio), GFP_KERNEL);
+ if (!qdio)
+ return -ENOMEM;
+
+ qdio->adapter = adapter;
+
+ if (zfcp_qdio_allocate(qdio)) {
+ zfcp_qdio_destroy(qdio);
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&qdio->req_q_lock);
+ spin_lock_init(&qdio->stat_lock);
+
+ adapter->qdio = qdio;
+ return 0;
+}
+
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 6925a178468..3ff726afafc 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -9,8 +9,9 @@
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include "zfcp_ext.h"
#include <asm/atomic.h>
+#include "zfcp_ext.h"
+#include "zfcp_dbf.h"
static unsigned int default_depth = 32;
module_param_named(queue_depth, default_depth, uint, 0600);
@@ -52,11 +53,11 @@ static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
{
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
set_host_byte(scpnt, result);
if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
- zfcp_scsi_dbf_event_result("fail", 4,
- (struct zfcp_adapter*) scpnt->device->host->hostdata[0],
- scpnt, NULL);
+ zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL);
/* return directly */
scpnt->scsi_done(scpnt);
}
@@ -92,7 +93,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
scsi_result = fc_remote_port_chkready(rport);
if (unlikely(scsi_result)) {
scpnt->result = scsi_result;
- zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL);
+ zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL);
scpnt->scsi_done(scpnt);
return 0;
}
@@ -180,8 +181,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
spin_unlock(&adapter->req_list_lock);
if (!old_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
- old_reqid);
+ zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL,
+ old_reqid);
return FAILED; /* completion could be in progress */
}
old_req->data = NULL;
@@ -197,16 +198,15 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
zfcp_erp_wait(adapter);
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING)) {
- zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
- old_reqid);
+ zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL,
+ old_reqid);
return SUCCESS;
}
}
if (!abrt_req)
return FAILED;
- wait_event(abrt_req->completion_wq,
- abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&abrt_req->completion);
if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
dbf_tag = "okay";
@@ -216,7 +216,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
dbf_tag = "fail";
retval = FAILED;
}
- zfcp_scsi_dbf_event_abort(dbf_tag, adapter, scpnt, abrt_req, old_reqid);
+ zfcp_dbf_scsi_abort(dbf_tag, adapter->dbf, scpnt, abrt_req, old_reqid);
zfcp_fsf_req_free(abrt_req);
return retval;
}
@@ -225,7 +225,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
{
struct zfcp_unit *unit = scpnt->device->hostdata;
struct zfcp_adapter *adapter = unit->port->adapter;
- struct zfcp_fsf_req *fsf_req;
+ struct zfcp_fsf_req *fsf_req = NULL;
int retval = SUCCESS;
int retry = 3;
@@ -237,25 +237,23 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
zfcp_erp_wait(adapter);
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING)) {
- zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit,
- scpnt);
+ zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
return SUCCESS;
}
}
if (!fsf_req)
return FAILED;
- wait_event(fsf_req->completion_wq,
- fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_for_completion(&fsf_req->completion);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
- zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
+ zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
retval = FAILED;
} else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) {
- zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt);
+ zfcp_dbf_scsi_devreset("nsup", tm_flags, unit, scpnt);
retval = FAILED;
} else
- zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
+ zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
zfcp_fsf_req_free(fsf_req);
return retval;
@@ -430,7 +428,7 @@ static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host)
if (!data)
return NULL;
- ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
+ ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
if (ret) {
kfree(data);
return NULL;
@@ -459,7 +457,7 @@ static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
if (!data)
return;
- ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
+ ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
if (ret)
kfree(data);
else {
@@ -493,21 +491,6 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
}
/**
- * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport
- * @rport: The rport that is about to be deleted.
- */
-static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
-{
- struct zfcp_port *port;
-
- write_lock_irq(&zfcp_data.config_lock);
- port = rport->dd_data;
- if (port)
- port->rport = NULL;
- write_unlock_irq(&zfcp_data.config_lock);
-}
-
-/**
* zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
* @rport: The FC rport where to teminate I/O
*
@@ -518,9 +501,12 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
{
struct zfcp_port *port;
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *)shost->hostdata[0];
write_lock_irq(&zfcp_data.config_lock);
- port = rport->dd_data;
+ port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
if (port)
zfcp_port_get(port);
write_unlock_irq(&zfcp_data.config_lock);
@@ -552,7 +538,6 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
return;
}
- rport->dd_data = port;
rport->maxframe_size = port->maxframe_size;
rport->supported_classes = port->supported_classes;
port->rport = rport;
@@ -573,7 +558,7 @@ void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
zfcp_port_get(port);
port->rport_task = RPORT_ADD;
- if (!queue_work(zfcp_data.work_queue, &port->rport_work))
+ if (!queue_work(port->adapter->work_queue, &port->rport_work))
zfcp_port_put(port);
}
@@ -582,8 +567,11 @@ void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
zfcp_port_get(port);
port->rport_task = RPORT_DEL;
- if (!queue_work(zfcp_data.work_queue, &port->rport_work))
- zfcp_port_put(port);
+ if (port->rport && queue_work(port->adapter->work_queue,
+ &port->rport_work))
+ return;
+
+ zfcp_port_put(port);
}
void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
@@ -662,7 +650,6 @@ struct fc_function_template zfcp_transport_functions = {
.reset_fc_host_stats = zfcp_reset_fc_host_stats,
.set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
.get_host_port_state = zfcp_get_host_port_state,
- .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
.terminate_rport_io = zfcp_scsi_terminate_rport_io,
.show_host_port_state = 1,
.bsg_request = zfcp_execute_fc_job,
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 0fe5cce818c..079a8cf518a 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -88,7 +88,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
unsigned long val; \
int retval = 0; \
\
- down(&zfcp_data.config_sema); \
+ mutex_lock(&zfcp_data.config_mutex); \
if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \
retval = -EBUSY; \
goto out; \
@@ -105,7 +105,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
_reopen_id, NULL); \
zfcp_erp_wait(_adapter); \
out: \
- up(&zfcp_data.config_sema); \
+ mutex_unlock(&zfcp_data.config_mutex); \
return retval ? retval : (ssize_t) count; \
} \
static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
@@ -126,7 +126,7 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE)
return -EBUSY;
- ret = zfcp_scan_ports(adapter);
+ ret = zfcp_fc_scan_ports(adapter);
return ret ? ret : (ssize_t) count;
}
static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
@@ -142,7 +142,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
int retval = 0;
LIST_HEAD(port_remove_lh);
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
retval = -EBUSY;
goto out;
@@ -173,7 +173,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
zfcp_port_put(port);
zfcp_port_dequeue(port);
out:
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
return retval ? retval : (ssize_t) count;
}
static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
@@ -207,7 +207,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
u64 fcp_lun;
int retval = -EINVAL;
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
retval = -EBUSY;
goto out;
@@ -226,7 +226,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
zfcp_erp_wait(unit->port->adapter);
zfcp_unit_put(unit);
out:
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
return retval ? retval : (ssize_t) count;
}
static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -241,7 +241,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
int retval = 0;
LIST_HEAD(unit_remove_lh);
- down(&zfcp_data.config_sema);
+ mutex_lock(&zfcp_data.config_mutex);
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
retval = -EBUSY;
goto out;
@@ -282,7 +282,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
zfcp_unit_put(unit);
zfcp_unit_dequeue(unit);
out:
- up(&zfcp_data.config_sema);
+ mutex_unlock(&zfcp_data.config_mutex);
return retval ? retval : (ssize_t) count;
}
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
@@ -425,7 +425,7 @@ static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
if (!qtcb_port)
return -ENOMEM;
- retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
+ retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
if (!retval)
retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
qtcb_port->cb_util, qtcb_port->a_util);
@@ -451,7 +451,7 @@ static int zfcp_sysfs_adapter_ex_config(struct device *dev,
if (!qtcb_config)
return -ENOMEM;
- retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
+ retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
if (!retval)
*stat_inf = qtcb_config->stat_info;
@@ -492,15 +492,15 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
char *buf)
{
struct Scsi_Host *scsi_host = class_to_shost(dev);
- struct zfcp_adapter *adapter =
- (struct zfcp_adapter *) scsi_host->hostdata[0];
+ struct zfcp_qdio *qdio =
+ ((struct zfcp_adapter *) scsi_host->hostdata[0])->qdio;
u64 util;
- spin_lock_bh(&adapter->qdio_stat_lock);
- util = adapter->req_q_util;
- spin_unlock_bh(&adapter->qdio_stat_lock);
+ spin_lock_bh(&qdio->stat_lock);
+ util = qdio->req_q_util;
+ spin_unlock_bh(&qdio->stat_lock);
- return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full),
+ return sprintf(buf, "%d %llu\n", atomic_read(&qdio->req_q_full),
(unsigned long long)util);
}
static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);