summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c110
-rw-r--r--drivers/s390/block/dasd_3370_erp.c27
-rw-r--r--drivers/s390/block/dasd_3990_erp.c189
-rw-r--r--drivers/s390/block/dasd_9336_erp.c27
-rw-r--r--drivers/s390/block/dasd_9343_erp.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c103
-rw-r--r--drivers/s390/block/dasd_diag.c7
-rw-r--r--drivers/s390/block/dasd_diag.h2
-rw-r--r--drivers/s390/block/dasd_eckd.c338
-rw-r--r--drivers/s390/block/dasd_eckd.h24
-rw-r--r--drivers/s390/block/dasd_eer.c6
-rw-r--r--drivers/s390/block/dasd_erp.c9
-rw-r--r--drivers/s390/block/dasd_fba.c50
-rw-r--r--drivers/s390/block/dasd_fba.h2
-rw-r--r--drivers/s390/block/dasd_genhd.c3
-rw-r--r--drivers/s390/block/dasd_int.h40
-rw-r--r--drivers/s390/block/dasd_ioctl.c13
-rw-r--r--drivers/s390/block/dasd_proc.c1
-rw-r--r--drivers/s390/block/xpram.c6
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/char/con3270.c1
-rw-r--r--drivers/s390/char/ctrlchar.c1
-rw-r--r--drivers/s390/char/fs3270.c1
-rw-r--r--drivers/s390/char/keyboard.c1
-rw-r--r--drivers/s390/char/monreader.c1
-rw-r--r--drivers/s390/char/raw3270.c68
-rw-r--r--drivers/s390/char/sclp_con.c1
-rw-r--r--drivers/s390/char/sclp_cpi.c1
-rw-r--r--drivers/s390/char/sclp_quiesce.c4
-rw-r--r--drivers/s390/char/sclp_rw.c1
-rw-r--r--drivers/s390/char/sclp_tty.c1
-rw-r--r--drivers/s390/char/sclp_vt220.c1
-rw-r--r--drivers/s390/char/tape.h1
-rw-r--r--drivers/s390/char/tape_34xx.c1
-rw-r--r--drivers/s390/char/tape_3590.c1
-rw-r--r--drivers/s390/char/tape_block.c1
-rw-r--r--drivers/s390/char/tape_char.c1
-rw-r--r--drivers/s390/char/tape_core.c1
-rw-r--r--drivers/s390/char/tape_proc.c1
-rw-r--r--drivers/s390/char/tape_std.c1
-rw-r--r--drivers/s390/char/tty3270.c4
-rw-r--r--drivers/s390/cio/blacklist.c36
-rw-r--r--drivers/s390/cio/ccwgroup.c17
-rw-r--r--drivers/s390/cio/chsc.c7
-rw-r--r--drivers/s390/cio/cio.c1
-rw-r--r--drivers/s390/cio/cmf.c623
-rw-r--r--drivers/s390/cio/css.c63
-rw-r--r--drivers/s390/cio/device.c5
-rw-r--r--drivers/s390/cio/device.h10
-rw-r--r--drivers/s390/cio/device_fsm.c21
-rw-r--r--drivers/s390/cio/device_id.c1
-rw-r--r--drivers/s390/cio/device_ops.c11
-rw-r--r--drivers/s390/cio/device_pgid.c1
-rw-r--r--drivers/s390/cio/device_status.c1
-rw-r--r--drivers/s390/cio/qdio.c1
-rw-r--r--drivers/s390/crypto/z90crypt.h185
-rw-r--r--drivers/s390/crypto/z90main.c1
-rw-r--r--drivers/s390/net/fsm.c1
-rw-r--r--drivers/s390/net/iucv.c1
-rw-r--r--drivers/s390/net/lcs.c7
-rw-r--r--drivers/s390/net/qeth_eddp.c13
-rw-r--r--drivers/s390/net/qeth_main.c5
-rw-r--r--drivers/s390/net/qeth_tso.h2
-rw-r--r--drivers/s390/s390mach.c6
-rw-r--r--drivers/s390/scsi/zfcp_aux.c91
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c14
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c10
-rw-r--r--drivers/s390/scsi/zfcp_def.h68
-rw-r--r--drivers/s390/scsi/zfcp_erp.c289
-rw-r--r--drivers/s390/scsi/zfcp_ext.h19
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c142
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h38
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c19
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c89
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c14
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_driver.c14
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c15
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c15
-rw-r--r--drivers/s390/sysinfo.c1
79 files changed, 1299 insertions, 1612 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index cfb1fff3787c..4bf03fb67f8d 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -9,7 +9,6 @@
*
*/
-#include <linux/config.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -95,7 +94,7 @@ dasd_alloc_device(void)
spin_lock_init(&device->mem_lock);
spin_lock_init(&device->request_queue_lock);
atomic_set (&device->tasklet_scheduled, 0);
- tasklet_init(&device->tasklet,
+ tasklet_init(&device->tasklet,
(void (*)(unsigned long)) dasd_tasklet,
(unsigned long) device);
INIT_LIST_HEAD(&device->ccw_queue);
@@ -128,7 +127,7 @@ dasd_state_new_to_known(struct dasd_device *device)
int rc;
/*
- * As long as the device is not in state DASD_STATE_NEW we want to
+ * As long as the device is not in state DASD_STATE_NEW we want to
* keep the reference count > 0.
*/
dasd_get_device(device);
@@ -336,7 +335,7 @@ dasd_decrease_state(struct dasd_device *device)
if (device->state == DASD_STATE_ONLINE &&
device->target <= DASD_STATE_READY)
dasd_state_online_to_ready(device);
-
+
if (device->state == DASD_STATE_READY &&
device->target <= DASD_STATE_BASIC)
dasd_state_ready_to_basic(device);
@@ -348,7 +347,7 @@ dasd_decrease_state(struct dasd_device *device)
if (device->state == DASD_STATE_BASIC &&
device->target <= DASD_STATE_KNOWN)
dasd_state_basic_to_known(device);
-
+
if (device->state == DASD_STATE_KNOWN &&
device->target <= DASD_STATE_NEW)
dasd_state_known_to_new(device);
@@ -994,7 +993,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr);
/* Find out the appropriate era_action. */
- if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC)
+ if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC)
era = dasd_era_fatal;
else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
irb->scsw.cstat == 0 &&
@@ -1004,7 +1003,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
era = dasd_era_fatal; /* don't recover this request */
else if (irb->esw.esw0.erw.cons)
era = device->discipline->examine_error(cqr, irb);
- else
+ else
era = dasd_era_recover;
DBF_DEV_EVENT(DBF_DEBUG, device, "era_code %d", era);
@@ -1287,7 +1286,7 @@ __dasd_start_head(struct dasd_device * device)
}
/*
- * Remove requests from the ccw queue.
+ * Remove requests from the ccw queue.
*/
static void
dasd_flush_ccw_queue(struct dasd_device * device, int all)
@@ -1450,23 +1449,23 @@ dasd_sleep_on(struct dasd_ccw_req * cqr)
wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
-
+
device = cqr->device;
spin_lock_irq(get_ccwdev_lock(device->cdev));
-
+
init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
cqr->callback_data = (void *) &wait_q;
cqr->status = DASD_CQR_QUEUED;
list_add_tail(&cqr->list, &device->ccw_queue);
-
+
/* let the bh start the request to keep them in order */
dasd_schedule_bh(device);
-
+
spin_unlock_irq(get_ccwdev_lock(device->cdev));
wait_event(wait_q, _wait_for_wakeup(cqr));
-
+
/* Request status is either done or failed. */
rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
return rc;
@@ -1568,7 +1567,7 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr)
wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
-
+
device = cqr->device;
spin_lock_irq(get_ccwdev_lock(device->cdev));
rc = _dasd_term_running_cqr(device);
@@ -1576,20 +1575,20 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr)
spin_unlock_irq(get_ccwdev_lock(device->cdev));
return rc;
}
-
+
init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
cqr->callback_data = (void *) &wait_q;
cqr->status = DASD_CQR_QUEUED;
list_add(&cqr->list, &device->ccw_queue);
-
+
/* let the bh start the request to keep them in order */
dasd_schedule_bh(device);
-
+
spin_unlock_irq(get_ccwdev_lock(device->cdev));
wait_event(wait_q, _wait_for_wakeup(cqr));
-
+
/* Request status is either done or failed. */
rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
return rc;
@@ -1725,7 +1724,7 @@ dasd_flush_request_queue(struct dasd_device * device)
if (!device->request_queue)
return;
-
+
spin_lock_irq(&device->request_queue_lock);
while (!list_empty(&device->request_queue->queue_head)) {
req = elv_next_request(device->request_queue);
@@ -1834,7 +1833,6 @@ dasd_exit(void)
}
dasd_gendisk_exit();
dasd_devmap_exit();
- devfs_remove("dasd");
if (dasd_debug_area != NULL) {
debug_unregister(dasd_debug_area);
dasd_debug_area = NULL;
@@ -1855,15 +1853,34 @@ dasd_generic_probe (struct ccw_device *cdev,
{
int ret;
+ ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
+ if (ret) {
+ printk(KERN_WARNING
+ "dasd_generic_probe: could not set ccw-device options "
+ "for %s\n", cdev->dev.bus_id);
+ return ret;
+ }
ret = dasd_add_sysfs_files(cdev);
if (ret) {
printk(KERN_WARNING
"dasd_generic_probe: could not add sysfs entries "
"for %s\n", cdev->dev.bus_id);
- } else {
- cdev->handler = &dasd_int_handler;
+ return ret;
}
+ cdev->handler = &dasd_int_handler;
+ /*
+ * Automatically online either all dasd devices (dasd_autodetect)
+ * or all devices specified with dasd= parameters during
+ * initial probe.
+ */
+ if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
+ (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0))
+ ret = ccw_device_set_online(cdev);
+ if (ret)
+ printk(KERN_WARNING
+ "dasd_generic_probe: could not initially online "
+ "ccw-device %s\n", cdev->dev.bus_id);
return ret;
}
@@ -1911,6 +1928,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
struct dasd_device *device;
int rc;
+ /* first online clears initial online feature flag */
+ dasd_set_feature(cdev, DASD_FEATURE_INITIAL_ONLINE, 0);
device = dasd_create_device(cdev);
if (IS_ERR(device))
return PTR_ERR(device);
@@ -2065,31 +2084,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
return ret;
}
-/*
- * Automatically online either all dasd devices (dasd_autodetect) or
- * all devices specified with dasd= parameters.
- */
-static int
-__dasd_auto_online(struct device *dev, void *data)
-{
- struct ccw_device *cdev;
-
- cdev = to_ccwdev(dev);
- if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
- ccw_device_set_online(cdev);
- return 0;
-}
-
-void
-dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
-{
- struct device_driver *drv;
-
- drv = get_driver(&dasd_discipline_driver->driver);
- driver_for_each_device(drv, NULL, NULL, __dasd_auto_online);
- put_driver(drv);
-}
-
static int __init
dasd_init(void)
@@ -2111,9 +2105,6 @@ dasd_init(void)
dasd_diag_discipline_pointer = NULL;
- rc = devfs_mk_dir("dasd");
- if (rc)
- goto failed;
rc = dasd_devmap_init();
if (rc)
goto failed;
@@ -2170,23 +2161,4 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove);
EXPORT_SYMBOL_GPL(dasd_generic_notify);
EXPORT_SYMBOL_GPL(dasd_generic_set_online);
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
-EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c
index 1d11c2a9525d..1ddab8991d92 100644
--- a/drivers/s390/block/dasd_3370_erp.c
+++ b/drivers/s390/block/dasd_3370_erp.c
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_3370_erp.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
@@ -12,10 +12,10 @@
/*
- * DASD_3370_ERP_EXAMINE
+ * DASD_3370_ERP_EXAMINE
*
* DESCRIPTION
- * Checks only for fatal/no/recover error.
+ * Checks only for fatal/no/recover error.
* A detailed examination of the sense data is done later outside
* the interrupt handler.
*
@@ -23,7 +23,7 @@
* 'Chapter 7. 3370 Sense Data'.
*
* RETURN VALUES
- * dasd_era_none no error
+ * dasd_era_none no error
* dasd_era_fatal for all fatal (unrecoverable errors)
* dasd_era_recover for all others.
*/
@@ -82,22 +82,3 @@ dasd_3370_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb)
return dasd_era_recover;
} /* END dasd_3370_erp_examine */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 2ed51562319e..669805d4402d 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1,6 +1,6 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_3990_erp.c
- * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com>
+ * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com>
* Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
@@ -25,23 +25,23 @@ struct DCTL_data {
} __attribute__ ((packed));
/*
- *****************************************************************************
+ *****************************************************************************
* SECTION ERP EXAMINATION
- *****************************************************************************
+ *****************************************************************************
*/
/*
- * DASD_3990_ERP_EXAMINE_24
+ * DASD_3990_ERP_EXAMINE_24
*
* DESCRIPTION
- * Checks only for fatal (unrecoverable) error.
+ * Checks only for fatal (unrecoverable) error.
* A detailed examination of the sense data is done later outside
* the interrupt handler.
*
* Each bit configuration leading to an action code 2 (Exit with
* programming error or unusual condition indication)
* are handled as fatal errorīs.
- *
+ *
* All other configurations are handled as recoverable errors.
*
* RETURN VALUES
@@ -93,15 +93,15 @@ dasd_3990_erp_examine_24(struct dasd_ccw_req * cqr, char *sense)
} /* END dasd_3990_erp_examine_24 */
/*
- * DASD_3990_ERP_EXAMINE_32
+ * DASD_3990_ERP_EXAMINE_32
*
* DESCRIPTION
- * Checks only for fatal/no/recoverable error.
+ * Checks only for fatal/no/recoverable error.
* A detailed examination of the sense data is done later outside
* the interrupt handler.
*
* RETURN VALUES
- * dasd_era_none no error
+ * dasd_era_none no error
* dasd_era_fatal for all fatal (unrecoverable errors)
* dasd_era_recover for recoverable others.
*/
@@ -128,10 +128,10 @@ dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense)
} /* end dasd_3990_erp_examine_32 */
/*
- * DASD_3990_ERP_EXAMINE
+ * DASD_3990_ERP_EXAMINE
*
* DESCRIPTION
- * Checks only for fatal/no/recover error.
+ * Checks only for fatal/no/recover error.
* A detailed examination of the sense data is done later outside
* the interrupt handler.
*
@@ -139,7 +139,7 @@ dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense)
* 'Chapter 7. Error Recovery Procedures'.
*
* RETURN VALUES
- * dasd_era_none no error
+ * dasd_era_none no error
* dasd_era_fatal for all fatal (unrecoverable errors)
* dasd_era_recover for all others.
*/
@@ -178,18 +178,18 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb)
} /* END dasd_3990_erp_examine */
/*
- *****************************************************************************
+ *****************************************************************************
* SECTION ERP HANDLING
- *****************************************************************************
+ *****************************************************************************
*/
/*
- *****************************************************************************
+ *****************************************************************************
* 24 and 32 byte sense ERP functions
- *****************************************************************************
+ *****************************************************************************
*/
/*
- * DASD_3990_ERP_CLEANUP
+ * DASD_3990_ERP_CLEANUP
*
* DESCRIPTION
* Removes the already build but not necessary ERP request and sets
@@ -197,10 +197,10 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb)
*
* PARAMETER
* erp request to be blocked
- * final_status either DASD_CQR_DONE or DASD_CQR_FAILED
+ * final_status either DASD_CQR_DONE or DASD_CQR_FAILED
*
* RETURN VALUES
- * cqr original cqr
+ * cqr original cqr
*/
static struct dasd_ccw_req *
dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status)
@@ -214,7 +214,7 @@ dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status)
} /* end dasd_3990_erp_cleanup */
/*
- * DASD_3990_ERP_BLOCK_QUEUE
+ * DASD_3990_ERP_BLOCK_QUEUE
*
* DESCRIPTION
* Block the given device request queue to prevent from further
@@ -237,7 +237,7 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires)
}
/*
- * DASD_3990_ERP_INT_REQ
+ * DASD_3990_ERP_INT_REQ
*
* DESCRIPTION
* Handles 'Intervention Required' error.
@@ -277,7 +277,7 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp)
} /* end dasd_3990_erp_int_req */
/*
- * DASD_3990_ERP_ALTERNATE_PATH
+ * DASD_3990_ERP_ALTERNATE_PATH
*
* DESCRIPTION
* Repeat the operation on a different channel path.
@@ -330,15 +330,15 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
* DASD_3990_ERP_DCTL
*
* DESCRIPTION
- * Setup cqr to do the Diagnostic Control (DCTL) command with an
+ * Setup cqr to do the Diagnostic Control (DCTL) command with an
* Inhibit Write subcommand (0x20) and the given modifier.
*
* PARAMETER
* erp pointer to the current (failed) ERP
* modifier subcommand modifier
- *
+ *
* RETURN VALUES
- * dctl_cqr pointer to NEW dctl_cqr
+ * dctl_cqr pointer to NEW dctl_cqr
*
*/
static struct dasd_ccw_req *
@@ -386,7 +386,7 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
} /* end dasd_3990_erp_DCTL */
/*
- * DASD_3990_ERP_ACTION_1
+ * DASD_3990_ERP_ACTION_1
*
* DESCRIPTION
* Setup ERP to do the ERP action 1 (see Reference manual).
@@ -415,7 +415,7 @@ dasd_3990_erp_action_1(struct dasd_ccw_req * erp)
} /* end dasd_3990_erp_action_1 */
/*
- * DASD_3990_ERP_ACTION_4
+ * DASD_3990_ERP_ACTION_4
*
* DESCRIPTION
* Setup ERP to do the ERP action 4 (see Reference manual).
@@ -453,11 +453,11 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
if (sense[25] == 0x1D) { /* state change pending */
- DEV_MESSAGE(KERN_INFO, device,
+ DEV_MESSAGE(KERN_INFO, device,
"waiting for state change pending "
"interrupt, %d retries left",
erp->retries);
-
+
dasd_3990_erp_block_queue(erp, 30*HZ);
} else if (sense[25] == 0x1E) { /* busy */
@@ -469,9 +469,9 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
} else {
/* no state change pending - retry */
- DEV_MESSAGE (KERN_INFO, device,
+ DEV_MESSAGE (KERN_INFO, device,
"redriving request immediately, "
- "%d retries left",
+ "%d retries left",
erp->retries);
erp->status = DASD_CQR_QUEUED;
}
@@ -482,13 +482,13 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_action_4 */
/*
- *****************************************************************************
+ *****************************************************************************
* 24 byte sense ERP functions (only)
- *****************************************************************************
+ *****************************************************************************
*/
/*
- * DASD_3990_ERP_ACTION_5
+ * DASD_3990_ERP_ACTION_5
*
* DESCRIPTION
* Setup ERP to do the ERP action 5 (see Reference manual).
@@ -523,7 +523,7 @@ dasd_3990_erp_action_5(struct dasd_ccw_req * erp)
*
* PARAMETER
* sense current sense data
- *
+ *
* RETURN VALUES
* void
*/
@@ -1150,9 +1150,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
* PARAMETER
* erp current erp_head
* sense current sense data
- *
+ *
* RETURN VALUES
- * erp 'new' erp_head - pointer to new ERP
+ * erp 'new' erp_head - pointer to new ERP
*/
static struct dasd_ccw_req *
dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
@@ -1185,7 +1185,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_com_rej */
/*
- * DASD_3990_ERP_BUS_OUT
+ * DASD_3990_ERP_BUS_OUT
*
* DESCRIPTION
* Handles 24 byte 'Bus Out Parity Check' error.
@@ -1483,7 +1483,7 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
*
* PARAMETER
* erp already added default ERP
- *
+ *
* RETURN VALUES
* erp new erp_head - pointer to new ERP
*/
@@ -1527,11 +1527,11 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
} /* end dasd_3990_erp_file_prot */
/*
- * DASD_3990_ERP_INSPECT_24
+ * DASD_3990_ERP_INSPECT_24
*
* DESCRIPTION
* Does a detailed inspection of the 24 byte sense data
- * and sets up a related error recovery action.
+ * and sets up a related error recovery action.
*
* PARAMETER
* sense sense data of the actual error
@@ -1602,13 +1602,13 @@ dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense)
} /* END dasd_3990_erp_inspect_24 */
/*
- *****************************************************************************
+ *****************************************************************************
* 32 byte sense ERP functions (only)
- *****************************************************************************
+ *****************************************************************************
*/
/*
- * DASD_3990_ERPACTION_10_32
+ * DASD_3990_ERPACTION_10_32
*
* DESCRIPTION
* Handles 32 byte 'Action 10' of Single Program Action Codes.
@@ -1616,7 +1616,7 @@ dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense)
*
* PARAMETER
* erp current erp_head
- * sense current sense data
+ * sense current sense data
* RETURN VALUES
* erp modified erp_head
*/
@@ -1640,18 +1640,18 @@ dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)
*
* DESCRIPTION
* Handles 32 byte 'Action 1B' of Single Program Action Codes.
- * A write operation could not be finished because of an unexpected
+ * A write operation could not be finished because of an unexpected
* condition.
- * The already created 'default erp' is used to get the link to
- * the erp chain, but it can not be used for this recovery
+ * The already created 'default erp' is used to get the link to
+ * the erp chain, but it can not be used for this recovery
* action because it contains no DE/LO data space.
*
* PARAMETER
* default_erp already added default erp.
- * sense current sense data
+ * sense current sense data
*
* RETURN VALUES
- * erp new erp or
+ * erp new erp or
* default_erp in case of imprecise ending or error
*/
static struct dasd_ccw_req *
@@ -1789,16 +1789,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
* DASD_3990_UPDATE_1B
*
* DESCRIPTION
- * Handles the update to the 32 byte 'Action 1B' of Single Program
+ * Handles the update to the 32 byte 'Action 1B' of Single Program
* Action Codes in case the first action was not successful.
* The already created 'previous_erp' is the currently not successful
- * ERP.
+ * ERP.
*
* PARAMETER
* previous_erp already created previous erp.
- * sense current sense data
+ * sense current sense data
* RETURN VALUES
- * erp modified erp
+ * erp modified erp
*/
static struct dasd_ccw_req *
dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
@@ -1897,7 +1897,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
} /* end dasd_3990_update_1B */
/*
- * DASD_3990_ERP_COMPOUND_RETRY
+ * DASD_3990_ERP_COMPOUND_RETRY
*
* DESCRIPTION
* Handles the compound ERP action retry code.
@@ -1943,7 +1943,7 @@ dasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_compound_retry */
/*
- * DASD_3990_ERP_COMPOUND_PATH
+ * DASD_3990_ERP_COMPOUND_PATH
*
* DESCRIPTION
* Handles the compound ERP action for retry on alternate
@@ -1965,7 +1965,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
dasd_3990_erp_alternate_path(erp);
if (erp->status == DASD_CQR_FAILED) {
- /* reset the lpm and the status to be able to
+ /* reset the lpm and the status to be able to
* try further actions. */
erp->lpm = 0;
@@ -1980,7 +1980,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_compound_path */
/*
- * DASD_3990_ERP_COMPOUND_CODE
+ * DASD_3990_ERP_COMPOUND_CODE
*
* DESCRIPTION
* Handles the compound ERP action for retry code.
@@ -2001,18 +2001,18 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense)
switch (sense[28]) {
case 0x17:
- /* issue a Diagnostic Control command with an
+ /* issue a Diagnostic Control command with an
* Inhibit Write subcommand and controler modifier */
erp = dasd_3990_erp_DCTL(erp, 0x20);
break;
-
+
case 0x25:
/* wait for 5 seconds and retry again */
erp->retries = 1;
-
+
dasd_3990_erp_block_queue (erp, 5*HZ);
break;
-
+
default:
/* should not happen - continue */
break;
@@ -2026,7 +2026,7 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_compound_code */
/*
- * DASD_3990_ERP_COMPOUND_CONFIG
+ * DASD_3990_ERP_COMPOUND_CONFIG
*
* DESCRIPTION
* Handles the compound ERP action for configruation
@@ -2063,10 +2063,10 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_compound_config */
/*
- * DASD_3990_ERP_COMPOUND
+ * DASD_3990_ERP_COMPOUND
*
* DESCRIPTION
- * Does the further compound program action if
+ * Does the further compound program action if
* compound retry was not successful.
*
* PARAMETER
@@ -2110,11 +2110,11 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_compound */
/*
- * DASD_3990_ERP_INSPECT_32
+ * DASD_3990_ERP_INSPECT_32
*
* DESCRIPTION
* Does a detailed inspection of the 32 byte sense data
- * and sets up a related error recovery action.
+ * and sets up a related error recovery action.
*
* PARAMETER
* sense sense data of the actual error
@@ -2228,9 +2228,9 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
} /* end dasd_3990_erp_inspect_32 */
/*
- *****************************************************************************
+ *****************************************************************************
* main ERP control fuctions (24 and 32 byte sense)
- *****************************************************************************
+ *****************************************************************************
*/
/*
@@ -2243,7 +2243,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
* PARAMETER
* erp pointer to the currently created default ERP
* RETURN VALUES
- * erp_new contens was possibly modified
+ * erp_new contens was possibly modified
*/
static struct dasd_ccw_req *
dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
@@ -2272,14 +2272,14 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
/*
* DASD_3990_ERP_ADD_ERP
- *
+ *
* DESCRIPTION
* This funtion adds an additional request block (ERP) to the head of
* the given cqr (or erp).
* This erp is initialized as an default erp (retry TIC)
*
* PARAMETER
- * cqr head of the current ERP-chain (or single cqr if
+ * cqr head of the current ERP-chain (or single cqr if
* first error)
* RETURN VALUES
* erp pointer to new ERP-chain head
@@ -2332,15 +2332,15 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
}
/*
- * DASD_3990_ERP_ADDITIONAL_ERP
- *
+ * DASD_3990_ERP_ADDITIONAL_ERP
+ *
* DESCRIPTION
* An additional ERP is needed to handle the current error.
* Add ERP to the head of the ERP-chain containing the ERP processing
* determined based on the sense data.
*
* PARAMETER
- * cqr head of the current ERP-chain (or single cqr if
+ * cqr head of the current ERP-chain (or single cqr if
* first error)
*
* RETURN VALUES
@@ -2376,7 +2376,7 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr)
* 24 byte sense byte 25 and 27 is set as well.
*
* PARAMETER
- * cqr1 first cqr, which will be compared with the
+ * cqr1 first cqr, which will be compared with the
* cqr2 second cqr.
*
* RETURN VALUES
@@ -2415,7 +2415,7 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
* cqr failed cqr (either original cqr or already an erp)
*
* RETURN VALUES
- * erp erp-pointer to the already defined error
+ * erp erp-pointer to the already defined error
* recovery procedure OR
* NULL if a 'new' error occurred.
*/
@@ -2451,10 +2451,10 @@ dasd_3990_erp_in_erp(struct dasd_ccw_req *cqr)
* DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense)
*
* DESCRIPTION
- * No retry is left for the current ERP. Check what has to be done
+ * No retry is left for the current ERP. Check what has to be done
* with the ERP.
* - do further defined ERP action or
- * - wait for interrupt or
+ * - wait for interrupt or
* - exit with permanent error
*
* PARAMETER
@@ -2485,7 +2485,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
if (!(sense[2] & DASD_SENSE_BIT_0)) {
- /* issue a Diagnostic Control command with an
+ /* issue a Diagnostic Control command with an
* Inhibit Write subcommand */
switch (sense[25]) {
@@ -2535,14 +2535,14 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
} /* end dasd_3990_erp_further_erp */
/*
- * DASD_3990_ERP_HANDLE_MATCH_ERP
+ * DASD_3990_ERP_HANDLE_MATCH_ERP
*
* DESCRIPTION
* An error occurred again and an ERP has been detected which is already
- * used to handle this error (e.g. retries).
+ * used to handle this error (e.g. retries).
* All prior ERP's are asumed to be successful and therefore removed
* from queue.
- * If retry counter of matching erp is already 0, it is checked if further
+ * If retry counter of matching erp is already 0, it is checked if further
* action is needed (besides retry) or if the ERP has failed.
*
* PARAMETER
@@ -2631,7 +2631,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
* erp erp-pointer to the head of the ERP action chain.
* This means:
* - either a ptr to an additional ERP cqr or
- * - the original given cqr (which's status might
+ * - the original given cqr (which's status might
* be modified)
*/
struct dasd_ccw_req *
@@ -2723,22 +2723,3 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
return erp;
} /* end dasd_3990_erp_action */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c
index dc861446d056..6e082688475a 100644
--- a/drivers/s390/block/dasd_9336_erp.c
+++ b/drivers/s390/block/dasd_9336_erp.c
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_9336_erp.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
@@ -12,10 +12,10 @@
/*
- * DASD_9336_ERP_EXAMINE
+ * DASD_9336_ERP_EXAMINE
*
* DESCRIPTION
- * Checks only for fatal/no/recover error.
+ * Checks only for fatal/no/recover error.
* A detailed examination of the sense data is done later outside
* the interrupt handler.
*
@@ -23,7 +23,7 @@
* 'Chapter 7. 9336 Sense Data'.
*
* RETURN VALUES
- * dasd_era_none no error
+ * dasd_era_none no error
* dasd_era_fatal for all fatal (unrecoverable errors)
* dasd_era_recover for all others.
*/
@@ -39,22 +39,3 @@ dasd_9336_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb)
return dasd_era_recover;
} /* END dasd_9336_erp_examine */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c
index 4a5b79569aaa..ddecb9808ed4 100644
--- a/drivers/s390/block/dasd_9343_erp.c
+++ b/drivers/s390/block/dasd_9343_erp.c
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_9345_erp.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 216bc4fba199..d7295386821c 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -13,7 +13,6 @@
*
*/
-#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -27,7 +26,7 @@
#include "dasd_int.h"
kmem_cache_t *dasd_page_cache;
-EXPORT_SYMBOL(dasd_page_cache);
+EXPORT_SYMBOL_GPL(dasd_page_cache);
/*
* dasd_devmap_t is used to store the features and the relation
@@ -49,6 +48,20 @@ struct dasd_devmap {
};
/*
+ * dasd_servermap is used to store the server_id of all storage servers
+ * accessed by DASD device driver.
+ */
+struct dasd_servermap {
+ struct list_head list;
+ struct server_id {
+ char vendor[4];
+ char serial[15];
+ } sid;
+};
+
+static struct list_head dasd_serverlist;
+
+/*
* Parameter parsing functions for dasd= parameter. The syntax is:
* <devno> : (0x)?[0-9a-fA-F]+
* <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
@@ -64,6 +77,8 @@ struct dasd_devmap {
int dasd_probeonly = 0; /* is true, when probeonly mode is active */
int dasd_autodetect = 0; /* is true, when autodetection is active */
+int dasd_nopav = 0; /* is true, when PAV is disabled */
+EXPORT_SYMBOL_GPL(dasd_nopav);
/*
* char *dasd[] is intended to hold the ranges supplied by the dasd= statement
@@ -123,7 +138,7 @@ static inline int
dasd_busid(char **str, int *id0, int *id1, int *devno)
{
int val, old_style;
-
+
/* check for leading '0x' */
old_style = 0;
if ((*str)[0] == '0' && (*str)[1] == 'x') {
@@ -179,7 +194,7 @@ dasd_feature_list(char *str, char **endp)
features = 0;
while (1) {
- for (len = 0;
+ for (len = 0;
str[len] && str[len] != ':' && str[len] != ')'; len++);
if (len == 2 && !strncmp(str, "ro", 2))
features |= DASD_FEATURE_READONLY;
@@ -228,19 +243,24 @@ dasd_parse_keyword( char *parsestring ) {
length = strlen(parsestring);
residual_str = parsestring + length;
}
- if (strncmp ("autodetect", parsestring, length) == 0) {
+ if (strncmp("autodetect", parsestring, length) == 0) {
dasd_autodetect = 1;
MESSAGE (KERN_INFO, "%s",
"turning to autodetection mode");
return residual_str;
}
- if (strncmp ("probeonly", parsestring, length) == 0) {
+ if (strncmp("probeonly", parsestring, length) == 0) {
dasd_probeonly = 1;
MESSAGE(KERN_INFO, "%s",
"turning to probeonly mode");
return residual_str;
}
- if (strncmp ("fixedbuffers", parsestring, length) == 0) {
+ if (strncmp("nopav", parsestring, length) == 0) {
+ dasd_nopav = 1;
+ MESSAGE(KERN_INFO, "%s", "disable PAV mode");
+ return residual_str;
+ }
+ if (strncmp("fixedbuffers", parsestring, length) == 0) {
if (dasd_page_cache)
return residual_str;
dasd_page_cache =
@@ -294,6 +314,8 @@ dasd_parse_range( char *parsestring ) {
features = dasd_feature_list(str, &str);
if (features < 0)
return ERR_PTR(-EINVAL);
+ /* each device in dasd= parameter should be set initially online */
+ features |= DASD_FEATURE_INITIAL_ONLINE;
while (from <= to) {
sprintf(bus_id, "%01x.%01x.%04x",
from_id0, from_id1, from++);
@@ -359,7 +381,7 @@ dasd_parse(void)
* Add a devmap for the device specified by busid. It is possible that
* the devmap already exists (dasd= parameter). The order of the devices
* added through this function will define the kdevs for the individual
- * devices.
+ * devices.
*/
static struct dasd_devmap *
dasd_add_busid(char *bus_id, int features)
@@ -368,7 +390,7 @@ dasd_add_busid(char *bus_id, int features)
int hash;
new = (struct dasd_devmap *)
- kmalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
+ kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
if (!new)
return ERR_PTR(-ENOMEM);
spin_lock(&dasd_devmap_lock);
@@ -630,7 +652,8 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static ssize_t
-dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+dasd_ro_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct dasd_devmap *devmap;
int ro_flag;
@@ -658,7 +681,7 @@ static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
* use_diag controls whether the driver should use diag rather than ssch
* to talk to the device
*/
-static ssize_t
+static ssize_t
dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_devmap *devmap;
@@ -673,7 +696,8 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static ssize_t
-dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct dasd_devmap *devmap;
ssize_t rc;
@@ -697,11 +721,11 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const cha
return rc;
}
-static
-DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
+static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
static ssize_t
-dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf)
+dasd_discipline_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct dasd_devmap *devmap;
char *dname;
@@ -834,6 +858,38 @@ static struct attribute_group dasd_attr_group = {
.attrs = dasd_attrs,
};
+/*
+ * Check if the related storage server is already contained in the
+ * dasd_serverlist. If server is not contained, create new entry.
+ * Return 0 if server was already in serverlist,
+ * 1 if the server was added successfully
+ * <0 in case of error.
+ */
+static int
+dasd_add_server(struct dasd_uid *uid)
+{
+ struct dasd_servermap *new, *tmp;
+
+ /* check if server is already contained */
+ list_for_each_entry(tmp, &dasd_serverlist, list)
+ // normale cmp?
+ if (strncmp(tmp->sid.vendor, uid->vendor,
+ sizeof(tmp->sid.vendor)) == 0
+ && strncmp(tmp->sid.serial, uid->serial,
+ sizeof(tmp->sid.serial)) == 0)
+ return 0;
+
+ new = (struct dasd_servermap *)
+ kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor));
+ strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial));
+ list_add(&new->list, &dasd_serverlist);
+ return 1;
+}
+
/*
* Return copy of the device unique identifier.
@@ -854,21 +910,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
/*
* Register the given device unique identifier into devmap struct.
+ * Return 0 if server was already in serverlist,
+ * 1 if the server was added successful
+ * <0 in case of error.
*/
int
dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
{
struct dasd_devmap *devmap;
+ int rc;
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
return PTR_ERR(devmap);
spin_lock(&dasd_devmap_lock);
devmap->uid = *uid;
+ rc = dasd_add_server(uid);
spin_unlock(&dasd_devmap_lock);
- return 0;
+ return rc;
}
-EXPORT_SYMBOL(dasd_set_uid);
+EXPORT_SYMBOL_GPL(dasd_set_uid);
/*
* Return value of the specified feature.
@@ -880,7 +941,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
- return (int) PTR_ERR(devmap);
+ return PTR_ERR(devmap);
return ((devmap->features & feature) != 0);
}
@@ -896,7 +957,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
- return (int) PTR_ERR(devmap);
+ return PTR_ERR(devmap);
spin_lock(&dasd_devmap_lock);
if (flag)
@@ -932,8 +993,10 @@ dasd_devmap_init(void)
dasd_max_devindex = 0;
for (i = 0; i < 256; i++)
INIT_LIST_HEAD(&dasd_hashlists[i]);
- return 0;
+ /* Initialize servermap structure. */
+ INIT_LIST_HEAD(&dasd_serverlist);
+ return 0;
}
void
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 3f9d704d2657..23fa0b289173 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_diag.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Based on.......: linux/drivers/s390/block/mdisk.c
@@ -8,7 +8,6 @@
*
*/
-#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -336,7 +335,7 @@ dasd_diag_check_device(struct dasd_device *device)
private = (struct dasd_diag_private *) device->private;
if (private == NULL) {
- private = kmalloc(sizeof(struct dasd_diag_private),GFP_KERNEL);
+ private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL);
if (private == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"memory allocation failed for private data");
@@ -527,7 +526,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
datasize, device);
if (IS_ERR(cqr))
return cqr;
-
+
dreq = (struct dasd_diag_req *) cqr->data;
dreq->block_count = count;
dbio = dreq->bio;
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index 38a4e55f8953..b8c78267ff3e 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_diag.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Based on.......: linux/drivers/s390/block/mdisk.h
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 7d5a6cee4bd8..2e655f466743 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1,7 +1,7 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_eckd.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Horst Hummel <Horst.Hummel@de.ibm.com>
+ * Horst Hummel <Horst.Hummel@de.ibm.com>
* Carsten Otte <Cotte@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
@@ -9,7 +9,6 @@
*
*/
-#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -24,6 +23,7 @@
#include <asm/io.h>
#include <asm/todclk.h>
#include <asm/uaccess.h>
+#include <asm/cio.h>
#include <asm/ccwdev.h>
#include "dasd_int.h"
@@ -89,17 +89,22 @@ dasd_eckd_probe (struct ccw_device *cdev)
{
int ret;
- ret = dasd_generic_probe (cdev, &dasd_eckd_discipline);
- if (ret)
+ /* set ECKD specific ccw-device options */
+ ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE);
+ if (ret) {
+ printk(KERN_WARNING
+ "dasd_eckd_probe: could not set ccw-device options "
+ "for %s\n", cdev->dev.bus_id);
return ret;
- ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE);
- return 0;
+ }
+ ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
+ return ret;
}
static int
dasd_eckd_set_online(struct ccw_device *cdev)
{
- return dasd_generic_set_online (cdev, &dasd_eckd_discipline);
+ return dasd_generic_set_online(cdev, &dasd_eckd_discipline);
}
static struct ccw_driver dasd_eckd_driver = {
@@ -210,14 +215,14 @@ check_XRC (struct ccw1 *de_ccw,
/* switch on System Time Stamp - needed for XRC Support */
if (private->rdc_data.facilities.XRC_supported) {
-
+
data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */
data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */
-
+
data->ep_sys_time = get_clock ();
-
+
de_ccw->count = sizeof (struct DE_eckd_data);
- de_ccw->flags |= CCW_FLAG_SLI;
+ de_ccw->flags |= CCW_FLAG_SLI;
}
return;
@@ -296,8 +301,8 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
/* check for sequential prestage - enhance cylinder range */
if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
data->attributes.operation == DASD_SEQ_ACCESS) {
-
- if (end.cyl + private->attrib.nr_cyl < geo.cyl)
+
+ if (end.cyl + private->attrib.nr_cyl < geo.cyl)
end.cyl += private->attrib.nr_cyl;
else
end.cyl = (geo.cyl - 1);
@@ -317,7 +322,7 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
struct dasd_eckd_private *private;
int sector;
int dn, d;
-
+
private = (struct dasd_eckd_private *) device->private;
DBF_DEV_EVENT(DBF_INFO, device,
@@ -541,6 +546,86 @@ dasd_eckd_read_conf(struct dasd_device *device)
}
/*
+ * Build CP for Perform Subsystem Function - SSC.
+ */
+struct dasd_ccw_req *
+dasd_eckd_build_psf_ssc(struct dasd_device *device)
+{
+ struct dasd_ccw_req *cqr;
+ struct dasd_psf_ssc_data *psf_ssc_data;
+ struct ccw1 *ccw;
+
+ cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ ,
+ sizeof(struct dasd_psf_ssc_data),
+ device);
+
+ if (IS_ERR(cqr)) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s",
+ "Could not allocate PSF-SSC request");
+ return cqr;
+ }
+ psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data;
+ psf_ssc_data->order = PSF_ORDER_SSC;
+ psf_ssc_data->suborder = 0x08;
+
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = DASD_ECKD_CCW_PSF;
+ ccw->cda = (__u32)(addr_t)psf_ssc_data;
+ ccw->count = 66;
+
+ cqr->device = device;
+ cqr->expires = 10*HZ;
+ cqr->buildclk = get_clock();
+ cqr->status = DASD_CQR_FILLED;
+ return cqr;
+}
+
+/*
+ * Perform Subsystem Function.
+ * It is necessary to trigger CIO for channel revalidation since this
+ * call might change behaviour of DASD devices.
+ */
+static int
+dasd_eckd_psf_ssc(struct dasd_device *device)
+{
+ struct dasd_ccw_req *cqr;
+ int rc;
+
+ cqr = dasd_eckd_build_psf_ssc(device);
+ if (IS_ERR(cqr))
+ return PTR_ERR(cqr);
+
+ rc = dasd_sleep_on(cqr);
+ if (!rc)
+ /* trigger CIO to reprobe devices */
+ css_schedule_reprobe();
+ dasd_sfree_request(cqr, cqr->device);
+ return rc;
+}
+
+/*
+ * Valide storage server of current device.
+ */
+static int
+dasd_eckd_validate_server(struct dasd_device *device)
+{
+ int rc;
+
+ /* Currently PAV is the only reason to 'validate' server on LPAR */
+ if (dasd_nopav || MACHINE_IS_VM)
+ return 0;
+
+ rc = dasd_eckd_psf_ssc(device);
+ if (rc)
+ /* may be requested feature is not available on server,
+ * therefore just report error and go ahead */
+ DEV_MESSAGE(KERN_INFO, device,
+ "Perform Subsystem Function returned rc=%d", rc);
+ /* RE-Read Configuration Data */
+ return dasd_eckd_read_conf(device);
+}
+
+/*
* Check device characteristics.
* If the device is accessible using ECKD discipline, the device is enabled.
*/
@@ -554,7 +639,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
private = (struct dasd_eckd_private *) device->private;
if (private == NULL) {
- private = kmalloc(sizeof(struct dasd_eckd_private),
+ private = kzalloc(sizeof(struct dasd_eckd_private),
GFP_KERNEL | GFP_DMA);
if (private == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
@@ -562,7 +647,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
"data");
return -ENOMEM;
}
- memset(private, 0, sizeof(struct dasd_eckd_private));
device->private = (void *) private;
}
/* Invalidate status of initial analysis. */
@@ -571,16 +655,29 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
private->attrib.operation = DASD_NORMAL_CACHE;
private->attrib.nr_cyl = 0;
+ /* Read Configuration Data */
+ rc = dasd_eckd_read_conf(device);
+ if (rc)
+ return rc;
+
+ /* Generate device unique id and register in devmap */
+ rc = dasd_eckd_generate_uid(device, &uid);
+ if (rc)
+ return rc;
+ rc = dasd_set_uid(device->cdev, &uid);
+ if (rc == 1) /* new server found */
+ rc = dasd_eckd_validate_server(device);
+ if (rc)
+ return rc;
+
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
memset(rdc_data, 0, sizeof(rdc_data));
rc = read_dev_chars(device->cdev, &rdc_data, 64);
- if (rc) {
+ if (rc)
DEV_MESSAGE(KERN_WARNING, device,
- "Read device characteristics returned error %d",
- rc);
- return rc;
- }
+ "Read device characteristics returned "
+ "rc=%d", rc);
DEV_MESSAGE(KERN_INFO, device,
"%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
@@ -591,19 +688,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
private->rdc_data.no_cyl,
private->rdc_data.trk_per_cyl,
private->rdc_data.sec_per_trk);
-
- /* Read Configuration Data */
- rc = dasd_eckd_read_conf (device);
- if (rc)
- return rc;
-
- /* Generate device unique id and register in devmap */
- rc = dasd_eckd_generate_uid(device, &uid);
- if (rc)
- return rc;
-
- rc = dasd_set_uid(device->cdev, &uid);
-
return rc;
}
@@ -773,7 +857,7 @@ dasd_eckd_end_analysis(struct dasd_device *device)
((private->rdc_data.no_cyl *
private->rdc_data.trk_per_cyl *
blk_per_trk * (device->bp_block >> 9)) >> 1),
- ((blk_per_trk * device->bp_block) >> 10),
+ ((blk_per_trk * device->bp_block) >> 10),
private->uses_cdl ?
"compatible disk layout" : "linux disk layout");
@@ -970,7 +1054,7 @@ dasd_eckd_format_device(struct dasd_device * device,
if (i < 3) {
ect->kl = 4;
ect->dl = sizes_trk0[i] - 4;
- }
+ }
}
if ((fdata->intensity & 0x08) &&
fdata->start_unit == 1) {
@@ -1270,7 +1354,7 @@ dasd_eckd_fill_info(struct dasd_device * device,
/*
* Release device ioctl.
- * Buils a channel programm to releases a prior reserved
+ * Buils a channel programm to releases a prior reserved
* (see dasd_eckd_reserve) device.
*/
static int
@@ -1310,8 +1394,8 @@ dasd_eckd_release(struct dasd_device *device)
/*
* Reserve device ioctl.
* Options are set to 'synchronous wait for interrupt' and
- * 'timeout the request'. This leads to a terminate IO if
- * the interrupt is outstanding for a certain time.
+ * 'timeout the request'. This leads to a terminate IO if
+ * the interrupt is outstanding for a certain time.
*/
static int
dasd_eckd_reserve(struct dasd_device *device)
@@ -1349,7 +1433,7 @@ dasd_eckd_reserve(struct dasd_device *device)
/*
* Steal lock ioctl - unconditional reserve device.
- * Buils a channel programm to break a device's reservation.
+ * Buils a channel programm to break a device's reservation.
* (unconditional reserve)
*/
static int
@@ -1522,6 +1606,40 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp)
}
/*
+ * Dump the range of CCWs into 'page' buffer
+ * and return number of printed chars.
+ */
+static inline int
+dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
+{
+ int len, count;
+ char *datap;
+
+ len = 0;
+ while (from <= to) {
+ len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+ " CCW %p: %08X %08X DAT:",
+ from, ((int *) from)[0], ((int *) from)[1]);
+
+ /* get pointer to data (consider IDALs) */
+ if (from->flags & CCW_FLAG_IDA)
+ datap = (char *) *((addr_t *) (addr_t) from->cda);
+ else
+ datap = (char *) ((addr_t) from->cda);
+
+ /* dump data (max 32 bytes) */
+ for (count = 0; count < from->count && count < 32; count++) {
+ if (count % 8 == 0) len += sprintf(page + len, " ");
+ if (count % 4 == 0) len += sprintf(page + len, " ");
+ len += sprintf(page + len, "%02x", datap[count]);
+ }
+ len += sprintf(page + len, "\n");
+ from++;
+ }
+ return len;
+}
+
+/*
* Print sense data and related channel program.
* Parts are printed because printk buffer is only 1024 bytes.
*/
@@ -1530,8 +1648,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
struct irb *irb)
{
char *page;
- struct ccw1 *act, *end, *last;
- int len, sl, sct, count;
+ struct ccw1 *first, *last, *fail, *from, *to;
+ int len, sl, sct;
page = (char *) get_zeroed_page(GFP_ATOMIC);
if (page == NULL) {
@@ -1539,7 +1657,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
"No memory to dump sense data");
return;
}
- len = sprintf(page, KERN_ERR PRINTK_HEADER
+ /* dump the sense data */
+ len = sprintf(page, KERN_ERR PRINTK_HEADER
" I/O status report for device %s:\n",
device->cdev->dev.bus_id);
len += sprintf(page + len, KERN_ERR PRINTK_HEADER
@@ -1564,87 +1683,55 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
if (irb->ecw[27] & DASD_SENSE_BIT_0) {
/* 24 Byte Sense Data */
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER
- " 24 Byte: %x MSG %x, "
- "%s MSGb to SYSOP\n",
- irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
- irb->ecw[1] & 0x10 ? "" : "no");
+ sprintf(page + len, KERN_ERR PRINTK_HEADER
+ " 24 Byte: %x MSG %x, "
+ "%s MSGb to SYSOP\n",
+ irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
+ irb->ecw[1] & 0x10 ? "" : "no");
} else {
/* 32 Byte Sense Data */
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER
- " 32 Byte: Format: %x "
- "Exception class %x\n",
- irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
+ sprintf(page + len, KERN_ERR PRINTK_HEADER
+ " 32 Byte: Format: %x "
+ "Exception class %x\n",
+ irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
}
} else {
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER
- " SORRY - NO VALID SENSE AVAILABLE\n");
+ sprintf(page + len, KERN_ERR PRINTK_HEADER
+ " SORRY - NO VALID SENSE AVAILABLE\n");
}
- MESSAGE_LOG(KERN_ERR, "%s",
- page + sizeof(KERN_ERR PRINTK_HEADER));
-
- /* dump the Channel Program */
- /* print first CCWs (maximum 8) */
- act = req->cpaddr;
- for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
- end = min(act + 8, last);
- len = sprintf(page, KERN_ERR PRINTK_HEADER
+ printk("%s", page);
+
+ /* dump the Channel Program (max 140 Bytes per line) */
+ /* Count CCW and print first CCWs (maximum 1024 % 140 = 7) */
+ first = req->cpaddr;
+ for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
+ to = min(first + 6, last);
+ len = sprintf(page, KERN_ERR PRINTK_HEADER
" Related CP in req: %p\n", req);
- while (act <= end) {
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER
- " CCW %p: %08X %08X DAT:",
- act, ((int *) act)[0], ((int *) act)[1]);
- for (count = 0; count < 32 && count < act->count;
- count += sizeof(int))
- len += sprintf(page + len, " %08X",
- ((int *) (addr_t) act->cda)
- [(count>>2)]);
- len += sprintf(page + len, "\n");
- act++;
- }
- MESSAGE_LOG(KERN_ERR, "%s",
- page + sizeof(KERN_ERR PRINTK_HEADER));
+ dasd_eckd_dump_ccw_range(first, to, page + len);
+ printk("%s", page);
- /* print failing CCW area */
+ /* print failing CCW area (maximum 4) */
+ /* scsw->cda is either valid or zero */
len = 0;
- if (act < ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) {
- act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2;
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
- }
- end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last);
- while (act <= end) {
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER
- " CCW %p: %08X %08X DAT:",
- act, ((int *) act)[0], ((int *) act)[1]);
- for (count = 0; count < 32 && count < act->count;
- count += sizeof(int))
- len += sprintf(page + len, " %08X",
- ((int *) (addr_t) act->cda)
- [(count>>2)]);
- len += sprintf(page + len, "\n");
- act++;
+ from = ++to;
+ fail = (struct ccw1 *)(addr_t) irb->scsw.cpa; /* failing CCW */
+ if (from < fail - 2) {
+ from = fail - 2; /* there is a gap - print header */
+ len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n");
}
+ to = min(fail + 1, last);
+ len += dasd_eckd_dump_ccw_range(from, to, page + len);
- /* print last CCWs */
- if (act < last - 2) {
- act = last - 2;
+ /* print last CCWs (maximum 2) */
+ from = max(from, ++to);
+ if (from < last - 1) {
+ from = last - 1; /* there is a gap - print header */
len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
}
- while (act <= last) {
- len += sprintf(page + len, KERN_ERR PRINTK_HEADER
- " CCW %p: %08X %08X DAT:",
- act, ((int *) act)[0], ((int *) act)[1]);
- for (count = 0; count < 32 && count < act->count;
- count += sizeof(int))
- len += sprintf(page + len, " %08X",
- ((int *) (addr_t) act->cda)
- [(count>>2)]);
- len += sprintf(page + len, "\n");
- act++;
- }
+ len += dasd_eckd_dump_ccw_range(from, last, page + len);
if (len > 0)
- MESSAGE_LOG(KERN_ERR, "%s",
- page + sizeof(KERN_ERR PRINTK_HEADER));
+ printk("%s", page);
free_page((unsigned long) page);
}
@@ -1685,14 +1772,8 @@ static struct dasd_discipline dasd_eckd_discipline = {
static int __init
dasd_eckd_init(void)
{
- int ret;
-
ASCEBC(dasd_eckd_discipline.ebcname, 4);
-
- ret = ccw_driver_register(&dasd_eckd_driver);
- if (!ret)
- dasd_generic_auto_online(&dasd_eckd_driver);
- return ret;
+ return ccw_driver_register(&dasd_eckd_driver);
}
static void __exit
@@ -1703,22 +1784,3 @@ dasd_eckd_cleanup(void)
module_init(dasd_eckd_init);
module_exit(dasd_eckd_cleanup);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index d5734e976e1c..712ff1650134 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -1,7 +1,7 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_eckd.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Horst Hummel <Horst.Hummel@de.ibm.com>
+ * Horst Hummel <Horst.Hummel@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
@@ -41,9 +41,10 @@
#define DASD_ECKD_CCW_RESERVE 0xB4
/*
- *Perform Subsystem Function / Sub-Orders
+ * Perform Subsystem Function / Sub-Orders
*/
-#define PSF_ORDER_PRSSD 0x18
+#define PSF_ORDER_PRSSD 0x18
+#define PSF_ORDER_SSC 0x1D
/*****************************************************************************
* SECTION: Type Definitions
@@ -155,7 +156,7 @@ struct dasd_eckd_characteristics {
unsigned char reserved2:4;
unsigned char reserved3:8;
unsigned char defect_wr:1;
- unsigned char XRC_supported:1;
+ unsigned char XRC_supported:1;
unsigned char reserved4:1;
unsigned char striping:1;
unsigned char reserved5:4;
@@ -343,7 +344,7 @@ struct dasd_eckd_path {
};
/*
- * Perform Subsystem Function - Prepare for Read Subsystem Data
+ * Perform Subsystem Function - Prepare for Read Subsystem Data
*/
struct dasd_psf_prssd_data {
unsigned char order;
@@ -353,4 +354,15 @@ struct dasd_psf_prssd_data {
unsigned char varies[9];
} __attribute__ ((packed));
+/*
+ * Perform Subsystem Function - Set Subsystem Characteristics
+ */
+struct dasd_psf_ssc_data {
+ unsigned char order;
+ unsigned char flags;
+ unsigned char cu_type[4];
+ unsigned char suborder;
+ unsigned char reserved[59];
+} __attribute__((packed));
+
#endif /* DASD_ECKD_H */
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 2d946b6ca074..da65f1b032f5 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -89,7 +89,7 @@ struct eerbuffer {
};
static LIST_HEAD(bufferlist);
-static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(bufferlock);
static DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
/*
@@ -276,7 +276,7 @@ struct dasd_eer_header {
__u64 tv_sec;
__u64 tv_usec;
char busid[DASD_EER_BUSID_SIZE];
-};
+} __attribute__ ((packed));
/*
* The following function can be used for those triggers that have
@@ -521,6 +521,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp)
unsigned long flags;
eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL);
+ if (!eerb)
+ return -ENOMEM;
eerb->buffer_page_count = eer_pages;
if (eerb->buffer_page_count < 1 ||
eerb->buffer_page_count > INT_MAX / PAGE_SIZE) {
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index b842377cb0c6..58a65097922b 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -9,7 +9,6 @@
*
*/
-#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/init.h>
@@ -90,7 +89,7 @@ dasd_default_erp_action(struct dasd_ccw_req * cqr)
/* just retry - there is nothing to save ... I got no sense data.... */
if (cqr->retries > 0) {
- DEV_MESSAGE (KERN_DEBUG, device,
+ DEV_MESSAGE (KERN_DEBUG, device,
"default ERP called (%i retries left)",
cqr->retries);
cqr->lpm = LPM_ANYPATH;
@@ -155,7 +154,7 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr)
/*
* Print the hex dump of the memory used by a request. This includes
- * all error recovery ccws that have been chained in from of the
+ * all error recovery ccws that have been chained in from of the
* real request.
*/
static inline void
@@ -227,12 +226,12 @@ dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa)
/*
* Log bytes arround failed CCW but only if we did
* not log the whole CP of the CCW is outside the
- * logged CP.
+ * logged CP.
*/
if (cplength > 40 ||
((addr_t) cpa < (addr_t) lcqr->cpaddr &&
(addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) {
-
+
DEV_MESSAGE(KERN_ERR, device,
"Failed CCW (%p) (area):",
(void *) (long) cpa);
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 91145698f8e9..808434d38526 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_fba.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
@@ -6,7 +6,6 @@
*
*/
-#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <asm/debug.h>
@@ -56,19 +55,13 @@ static struct ccw_driver dasd_fba_driver; /* see below */
static int
dasd_fba_probe(struct ccw_device *cdev)
{
- int ret;
-
- ret = dasd_generic_probe (cdev, &dasd_fba_discipline);
- if (ret)
- return ret;
- ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
- return 0;
+ return dasd_generic_probe(cdev, &dasd_fba_discipline);
}
static int
dasd_fba_set_online(struct ccw_device *cdev)
{
- return dasd_generic_set_online (cdev, &dasd_fba_discipline);
+ return dasd_generic_set_online(cdev, &dasd_fba_discipline);
}
static struct ccw_driver dasd_fba_driver = {
@@ -125,13 +118,13 @@ static int
dasd_fba_check_characteristics(struct dasd_device *device)
{
struct dasd_fba_private *private;
- struct ccw_device *cdev = device->cdev;
+ struct ccw_device *cdev = device->cdev;
void *rdc_data;
int rc;
private = (struct dasd_fba_private *) device->private;
if (private == NULL) {
- private = kmalloc(sizeof(struct dasd_fba_private), GFP_KERNEL);
+ private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL);
if (private == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"memory allocation failed for private "
@@ -204,7 +197,7 @@ dasd_fba_examine_error(struct dasd_ccw_req * cqr, struct irb * irb)
if (irb->scsw.cstat == 0x00 &&
irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
return dasd_era_none;
-
+
cdev = device->cdev;
switch (cdev->id.dev_type) {
case 0x3370:
@@ -539,7 +532,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
* 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
* 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
* up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
- * addition we have one define extent ccw + 16 bytes of data and a
+ * addition we have one define extent ccw + 16 bytes of data and a
* locate record ccw for each block (stupid devices!) + 16 bytes of data.
* That makes:
* (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum.
@@ -569,16 +562,8 @@ static struct dasd_discipline dasd_fba_discipline = {
static int __init
dasd_fba_init(void)
{
- int ret;
-
ASCEBC(dasd_fba_discipline.ebcname, 4);
-
- ret = ccw_driver_register(&dasd_fba_driver);
- if (ret)
- return ret;
-
- dasd_generic_auto_online(&dasd_fba_driver);
- return 0;
+ return ccw_driver_register(&dasd_fba_driver);
}
static void __exit
@@ -589,22 +574,3 @@ dasd_fba_cleanup(void)
module_init(dasd_fba_init);
module_exit(dasd_fba_cleanup);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h
index da1fa91fc01d..14c910baa5fe 100644
--- a/drivers/s390/block/dasd_fba.h
+++ b/drivers/s390/block/dasd_fba.h
@@ -1,4 +1,4 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_fba.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index fce2835e7d19..12c7d296eaa8 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -11,7 +11,6 @@
*
*/
-#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/blkpg.h>
@@ -68,8 +67,6 @@ dasd_gendisk_alloc(struct dasd_device *device)
}
len += sprintf(gdp->disk_name + len, "%c", 'a'+(device->devindex%26));
- sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
-
if (device->features & DASD_FEATURE_READONLY)
set_disk_ro(gdp, 1);
gdp->private_data = device;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d4b13e300a76..3ccf06d28ba1 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -1,7 +1,7 @@
-/*
+/*
* File...........: linux/drivers/s390/block/dasd_int.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Horst Hummel <Horst.Hummel@de.ibm.com>
+ * Horst Hummel <Horst.Hummel@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
@@ -54,7 +54,6 @@
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/interrupt.h>
@@ -186,7 +185,7 @@ struct dasd_ccw_req {
void *callback_data;
};
-/*
+/*
* dasd_ccw_req -> status can be:
*/
#define DASD_CQR_FILLED 0x00 /* request is ready to be processed */
@@ -248,7 +247,7 @@ struct dasd_discipline {
/*
* Error recovery functions. examine_error() returns a value that
* indicates what to do for an error condition. If examine_error()
- * returns 'dasd_era_recover' erp_action() is called to create a
+ * returns 'dasd_era_recover' erp_action() is called to create a
* special error recovery ccw. erp_postaction() is called after
* an error recovery ccw has finished its execution. dump_sense
* is called for every error condition to print the sense data
@@ -302,11 +301,11 @@ struct dasd_device {
spinlock_t request_queue_lock;
struct block_device *bdev;
unsigned int devindex;
- unsigned long blocks; /* size of volume in blocks */
- unsigned int bp_block; /* bytes per block */
- unsigned int s2b_shift; /* log2 (bp_block/512) */
- unsigned long flags; /* per device flags */
- unsigned short features; /* copy of devmap-features (read-only!) */
+ unsigned long blocks; /* size of volume in blocks */
+ unsigned int bp_block; /* bytes per block */
+ unsigned int s2b_shift; /* log2 (bp_block/512) */
+ unsigned long flags; /* per device flags */
+ unsigned short features; /* copy of devmap-features (read-only!) */
/* extended error reporting stuff (eer) */
struct dasd_ccw_req *eer_cqr;
@@ -513,12 +512,12 @@ void dasd_generic_remove (struct ccw_device *cdev);
int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
int dasd_generic_set_offline (struct ccw_device *cdev);
int dasd_generic_notify(struct ccw_device *, int);
-void dasd_generic_auto_online (struct ccw_driver *);
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
extern int dasd_probeonly;
extern int dasd_autodetect;
+extern int dasd_nopav;
int dasd_devmap_init(void);
void dasd_devmap_exit(void);
@@ -606,22 +605,3 @@ static inline int dasd_eer_enabled(struct dasd_device *device)
#endif /* __KERNEL__ */
#endif /* DASD_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index b8c80d28df41..e97f5316ad2d 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -9,7 +9,6 @@
*
* i/o controls for the dasd driver.
*/
-#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/fs.h>
@@ -90,10 +89,10 @@ static int
dasd_ioctl_quiesce(struct dasd_device *device)
{
unsigned long flags;
-
+
if (!capable (CAP_SYS_ADMIN))
return -EACCES;
-
+
DEV_MESSAGE (KERN_DEBUG, device, "%s",
"Quiesce IO on device");
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
@@ -110,13 +109,13 @@ static int
dasd_ioctl_resume(struct dasd_device *device)
{
unsigned long flags;
-
- if (!capable (CAP_SYS_ADMIN))
+
+ if (!capable (CAP_SYS_ADMIN))
return -EACCES;
DEV_MESSAGE (KERN_DEBUG, device, "%s",
"resume IO on device");
-
+
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
device->stopped &= ~DASD_STOPPED_QUIESCE;
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
@@ -287,7 +286,7 @@ dasd_ioctl_information(struct dasd_device *device,
dasd_info->open_count = atomic_read(&device->open_count);
if (!device->bdev)
dasd_info->open_count++;
-
+
/*
* check if device is really formatted
* LDL / CDL was returned by 'fill_info'
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index ad23aede356c..bfa010f6dab2 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -11,7 +11,6 @@
*
*/
-#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 54ecd548c318..4c1e56b9b98d 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -36,7 +36,6 @@
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/sysdev.h>
#include <linux/bio.h>
-#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#define XPRAM_NAME "xpram"
@@ -439,8 +438,6 @@ static int __init xpram_setup_blkdev(void)
if (rc < 0)
goto out;
- devfs_mk_dir("slram");
-
/*
* Assign the other needed values: make request function, sizes and
* hardsect size. All the minor devices feature the same value.
@@ -469,14 +466,12 @@ static int __init xpram_setup_blkdev(void)
disk->private_data = &xpram_devices[i];
disk->queue = xpram_queue;
sprintf(disk->disk_name, "slram%d", i);
- sprintf(disk->devfs_name, "slram/%d", i);
set_capacity(disk, xpram_sizes[i] << 1);
add_disk(disk);
}
return 0;
out_unreg:
- devfs_remove("slram");
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
out:
while (i--)
@@ -495,7 +490,6 @@ static void __exit xpram_exit(void)
put_disk(xpram_disks[i]);
}
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
- devfs_remove("slram");
blk_cleanup_queue(xpram_queue);
sysdev_unregister(&xpram_sys_device);
sysdev_class_unregister(&xpram_sysclass);
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 606f6ad285a0..f25c6d116f6f 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -11,7 +11,6 @@
* Dan Morrison, IBM Corporation (dmorriso@cse.buffalo.edu)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index ef607a1de55a..7566be890688 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -8,7 +8,6 @@
* -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
*/
-#include <linux/config.h>
#include <linux/bootmem.h>
#include <linux/console.h>
#include <linux/init.h>
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index be463242cf0f..0ea6f36a2527 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -7,7 +7,6 @@
*
*/
-#include <linux/config.h>
#include <linux/stddef.h>
#include <asm/errno.h>
#include <linux/sysrq.h>
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index a6415377bc73..6099c14de429 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -8,7 +8,6 @@
* -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
*/
-#include <linux/config.h>
#include <linux/bootmem.h>
#include <linux/console.h>
#include <linux/init.h>
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index d4d2ff0a9da2..547ef906ae2c 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -7,7 +7,6 @@
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sysrq.h>
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index fb7bc9e5eebc..a138b1510093 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -586,7 +586,6 @@ static struct file_operations mon_fops = {
static struct miscdevice mon_dev = {
.name = "monreader",
- .devfs_name = "monreader",
.fops = &mon_fops,
.minor = MISC_DYNAMIC_MINOR,
};
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index eecb2afad5c2..e95b56f810db 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -8,7 +8,6 @@
* -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
*/
-#include <linux/config.h>
#include <linux/bootmem.h>
#include <linux/module.h>
#include <linux/err.h>
@@ -50,6 +49,9 @@ struct raw3270 {
unsigned char *ascebc; /* ascii -> ebcdic table */
struct class_device *clttydev; /* 3270-class tty device ptr */
struct class_device *cltubdev; /* 3270-class tub device ptr */
+
+ struct raw3270_request init_request;
+ unsigned char init_data[256];
};
/* raw3270->flags */
@@ -484,8 +486,6 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */
} __attribute__ ((packed)) aua;
} __attribute__ ((packed));
-static unsigned char raw3270_init_data[256];
-static struct raw3270_request raw3270_init_request;
static struct diag210 raw3270_init_diag210;
static DECLARE_MUTEX(raw3270_init_sem);
@@ -644,17 +644,17 @@ __raw3270_size_device(struct raw3270 *rp)
* required (3270 device switched to 'stand-by') and command
* rejects (old devices that can't do 'read partition').
*/
- memset(&raw3270_init_request, 0, sizeof(raw3270_init_request));
- memset(raw3270_init_data, 0, sizeof(raw3270_init_data));
- /* Store 'read partition' data stream to raw3270_init_data */
- memcpy(raw3270_init_data, wbuf, sizeof(wbuf));
- INIT_LIST_HEAD(&raw3270_init_request.list);
- raw3270_init_request.ccw.cmd_code = TC_WRITESF;
- raw3270_init_request.ccw.flags = CCW_FLAG_SLI;
- raw3270_init_request.ccw.count = sizeof(wbuf);
- raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
-
- rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
+ memset(&rp->init_request, 0, sizeof(rp->init_request));
+ memset(&rp->init_data, 0, 256);
+ /* Store 'read partition' data stream to init_data */
+ memcpy(&rp->init_data, wbuf, sizeof(wbuf));
+ INIT_LIST_HEAD(&rp->init_request.list);
+ rp->init_request.ccw.cmd_code = TC_WRITESF;
+ rp->init_request.ccw.flags = CCW_FLAG_SLI;
+ rp->init_request.ccw.count = sizeof(wbuf);
+ rp->init_request.ccw.cda = (__u32) __pa(&rp->init_data);
+
+ rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
if (rc)
/* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */
return rc;
@@ -679,18 +679,18 @@ __raw3270_size_device(struct raw3270 *rp)
* The device accepted the 'read partition' command. Now
* set up a read ccw and issue it.
*/
- raw3270_init_request.ccw.cmd_code = TC_READMOD;
- raw3270_init_request.ccw.flags = CCW_FLAG_SLI;
- raw3270_init_request.ccw.count = sizeof(raw3270_init_data);
- raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
- rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
+ rp->init_request.ccw.cmd_code = TC_READMOD;
+ rp->init_request.ccw.flags = CCW_FLAG_SLI;
+ rp->init_request.ccw.count = sizeof(rp->init_data);
+ rp->init_request.ccw.cda = (__u32) __pa(rp->init_data);
+ rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
if (rc)
return rc;
/* Got a Query Reply */
- count = sizeof(raw3270_init_data) - raw3270_init_request.rescnt;
- uap = (struct raw3270_ua *) (raw3270_init_data + 1);
+ count = sizeof(rp->init_data) - rp->init_request.rescnt;
+ uap = (struct raw3270_ua *) (rp->init_data + 1);
/* Paranoia check. */
- if (raw3270_init_data[0] != 0x88 || uap->uab.qcode != 0x81)
+ if (rp->init_data[0] != 0x88 || uap->uab.qcode != 0x81)
return -EOPNOTSUPP;
/* Copy rows/columns of default Usable Area */
rp->rows = uap->uab.h;
@@ -749,18 +749,18 @@ raw3270_reset_device(struct raw3270 *rp)
int rc;
down(&raw3270_init_sem);
- memset(&raw3270_init_request, 0, sizeof(raw3270_init_request));
- memset(raw3270_init_data, 0, sizeof(raw3270_init_data));
- /* Store reset data stream to raw3270_init_data/raw3270_init_request */
- raw3270_init_data[0] = TW_KR;
- INIT_LIST_HEAD(&raw3270_init_request.list);
- raw3270_init_request.ccw.cmd_code = TC_EWRITEA;
- raw3270_init_request.ccw.flags = CCW_FLAG_SLI;
- raw3270_init_request.ccw.count = 1;
- raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
+ memset(&rp->init_request, 0, sizeof(rp->init_request));
+ memset(&rp->init_data, 0, sizeof(rp->init_data));
+ /* Store reset data stream to init_data/init_request */
+ rp->init_data[0] = TW_KR;
+ INIT_LIST_HEAD(&rp->init_request.list);
+ rp->init_request.ccw.cmd_code = TC_EWRITEA;
+ rp->init_request.ccw.flags = CCW_FLAG_SLI;
+ rp->init_request.ccw.count = 1;
+ rp->init_request.ccw.cda = (__u32) __pa(rp->init_data);
rp->view = &raw3270_init_view;
raw3270_init_view.dev = rp;
- rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
+ rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
raw3270_init_view.dev = 0;
rp->view = 0;
up(&raw3270_init_sem);
@@ -854,7 +854,7 @@ raw3270_setup_console(struct ccw_device *cdev)
char *ascebc;
int rc;
- rp = (struct raw3270 *) alloc_bootmem(sizeof(struct raw3270));
+ rp = (struct raw3270 *) alloc_bootmem_low(sizeof(struct raw3270));
ascebc = (char *) alloc_bootmem(256);
rc = raw3270_setup_device(cdev, rp, ascebc);
if (rc)
@@ -895,7 +895,7 @@ raw3270_create_device(struct ccw_device *cdev)
char *ascebc;
int rc;
- rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL);
+ rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
if (!rp)
return ERR_PTR(-ENOMEM);
ascebc = kmalloc(256, GFP_KERNEL);
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
index 10ef22f13541..86864f641716 100644
--- a/drivers/s390/char/sclp_con.c
+++ b/drivers/s390/char/sclp_con.c
@@ -8,7 +8,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/kmod.h>
#include <linux/console.h>
#include <linux/init.h>
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 80f7f31310e6..732dfbdb85c4 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -5,7 +5,6 @@
* SCLP Control-Program Identification.
*/
-#include <linux/config.h>
#include <linux/version.h>
#include <linux/kmod.h>
#include <linux/module.h>
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 56fa69168898..32004aae95c1 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -7,12 +7,12 @@
* Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/cpumask.h>
#include <linux/smp.h>
#include <linux/init.h>
+#include <linux/reboot.h>
#include <asm/atomic.h>
#include <asm/ptrace.h>
#include <asm/sigp.h>
@@ -66,8 +66,6 @@ do_machine_quiesce(void)
}
#endif
-extern void ctrl_alt_del(void);
-
/* Handler for quiesce event. Start shutdown procedure. */
static void
sclp_quiesce_handler(struct evbuf_header *evbuf)
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 91e93c78f57a..0c92d3909cca 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -8,7 +8,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/kmod.h>
#include <linux/types.h>
#include <linux/err.h>
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 6cbf067f1a8f..f6cf9023039e 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -8,7 +8,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/tty.h>
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 9e02625c82cf..54fba6f17188 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -7,7 +7,6 @@
* Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/list.h>
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index cd51ace8b610..1f4c89967be4 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -16,7 +16,6 @@
#include <asm/ccwdev.h>
#include <asm/debug.h>
#include <asm/idals.h>
-#include <linux/config.h>
#include <linux/blkdev.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index d4f2da738078..48b4d30a7256 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -8,7 +8,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index d71ef1adea59..928cbefc49d5 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -8,7 +8,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index b70d92690242..3225fcd1dcb4 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -11,7 +11,6 @@
*/
#include <linux/fs.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 5ce7ca38ace0..97f75237bed6 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -10,7 +10,6 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index e6e4086d3224..122b4d8965c3 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -11,7 +11,6 @@
* Stefan Bader <shbader@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h> // for kernel parameters
#include <linux/kmod.h> // for requesting modules
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 5fec0a10cc3d..655d375ab22b 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -11,7 +11,6 @@
* PROCFS Functions
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/seq_file.h>
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 99cf881f41db..7a76ec413a3a 100644
--- a/drivers/s390/char/tape_std.c
+++ b/drivers/s390/char/tape_std.c
@@ -11,7 +11,6 @@
* Stefan Bader <shbader@de.ibm.com>
*/
-#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/bio.h>
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 9a141776873f..f496f236b9c0 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -8,7 +8,6 @@
* -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
@@ -1785,7 +1784,6 @@ tty3270_init(void)
* proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
*/
driver->owner = THIS_MODULE;
- driver->devfs_name = "ttyTUB/";
driver->driver_name = "ttyTUB";
driver->name = "ttyTUB";
driver->major = IBM_TTY3270_MAJOR;
@@ -1793,7 +1791,7 @@ tty3270_init(void)
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
- driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
+ driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(driver, &tty3270_ops);
ret = tty_register_driver(driver);
if (ret) {
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 0960bef7b199..12c2d6b746e6 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -9,7 +9,6 @@
* Arnd Bergmann (arndb@de.ibm.com)
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
@@ -224,39 +223,6 @@ is_blacklisted (int ssid, int devno)
}
#ifdef CONFIG_PROC_FS
-static int
-__s390_redo_validation(struct subchannel_id schid, void *data)
-{
- int ret;
- struct subchannel *sch;
-
- sch = get_subchannel_by_schid(schid);
- if (sch) {
- /* Already known. */
- put_device(&sch->dev);
- return 0;
- }
- ret = css_probe_device(schid);
- if (ret == -ENXIO)
- return ret; /* We're through. */
- if (ret == -ENOMEM)
- /* Stop validation for now. Bad, but no need for a panic. */
- return ret;
- return 0;
-}
-
-/*
- * Function: s390_redo_validation
- * Look for no longer blacklisted devices
- * FIXME: there must be a better way to do this */
-static inline void
-s390_redo_validation (void)
-{
- CIO_TRACE_EVENT (0, "redoval");
-
- for_each_subchannel(__s390_redo_validation, NULL);
-}
-
/*
* Function: blacklist_parse_proc_parameters
* parse the stuff which is piped to /proc/cio_ignore
@@ -281,7 +247,7 @@ blacklist_parse_proc_parameters (char *buf)
return;
}
- s390_redo_validation ();
+ css_schedule_reprobe();
}
/* Iterator struct for all devices. */
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index bdfee7fbaa2e..c7319a07ba35 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -404,21 +404,24 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
}
static int
-__ccwgroup_driver_unregister_device(struct device *dev, void *data)
+__ccwgroup_match_all(struct device *dev, void *data)
{
- __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
- device_unregister(dev);
- put_device(dev);
- return 0;
+ return 1;
}
void
ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
{
+ struct device *dev;
+
/* We don't want ccwgroup devices to live longer than their driver. */
get_driver(&cdriver->driver);
- driver_for_each_device(&cdriver->driver, NULL, NULL,
- __ccwgroup_driver_unregister_device);
+ while ((dev = driver_find_device(&cdriver->driver, NULL, NULL,
+ __ccwgroup_match_all))) {
+ __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
+ device_unregister(dev);
+ put_device(dev);
+ }
put_driver(&cdriver->driver);
driver_unregister(&cdriver->driver);
}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 72187e54dcac..a01f3bba4a7b 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -10,7 +10,6 @@
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
@@ -244,8 +243,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
(sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
- (sch->schib.pmcw.lpum == mask) &&
- (sch->vpm == 0)) {
+ (sch->schib.pmcw.lpum == mask)) {
int cc;
cc = cio_clear(sch);
@@ -918,12 +916,13 @@ chp_measurement_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
chp = to_channelpath(container_of(kobj, struct device, kobj));
css = to_css(chp->dev.parent);
- size = sizeof(struct cmg_chars);
+ size = sizeof(struct cmg_entry);
/* Only allow single reads. */
if (off || count < size)
return 0;
chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id);
+ count = size;
return count;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 5b20d8c9c025..a3423267467f 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -11,7 +11,6 @@
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 07ef3f640f4a..1c3e8e9012b0 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -3,9 +3,10 @@
*
* Linux on zSeries Channel Measurement Facility support
*
- * Copyright 2000,2003 IBM Corporation
+ * Copyright 2000,2006 IBM Corporation
*
- * Author: Arnd Bergmann <arndb@de.ibm.com>
+ * Authors: Arnd Bergmann <arndb@de.ibm.com>
+ * Cornelia Huck <cornelia.huck@de.ibm.com>
*
* original idea from Natarajan Krishnaswami <nkrishna@us.ibm.com>
*
@@ -96,9 +97,9 @@ module_param(format, bool, 0444);
/**
* struct cmb_operations - functions to use depending on cmb_format
*
- * all these functions operate on a struct cmf_device. There is only
- * one instance of struct cmb_operations because all cmf_device
- * objects are guaranteed to be of the same type.
+ * Most of these functions operate on a struct ccw_device. There is only
+ * one instance of struct cmb_operations because the format of the measurement
+ * data is guaranteed to be the same for every ccw_device.
*
* @alloc: allocate memory for a channel measurement block,
* either with the help of a special pool or with kmalloc
@@ -107,6 +108,7 @@ module_param(format, bool, 0444);
* @readall: read a measurement block in a common format
* @reset: clear the data in the associated measurement block and
* reset its time stamp
+ * @align: align an allocated block so that the hardware can use it
*/
struct cmb_operations {
int (*alloc) (struct ccw_device*);
@@ -115,11 +117,19 @@ struct cmb_operations {
u64 (*read) (struct ccw_device*, int);
int (*readall)(struct ccw_device*, struct cmbdata *);
void (*reset) (struct ccw_device*);
+ void * (*align) (void *);
struct attribute_group *attr_group;
};
static struct cmb_operations *cmbops;
+struct cmb_data {
+ void *hw_block; /* Pointer to block updated by hardware */
+ void *last_block; /* Last changed block copied from hardware block */
+ int size; /* Size of hw_block and last_block */
+ unsigned long long last_update; /* when last_block was updated */
+};
+
/* our user interface is designed in terms of nanoseconds,
* while the hardware measures total times in its own
* unit.*/
@@ -226,63 +236,229 @@ struct set_schib_struct {
unsigned long address;
wait_queue_head_t wait;
int ret;
+ struct kref kref;
};
+static void cmf_set_schib_release(struct kref *kref)
+{
+ struct set_schib_struct *set_data;
+
+ set_data = container_of(kref, struct set_schib_struct, kref);
+ kfree(set_data);
+}
+
+#define CMF_PENDING 1
+
static int set_schib_wait(struct ccw_device *cdev, u32 mme,
int mbfc, unsigned long address)
{
- struct set_schib_struct s = {
- .mme = mme,
- .mbfc = mbfc,
- .address = address,
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s.wait),
- };
+ struct set_schib_struct *set_data;
+ int ret;
spin_lock_irq(cdev->ccwlock);
- s.ret = set_schib(cdev, mme, mbfc, address);
- if (s.ret != -EBUSY) {
- goto out_nowait;
+ if (!cdev->private->cmb) {
+ ret = -ENODEV;
+ goto out;
}
+ set_data = kzalloc(sizeof(struct set_schib_struct), GFP_ATOMIC);
+ if (!set_data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ init_waitqueue_head(&set_data->wait);
+ kref_init(&set_data->kref);
+ set_data->mme = mme;
+ set_data->mbfc = mbfc;
+ set_data->address = address;
+
+ ret = set_schib(cdev, mme, mbfc, address);
+ if (ret != -EBUSY)
+ goto out_put;
if (cdev->private->state != DEV_STATE_ONLINE) {
- s.ret = -EBUSY;
/* if the device is not online, don't even try again */
- goto out_nowait;
+ ret = -EBUSY;
+ goto out_put;
}
+
cdev->private->state = DEV_STATE_CMFCHANGE;
- cdev->private->cmb_wait = &s;
- s.ret = 1;
+ set_data->ret = CMF_PENDING;
+ cdev->private->cmb_wait = set_data;
spin_unlock_irq(cdev->ccwlock);
- if (wait_event_interruptible(s.wait, s.ret != 1)) {
+ if (wait_event_interruptible(set_data->wait,
+ set_data->ret != CMF_PENDING)) {
spin_lock_irq(cdev->ccwlock);
- if (s.ret == 1) {
- s.ret = -ERESTARTSYS;
- cdev->private->cmb_wait = 0;
+ if (set_data->ret == CMF_PENDING) {
+ set_data->ret = -ERESTARTSYS;
if (cdev->private->state == DEV_STATE_CMFCHANGE)
cdev->private->state = DEV_STATE_ONLINE;
}
spin_unlock_irq(cdev->ccwlock);
}
- return s.ret;
-
-out_nowait:
+ spin_lock_irq(cdev->ccwlock);
+ cdev->private->cmb_wait = NULL;
+ ret = set_data->ret;
+out_put:
+ kref_put(&set_data->kref, cmf_set_schib_release);
+out:
spin_unlock_irq(cdev->ccwlock);
- return s.ret;
+ return ret;
}
void retry_set_schib(struct ccw_device *cdev)
{
- struct set_schib_struct *s;
+ struct set_schib_struct *set_data;
+
+ set_data = cdev->private->cmb_wait;
+ if (!set_data) {
+ WARN_ON(1);
+ return;
+ }
+ kref_get(&set_data->kref);
+ set_data->ret = set_schib(cdev, set_data->mme, set_data->mbfc,
+ set_data->address);
+ wake_up(&set_data->wait);
+ kref_put(&set_data->kref, cmf_set_schib_release);
+}
+
+static int cmf_copy_block(struct ccw_device *cdev)
+{
+ struct subchannel *sch;
+ void *reference_buf;
+ void *hw_block;
+ struct cmb_data *cmb_data;
+
+ sch = to_subchannel(cdev->dev.parent);
+
+ if (stsch(sch->schid, &sch->schib))
+ return -ENODEV;
+
+ if (sch->schib.scsw.fctl & SCSW_FCTL_START_FUNC) {
+ /* Don't copy if a start function is in progress. */
+ if ((!sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED) &&
+ (sch->schib.scsw.actl &
+ (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) &&
+ (!sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS))
+ return -EBUSY;
+ }
+ cmb_data = cdev->private->cmb;
+ hw_block = cmbops->align(cmb_data->hw_block);
+ if (!memcmp(cmb_data->last_block, hw_block, cmb_data->size))
+ /* No need to copy. */
+ return 0;
+ reference_buf = kzalloc(cmb_data->size, GFP_ATOMIC);
+ if (!reference_buf)
+ return -ENOMEM;
+ /* Ensure consistency of block copied from hardware. */
+ do {
+ memcpy(cmb_data->last_block, hw_block, cmb_data->size);
+ memcpy(reference_buf, hw_block, cmb_data->size);
+ } while (memcmp(cmb_data->last_block, reference_buf, cmb_data->size));
+ cmb_data->last_update = get_clock();
+ kfree(reference_buf);
+ return 0;
+}
+
+struct copy_block_struct {
+ wait_queue_head_t wait;
+ int ret;
+ struct kref kref;
+};
+
+static void cmf_copy_block_release(struct kref *kref)
+{
+ struct copy_block_struct *copy_block;
+
+ copy_block = container_of(kref, struct copy_block_struct, kref);
+ kfree(copy_block);
+}
+
+static int cmf_cmb_copy_wait(struct ccw_device *cdev)
+{
+ struct copy_block_struct *copy_block;
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ if (!cdev->private->cmb) {
+ ret = -ENODEV;
+ goto out;
+ }
+ copy_block = kzalloc(sizeof(struct copy_block_struct), GFP_ATOMIC);
+ if (!copy_block) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ init_waitqueue_head(&copy_block->wait);
+ kref_init(&copy_block->kref);
+
+ ret = cmf_copy_block(cdev);
+ if (ret != -EBUSY)
+ goto out_put;
+
+ if (cdev->private->state != DEV_STATE_ONLINE) {
+ ret = -EBUSY;
+ goto out_put;
+ }
+
+ cdev->private->state = DEV_STATE_CMFUPDATE;
+ copy_block->ret = CMF_PENDING;
+ cdev->private->cmb_wait = copy_block;
+
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ if (wait_event_interruptible(copy_block->wait,
+ copy_block->ret != CMF_PENDING)) {
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ if (copy_block->ret == CMF_PENDING) {
+ copy_block->ret = -ERESTARTSYS;
+ if (cdev->private->state == DEV_STATE_CMFUPDATE)
+ cdev->private->state = DEV_STATE_ONLINE;
+ }
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ }
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ cdev->private->cmb_wait = NULL;
+ ret = copy_block->ret;
+out_put:
+ kref_put(&copy_block->kref, cmf_copy_block_release);
+out:
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ return ret;
+}
+
+void cmf_retry_copy_block(struct ccw_device *cdev)
+{
+ struct copy_block_struct *copy_block;
- s = cdev->private->cmb_wait;
- cdev->private->cmb_wait = 0;
- if (!s) {
+ copy_block = cdev->private->cmb_wait;
+ if (!copy_block) {
WARN_ON(1);
return;
}
- s->ret = set_schib(cdev, s->mme, s->mbfc, s->address);
- wake_up(&s->wait);
+ kref_get(&copy_block->kref);
+ copy_block->ret = cmf_copy_block(cdev);
+ wake_up(&copy_block->wait);
+ kref_put(&copy_block->kref, cmf_copy_block_release);
+}
+
+static void cmf_generic_reset(struct ccw_device *cdev)
+{
+ struct cmb_data *cmb_data;
+
+ spin_lock_irq(cdev->ccwlock);
+ cmb_data = cdev->private->cmb;
+ if (cmb_data) {
+ memset(cmb_data->last_block, 0, cmb_data->size);
+ /*
+ * Need to reset hw block as well to make the hardware start
+ * from 0 again.
+ */
+ memset(cmbops->align(cmb_data->hw_block), 0, cmb_data->size);
+ cmb_data->last_update = 0;
+ }
+ cdev->private->cmb_start_time = get_clock();
+ spin_unlock_irq(cdev->ccwlock);
}
/**
@@ -343,8 +519,8 @@ struct cmb {
/* insert a single device into the cmb_area list
* called with cmb_area.lock held from alloc_cmb
*/
-static inline int
-alloc_cmb_single (struct ccw_device *cdev)
+static inline int alloc_cmb_single (struct ccw_device *cdev,
+ struct cmb_data *cmb_data)
{
struct cmb *cmb;
struct ccw_device_private *node;
@@ -358,10 +534,12 @@ alloc_cmb_single (struct ccw_device *cdev)
/* find first unused cmb in cmb_area.mem.
* this is a little tricky: cmb_area.list
- * remains sorted by ->cmb pointers */
+ * remains sorted by ->cmb->hw_data pointers */
cmb = cmb_area.mem;
list_for_each_entry(node, &cmb_area.list, cmb_list) {
- if ((struct cmb*)node->cmb > cmb)
+ struct cmb_data *data;
+ data = node->cmb;
+ if ((struct cmb*)data->hw_block > cmb)
break;
cmb++;
}
@@ -372,7 +550,8 @@ alloc_cmb_single (struct ccw_device *cdev)
/* insert new cmb */
list_add_tail(&cdev->private->cmb_list, &node->cmb_list);
- cdev->private->cmb = cmb;
+ cmb_data->hw_block = cmb;
+ cdev->private->cmb = cmb_data;
ret = 0;
out:
spin_unlock_irq(cdev->ccwlock);
@@ -385,7 +564,19 @@ alloc_cmb (struct ccw_device *cdev)
int ret;
struct cmb *mem;
ssize_t size;
+ struct cmb_data *cmb_data;
+
+ /* Allocate private cmb_data. */
+ cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL);
+ if (!cmb_data)
+ return -ENOMEM;
+ cmb_data->last_block = kzalloc(sizeof(struct cmb), GFP_KERNEL);
+ if (!cmb_data->last_block) {
+ kfree(cmb_data);
+ return -ENOMEM;
+ }
+ cmb_data->size = sizeof(struct cmb);
spin_lock(&cmb_area.lock);
if (!cmb_area.mem) {
@@ -414,29 +605,36 @@ alloc_cmb (struct ccw_device *cdev)
}
/* do the actual allocation */
- ret = alloc_cmb_single(cdev);
+ ret = alloc_cmb_single(cdev, cmb_data);
out:
spin_unlock(&cmb_area.lock);
-
+ if (ret) {
+ kfree(cmb_data->last_block);
+ kfree(cmb_data);
+ }
return ret;
}
-static void
-free_cmb(struct ccw_device *cdev)
+static void free_cmb(struct ccw_device *cdev)
{
struct ccw_device_private *priv;
-
- priv = cdev->private;
+ struct cmb_data *cmb_data;
spin_lock(&cmb_area.lock);
spin_lock_irq(cdev->ccwlock);
+ priv = cdev->private;
+
if (list_empty(&priv->cmb_list)) {
/* already freed */
goto out;
}
+ cmb_data = priv->cmb;
priv->cmb = NULL;
+ if (cmb_data)
+ kfree(cmb_data->last_block);
+ kfree(cmb_data);
list_del_init(&priv->cmb_list);
if (list_empty(&cmb_area.list)) {
@@ -451,83 +649,97 @@ out:
spin_unlock(&cmb_area.lock);
}
-static int
-set_cmb(struct ccw_device *cdev, u32 mme)
+static int set_cmb(struct ccw_device *cdev, u32 mme)
{
u16 offset;
+ struct cmb_data *cmb_data;
+ unsigned long flags;
- if (!cdev->private->cmb)
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ if (!cdev->private->cmb) {
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
return -EINVAL;
-
- offset = mme ? (struct cmb *)cdev->private->cmb - cmb_area.mem : 0;
+ }
+ cmb_data = cdev->private->cmb;
+ offset = mme ? (struct cmb *)cmb_data->hw_block - cmb_area.mem : 0;
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
return set_schib_wait(cdev, mme, 0, offset);
}
-static u64
-read_cmb (struct ccw_device *cdev, int index)
+static u64 read_cmb (struct ccw_device *cdev, int index)
{
- /* yes, we have to put it on the stack
- * because the cmb must only be accessed
- * atomically, e.g. with mvc */
- struct cmb cmb;
- unsigned long flags;
+ struct cmb *cmb;
u32 val;
+ int ret;
+ unsigned long flags;
+
+ ret = cmf_cmb_copy_wait(cdev);
+ if (ret < 0)
+ return 0;
spin_lock_irqsave(cdev->ccwlock, flags);
if (!cdev->private->cmb) {
- spin_unlock_irqrestore(cdev->ccwlock, flags);
- return 0;
+ ret = 0;
+ goto out;
}
-
- cmb = *(struct cmb*)cdev->private->cmb;
- spin_unlock_irqrestore(cdev->ccwlock, flags);
+ cmb = ((struct cmb_data *)cdev->private->cmb)->last_block;
switch (index) {
case cmb_ssch_rsch_count:
- return cmb.ssch_rsch_count;
+ ret = cmb->ssch_rsch_count;
+ goto out;
case cmb_sample_count:
- return cmb.sample_count;
+ ret = cmb->sample_count;
+ goto out;
case cmb_device_connect_time:
- val = cmb.device_connect_time;
+ val = cmb->device_connect_time;
break;
case cmb_function_pending_time:
- val = cmb.function_pending_time;
+ val = cmb->function_pending_time;
break;
case cmb_device_disconnect_time:
- val = cmb.device_disconnect_time;
+ val = cmb->device_disconnect_time;
break;
case cmb_control_unit_queuing_time:
- val = cmb.control_unit_queuing_time;
+ val = cmb->control_unit_queuing_time;
break;
case cmb_device_active_only_time:
- val = cmb.device_active_only_time;
+ val = cmb->device_active_only_time;
break;
default:
- return 0;
+ ret = 0;
+ goto out;
}
- return time_to_avg_nsec(val, cmb.sample_count);
+ ret = time_to_avg_nsec(val, cmb->sample_count);
+out:
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ return ret;
}
-static int
-readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
+static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
{
- /* yes, we have to put it on the stack
- * because the cmb must only be accessed
- * atomically, e.g. with mvc */
- struct cmb cmb;
- unsigned long flags;
+ struct cmb *cmb;
+ struct cmb_data *cmb_data;
u64 time;
+ unsigned long flags;
+ int ret;
+ ret = cmf_cmb_copy_wait(cdev);
+ if (ret < 0)
+ return ret;
spin_lock_irqsave(cdev->ccwlock, flags);
- if (!cdev->private->cmb) {
- spin_unlock_irqrestore(cdev->ccwlock, flags);
- return -ENODEV;
+ cmb_data = cdev->private->cmb;
+ if (!cmb_data) {
+ ret = -ENODEV;
+ goto out;
}
-
- cmb = *(struct cmb*)cdev->private->cmb;
- time = get_clock() - cdev->private->cmb_start_time;
- spin_unlock_irqrestore(cdev->ccwlock, flags);
+ if (cmb_data->last_update == 0) {
+ ret = -EAGAIN;
+ goto out;
+ }
+ cmb = cmb_data->last_block;
+ time = cmb_data->last_update - cdev->private->cmb_start_time;
memset(data, 0, sizeof(struct cmbdata));
@@ -538,31 +750,32 @@ readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
data->elapsed_time = (time * 1000) >> 12;
/* copy data to new structure */
- data->ssch_rsch_count = cmb.ssch_rsch_count;
- data->sample_count = cmb.sample_count;
+ data->ssch_rsch_count = cmb->ssch_rsch_count;
+ data->sample_count = cmb->sample_count;
/* time fields are converted to nanoseconds while copying */
- data->device_connect_time = time_to_nsec(cmb.device_connect_time);
- data->function_pending_time = time_to_nsec(cmb.function_pending_time);
- data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+ data->device_connect_time = time_to_nsec(cmb->device_connect_time);
+ data->function_pending_time = time_to_nsec(cmb->function_pending_time);
+ data->device_disconnect_time =
+ time_to_nsec(cmb->device_disconnect_time);
data->control_unit_queuing_time
- = time_to_nsec(cmb.control_unit_queuing_time);
+ = time_to_nsec(cmb->control_unit_queuing_time);
data->device_active_only_time
- = time_to_nsec(cmb.device_active_only_time);
+ = time_to_nsec(cmb->device_active_only_time);
+ ret = 0;
+out:
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ return ret;
+}
- return 0;
+static void reset_cmb(struct ccw_device *cdev)
+{
+ cmf_generic_reset(cdev);
}
-static void
-reset_cmb(struct ccw_device *cdev)
+static void * align_cmb(void *area)
{
- struct cmb *cmb;
- spin_lock_irq(cdev->ccwlock);
- cmb = cdev->private->cmb;
- if (cmb)
- memset (cmb, 0, sizeof (*cmb));
- cdev->private->cmb_start_time = get_clock();
- spin_unlock_irq(cdev->ccwlock);
+ return area;
}
static struct attribute_group cmf_attr_group;
@@ -574,6 +787,7 @@ static struct cmb_operations cmbops_basic = {
.read = read_cmb,
.readall = readall_cmb,
.reset = reset_cmb,
+ .align = align_cmb,
.attr_group = &cmf_attr_group,
};
@@ -610,22 +824,34 @@ static inline struct cmbe* cmbe_align(struct cmbe *c)
return (struct cmbe*)addr;
}
-static int
-alloc_cmbe (struct ccw_device *cdev)
+static int alloc_cmbe (struct ccw_device *cdev)
{
struct cmbe *cmbe;
- cmbe = kmalloc (sizeof (*cmbe) * 2, GFP_KERNEL);
+ struct cmb_data *cmb_data;
+ int ret;
+
+ cmbe = kzalloc (sizeof (*cmbe) * 2, GFP_KERNEL);
if (!cmbe)
return -ENOMEM;
-
+ cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL);
+ if (!cmb_data) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+ cmb_data->last_block = kzalloc(sizeof(struct cmbe), GFP_KERNEL);
+ if (!cmb_data->last_block) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+ cmb_data->size = sizeof(struct cmbe);
spin_lock_irq(cdev->ccwlock);
if (cdev->private->cmb) {
- kfree(cmbe);
spin_unlock_irq(cdev->ccwlock);
- return -EBUSY;
+ ret = -EBUSY;
+ goto out_free;
}
-
- cdev->private->cmb = cmbe;
+ cmb_data->hw_block = cmbe;
+ cdev->private->cmb = cmb_data;
spin_unlock_irq(cdev->ccwlock);
/* activate global measurement if this is the first channel */
@@ -636,14 +862,24 @@ alloc_cmbe (struct ccw_device *cdev)
spin_unlock(&cmb_area.lock);
return 0;
+out_free:
+ if (cmb_data)
+ kfree(cmb_data->last_block);
+ kfree(cmb_data);
+ kfree(cmbe);
+ return ret;
}
-static void
-free_cmbe (struct ccw_device *cdev)
+static void free_cmbe (struct ccw_device *cdev)
{
+ struct cmb_data *cmb_data;
+
spin_lock_irq(cdev->ccwlock);
- kfree(cdev->private->cmb);
+ cmb_data = cdev->private->cmb;
cdev->private->cmb = NULL;
+ if (cmb_data)
+ kfree(cmb_data->last_block);
+ kfree(cmb_data);
spin_unlock_irq(cdev->ccwlock);
/* deactivate global measurement if this is the last channel */
@@ -654,89 +890,105 @@ free_cmbe (struct ccw_device *cdev)
spin_unlock(&cmb_area.lock);
}
-static int
-set_cmbe(struct ccw_device *cdev, u32 mme)
+static int set_cmbe(struct ccw_device *cdev, u32 mme)
{
unsigned long mba;
+ struct cmb_data *cmb_data;
+ unsigned long flags;
- if (!cdev->private->cmb)
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ if (!cdev->private->cmb) {
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
return -EINVAL;
- mba = mme ? (unsigned long) cmbe_align(cdev->private->cmb) : 0;
+ }
+ cmb_data = cdev->private->cmb;
+ mba = mme ? (unsigned long) cmbe_align(cmb_data->hw_block) : 0;
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
return set_schib_wait(cdev, mme, 1, mba);
}
-u64
-read_cmbe (struct ccw_device *cdev, int index)
+static u64 read_cmbe (struct ccw_device *cdev, int index)
{
- /* yes, we have to put it on the stack
- * because the cmb must only be accessed
- * atomically, e.g. with mvc */
- struct cmbe cmb;
- unsigned long flags;
+ struct cmbe *cmb;
+ struct cmb_data *cmb_data;
u32 val;
+ int ret;
+ unsigned long flags;
- spin_lock_irqsave(cdev->ccwlock, flags);
- if (!cdev->private->cmb) {
- spin_unlock_irqrestore(cdev->ccwlock, flags);
+ ret = cmf_cmb_copy_wait(cdev);
+ if (ret < 0)
return 0;
- }
- cmb = *cmbe_align(cdev->private->cmb);
- spin_unlock_irqrestore(cdev->ccwlock, flags);
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ cmb_data = cdev->private->cmb;
+ if (!cmb_data) {
+ ret = 0;
+ goto out;
+ }
+ cmb = cmb_data->last_block;
switch (index) {
case cmb_ssch_rsch_count:
- return cmb.ssch_rsch_count;
+ ret = cmb->ssch_rsch_count;
+ goto out;
case cmb_sample_count:
- return cmb.sample_count;
+ ret = cmb->sample_count;
+ goto out;
case cmb_device_connect_time:
- val = cmb.device_connect_time;
+ val = cmb->device_connect_time;
break;
case cmb_function_pending_time:
- val = cmb.function_pending_time;
+ val = cmb->function_pending_time;
break;
case cmb_device_disconnect_time:
- val = cmb.device_disconnect_time;
+ val = cmb->device_disconnect_time;
break;
case cmb_control_unit_queuing_time:
- val = cmb.control_unit_queuing_time;
+ val = cmb->control_unit_queuing_time;
break;
case cmb_device_active_only_time:
- val = cmb.device_active_only_time;
+ val = cmb->device_active_only_time;
break;
case cmb_device_busy_time:
- val = cmb.device_busy_time;
+ val = cmb->device_busy_time;
break;
case cmb_initial_command_response_time:
- val = cmb.initial_command_response_time;
+ val = cmb->initial_command_response_time;
break;
default:
- return 0;
+ ret = 0;
+ goto out;
}
- return time_to_avg_nsec(val, cmb.sample_count);
+ ret = time_to_avg_nsec(val, cmb->sample_count);
+out:
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ return ret;
}
-static int
-readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
+static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
{
- /* yes, we have to put it on the stack
- * because the cmb must only be accessed
- * atomically, e.g. with mvc */
- struct cmbe cmb;
- unsigned long flags;
+ struct cmbe *cmb;
+ struct cmb_data *cmb_data;
u64 time;
+ unsigned long flags;
+ int ret;
+ ret = cmf_cmb_copy_wait(cdev);
+ if (ret < 0)
+ return ret;
spin_lock_irqsave(cdev->ccwlock, flags);
- if (!cdev->private->cmb) {
- spin_unlock_irqrestore(cdev->ccwlock, flags);
- return -ENODEV;
+ cmb_data = cdev->private->cmb;
+ if (!cmb_data) {
+ ret = -ENODEV;
+ goto out;
}
-
- cmb = *cmbe_align(cdev->private->cmb);
- time = get_clock() - cdev->private->cmb_start_time;
- spin_unlock_irqrestore(cdev->ccwlock, flags);
+ if (cmb_data->last_update == 0) {
+ ret = -EAGAIN;
+ goto out;
+ }
+ time = cmb_data->last_update - cdev->private->cmb_start_time;
memset (data, 0, sizeof(struct cmbdata));
@@ -746,35 +998,38 @@ readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
/* conver to nanoseconds */
data->elapsed_time = (time * 1000) >> 12;
+ cmb = cmb_data->last_block;
/* copy data to new structure */
- data->ssch_rsch_count = cmb.ssch_rsch_count;
- data->sample_count = cmb.sample_count;
+ data->ssch_rsch_count = cmb->ssch_rsch_count;
+ data->sample_count = cmb->sample_count;
/* time fields are converted to nanoseconds while copying */
- data->device_connect_time = time_to_nsec(cmb.device_connect_time);
- data->function_pending_time = time_to_nsec(cmb.function_pending_time);
- data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+ data->device_connect_time = time_to_nsec(cmb->device_connect_time);
+ data->function_pending_time = time_to_nsec(cmb->function_pending_time);
+ data->device_disconnect_time =
+ time_to_nsec(cmb->device_disconnect_time);
data->control_unit_queuing_time
- = time_to_nsec(cmb.control_unit_queuing_time);
+ = time_to_nsec(cmb->control_unit_queuing_time);
data->device_active_only_time
- = time_to_nsec(cmb.device_active_only_time);
- data->device_busy_time = time_to_nsec(cmb.device_busy_time);
+ = time_to_nsec(cmb->device_active_only_time);
+ data->device_busy_time = time_to_nsec(cmb->device_busy_time);
data->initial_command_response_time
- = time_to_nsec(cmb.initial_command_response_time);
+ = time_to_nsec(cmb->initial_command_response_time);
- return 0;
+ ret = 0;
+out:
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ return ret;
}
-static void
-reset_cmbe(struct ccw_device *cdev)
+static void reset_cmbe(struct ccw_device *cdev)
{
- struct cmbe *cmb;
- spin_lock_irq(cdev->ccwlock);
- cmb = cmbe_align(cdev->private->cmb);
- if (cmb)
- memset (cmb, 0, sizeof (*cmb));
- cdev->private->cmb_start_time = get_clock();
- spin_unlock_irq(cdev->ccwlock);
+ cmf_generic_reset(cdev);
+}
+
+static void * align_cmbe(void *area)
+{
+ return cmbe_align(area);
}
static struct attribute_group cmf_attr_group_ext;
@@ -786,6 +1041,7 @@ static struct cmb_operations cmbops_extended = {
.read = read_cmbe,
.readall = readall_cmbe,
.reset = reset_cmbe,
+ .align = align_cmbe,
.attr_group = &cmf_attr_group_ext,
};
@@ -803,14 +1059,19 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr,
struct ccw_device *cdev;
long interval;
unsigned long count;
+ struct cmb_data *cmb_data;
cdev = to_ccwdev(dev);
- interval = get_clock() - cdev->private->cmb_start_time;
count = cmf_read(cdev, cmb_sample_count);
- if (count)
+ spin_lock_irq(cdev->ccwlock);
+ cmb_data = cdev->private->cmb;
+ if (count) {
+ interval = cmb_data->last_update -
+ cdev->private->cmb_start_time;
interval /= count;
- else
+ } else
interval = -1;
+ spin_unlock_irq(cdev->ccwlock);
return sprintf(buf, "%ld\n", interval);
}
@@ -823,7 +1084,10 @@ cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char
int ret;
ret = cmf_readall(to_ccwdev(dev), &data);
- if (ret)
+ if (ret == -EAGAIN || ret == -ENODEV)
+ /* No data (yet/currently) available to use for calculation. */
+ return sprintf(buf, "n/a\n");
+ else if (ret)
return ret;
utilization = data.device_connect_time +
@@ -982,6 +1246,13 @@ cmf_readall(struct ccw_device *cdev, struct cmbdata *data)
return cmbops->readall(cdev, data);
}
+/* Reenable cmf when a disconnected device becomes available again. */
+int cmf_reenable(struct ccw_device *cdev)
+{
+ cmbops->reset(cdev);
+ return cmbops->set(cdev, 2);
+}
+
static int __init
init_cmf(void)
{
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 74ea8aac4b7d..1d3be80797f8 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -19,9 +19,11 @@
#include "cio_debug.h"
#include "ioasm.h"
#include "chsc.h"
+#include "device.h"
int need_rescan = 0;
int css_init_done = 0;
+static int need_reprobe = 0;
static int max_ssid = 0;
struct channel_subsystem *css[__MAX_CSSID + 1];
@@ -339,6 +341,67 @@ typedef void (*workfunc)(void *);
DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL);
struct workqueue_struct *slow_path_wq;
+/* Reprobe subchannel if unregistered. */
+static int reprobe_subchannel(struct subchannel_id schid, void *data)
+{
+ struct subchannel *sch;
+ int ret;
+
+ CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n",
+ schid.ssid, schid.sch_no);
+ if (need_reprobe)
+ return -EAGAIN;
+
+ sch = get_subchannel_by_schid(schid);
+ if (sch) {
+ /* Already known. */
+ put_device(&sch->dev);
+ return 0;
+ }
+
+ ret = css_probe_device(schid);
+ switch (ret) {
+ case 0:
+ break;
+ case -ENXIO:
+ case -ENOMEM:
+ /* These should abort looping */
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Work function used to reprobe all unregistered subchannels. */
+static void reprobe_all(void *data)
+{
+ int ret;
+
+ CIO_MSG_EVENT(2, "reprobe start\n");
+
+ need_reprobe = 0;
+ /* Make sure initial subchannel scan is done. */
+ wait_event(ccw_device_init_wq,
+ atomic_read(&ccw_device_init_count) == 0);
+ ret = for_each_subchannel(reprobe_subchannel, NULL);
+
+ CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
+ need_reprobe);
+}
+
+DECLARE_WORK(css_reprobe_work, reprobe_all, NULL);
+
+/* Schedule reprobing of all unregistered subchannels. */
+void css_schedule_reprobe(void)
+{
+ need_reprobe = 1;
+ queue_work(ccw_device_work, &css_reprobe_work);
+}
+
+EXPORT_SYMBOL_GPL(css_schedule_reprobe);
+
/*
* Rescan for new devices. FIXME: This is slow.
* This function is called when we have lost CRWs due to overflows and we have
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 8e3053c2a451..67f0de6aed33 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -8,7 +8,6 @@
* Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -133,8 +132,8 @@ struct css_driver io_subchannel_driver = {
struct workqueue_struct *ccw_device_work;
struct workqueue_struct *ccw_device_notify_work;
-static wait_queue_head_t ccw_device_init_wq;
-static atomic_t ccw_device_init_count;
+wait_queue_head_t ccw_device_init_wq;
+atomic_t ccw_device_init_count;
static int __init
init_ccw_bus_type (void)
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 11587ebb7289..00be9a5b4acd 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -1,6 +1,10 @@
#ifndef S390_DEVICE_H
#define S390_DEVICE_H
+#include <asm/ccwdev.h>
+#include <asm/atomic.h>
+#include <linux/wait.h>
+
/*
* states of the device statemachine
*/
@@ -23,6 +27,7 @@ enum dev_state {
DEV_STATE_DISCONNECTED,
DEV_STATE_DISCONNECTED_SENSE_ID,
DEV_STATE_CMFCHANGE,
+ DEV_STATE_CMFUPDATE,
/* last element! */
NR_DEV_STATES
};
@@ -67,6 +72,8 @@ dev_fsm_final_state(struct ccw_device *cdev)
extern struct workqueue_struct *ccw_device_work;
extern struct workqueue_struct *ccw_device_notify_work;
+extern wait_queue_head_t ccw_device_init_wq;
+extern atomic_t ccw_device_init_count;
void io_subchannel_recog_done(struct ccw_device *cdev);
@@ -112,5 +119,8 @@ int ccw_device_stlck(struct ccw_device *);
void ccw_device_set_timeout(struct ccw_device *, int);
extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
+/* Channel measurement facility related */
void retry_set_schib(struct ccw_device *cdev);
+void cmf_retry_copy_block(struct ccw_device *);
+int cmf_reenable(struct ccw_device *);
#endif
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 49ec562d7f60..cb1af0b6f033 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -9,7 +9,6 @@
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/string.h>
@@ -336,8 +335,11 @@ ccw_device_oper_notify(void *data)
if (!ret)
/* Driver doesn't want device back. */
ccw_device_do_unreg_rereg((void *)cdev);
- else
+ else {
+ /* Reenable channel measurements, if needed. */
+ cmf_reenable(cdev);
wake_up(&cdev->private->wait_q);
+ }
}
/*
@@ -861,6 +863,8 @@ ccw_device_clear_verify(struct ccw_device *cdev, enum dev_event dev_event)
irb = (struct irb *) __LC_IRB;
/* Accumulate status. We don't do basic sense. */
ccw_device_accumulate_irb(cdev, irb);
+ /* Remember to clear irb to avoid residuals. */
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
/* Try to start delayed device verification. */
ccw_device_online_verify(cdev, 0);
/* Note: Don't call handler for cio initiated clear! */
@@ -1093,6 +1097,13 @@ ccw_device_change_cmfstate(struct ccw_device *cdev, enum dev_event dev_event)
dev_fsm_event(cdev, dev_event);
}
+static void ccw_device_update_cmfblock(struct ccw_device *cdev,
+ enum dev_event dev_event)
+{
+ cmf_retry_copy_block(cdev);
+ cdev->private->state = DEV_STATE_ONLINE;
+ dev_fsm_event(cdev, dev_event);
+}
static void
ccw_device_quiesce_done(struct ccw_device *cdev, enum dev_event dev_event)
@@ -1247,6 +1258,12 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
[DEV_EVENT_TIMEOUT] = ccw_device_change_cmfstate,
[DEV_EVENT_VERIFY] = ccw_device_change_cmfstate,
},
+ [DEV_STATE_CMFUPDATE] = {
+ [DEV_EVENT_NOTOPER] = ccw_device_update_cmfblock,
+ [DEV_EVENT_INTERRUPT] = ccw_device_update_cmfblock,
+ [DEV_EVENT_TIMEOUT] = ccw_device_update_cmfblock,
+ [DEV_EVENT_VERIFY] = ccw_device_update_cmfblock,
+ },
};
/*
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index e60b2d8103b8..438db483035d 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -10,7 +10,6 @@
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <asm/ccwdev.h>
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 795abb5a65ba..a60124264bee 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -6,7 +6,6 @@
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
* Cornelia Huck (cornelia.huck@de.ibm.com)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -78,7 +77,8 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
- if (cdev->private->state == DEV_STATE_VERIFY) {
+ if (cdev->private->state == DEV_STATE_VERIFY ||
+ cdev->private->state == DEV_STATE_CLEAR_VERIFY) {
/* Remember to fake irb when finished. */
if (!cdev->private->flags.fake_irb) {
cdev->private->flags.fake_irb = 1;
@@ -270,7 +270,8 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
* We didn't get channel end / device end. Check if path
* verification has been started; we can retry after it has
* finished. We also retry unit checks except for command reject
- * or intervention required.
+ * or intervention required. Also check for long busy
+ * conditions.
*/
if (cdev->private->flags.doverify ||
cdev->private->state == DEV_STATE_VERIFY)
@@ -279,6 +280,10 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
!(irb->ecw[0] &
(SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ)))
cdev->private->intparm = -EAGAIN;
+ else if ((irb->scsw.dstat & DEV_STAT_ATTENTION) &&
+ (irb->scsw.dstat & DEV_STAT_DEV_END) &&
+ (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP))
+ cdev->private->intparm = -EAGAIN;
else
cdev->private->intparm = -EIO;
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 85b1020a1fcc..54cb64ed0786 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -9,7 +9,6 @@
* Path Group ID functions.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 6c762b43f921..14bef2c179bf 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -9,7 +9,6 @@
* Status accumulation and basic sense functions.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 96f519281d92..b70039af70d6 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -30,7 +30,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 5e6b1f535f62..0ca1d126ccb6 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -1,7 +1,7 @@
/*
* linux/drivers/s390/crypto/z90crypt.h
*
- * z90crypt 1.3.3
+ * z90crypt 1.3.3 (kernel-private header)
*
* Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
@@ -27,188 +27,7 @@
#ifndef _Z90CRYPT_H_
#define _Z90CRYPT_H_
-#include <linux/ioctl.h>
-
-#define z90crypt_VERSION 1
-#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
-#define z90crypt_VARIANT 3 // 3 = CEX2A support
-
-/**
- * struct ica_rsa_modexpo
- *
- * Requirements:
- * - outputdatalength is at least as large as inputdatalength.
- * - All key parts are right justified in their fields, padded on
- * the left with zeroes.
- * - length(b_key) = inputdatalength
- * - length(n_modulus) = inputdatalength
- */
-struct ica_rsa_modexpo {
- char __user * inputdata;
- unsigned int inputdatalength;
- char __user * outputdata;
- unsigned int outputdatalength;
- char __user * b_key;
- char __user * n_modulus;
-};
-
-/**
- * struct ica_rsa_modexpo_crt
- *
- * Requirements:
- * - inputdatalength is even.
- * - outputdatalength is at least as large as inputdatalength.
- * - All key parts are right justified in their fields, padded on
- * the left with zeroes.
- * - length(bp_key) = inputdatalength/2 + 8
- * - length(bq_key) = inputdatalength/2
- * - length(np_key) = inputdatalength/2 + 8
- * - length(nq_key) = inputdatalength/2
- * - length(u_mult_inv) = inputdatalength/2 + 8
- */
-struct ica_rsa_modexpo_crt {
- char __user * inputdata;
- unsigned int inputdatalength;
- char __user * outputdata;
- unsigned int outputdatalength;
- char __user * bp_key;
- char __user * bq_key;
- char __user * np_prime;
- char __user * nq_prime;
- char __user * u_mult_inv;
-};
-
-#define Z90_IOCTL_MAGIC 'z' // NOTE: Need to allocate from linux folks
-
-/**
- * Interface notes:
- *
- * The ioctl()s which are implemented (along with relevant details)
- * are:
- *
- * ICARSAMODEXPO
- * Perform an RSA operation using a Modulus-Exponent pair
- * This takes an ica_rsa_modexpo struct as its arg.
- *
- * NOTE: please refer to the comments preceding this structure
- * for the implementation details for the contents of the
- * block
- *
- * ICARSACRT
- * Perform an RSA operation using a Chinese-Remainder Theorem key
- * This takes an ica_rsa_modexpo_crt struct as its arg.
- *
- * NOTE: please refer to the comments preceding this structure
- * for the implementation details for the contents of the
- * block
- *
- * Z90STAT_TOTALCOUNT
- * Return an integer count of all device types together.
- *
- * Z90STAT_PCICACOUNT
- * Return an integer count of all PCICAs.
- *
- * Z90STAT_PCICCCOUNT
- * Return an integer count of all PCICCs.
- *
- * Z90STAT_PCIXCCMCL2COUNT
- * Return an integer count of all MCL2 PCIXCCs.
- *
- * Z90STAT_PCIXCCMCL3COUNT
- * Return an integer count of all MCL3 PCIXCCs.
- *
- * Z90STAT_CEX2CCOUNT
- * Return an integer count of all CEX2Cs.
- *
- * Z90STAT_CEX2ACOUNT
- * Return an integer count of all CEX2As.
- *
- * Z90STAT_REQUESTQ_COUNT
- * Return an integer count of the number of entries waiting to be
- * sent to a device.
- *
- * Z90STAT_PENDINGQ_COUNT
- * Return an integer count of the number of entries sent to a
- * device awaiting the reply.
- *
- * Z90STAT_TOTALOPEN_COUNT
- * Return an integer count of the number of open file handles.
- *
- * Z90STAT_DOMAIN_INDEX
- * Return the integer value of the Cryptographic Domain.
- *
- * Z90STAT_STATUS_MASK
- * Return an 64 element array of unsigned chars for the status of
- * all devices.
- * 0x01: PCICA
- * 0x02: PCICC
- * 0x03: PCIXCC_MCL2
- * 0x04: PCIXCC_MCL3
- * 0x05: CEX2C
- * 0x06: CEX2A
- * 0x0d: device is disabled via the proc filesystem
- *
- * Z90STAT_QDEPTH_MASK
- * Return an 64 element array of unsigned chars for the queue
- * depth of all devices.
- *
- * Z90STAT_PERDEV_REQCNT
- * Return an 64 element array of unsigned integers for the number
- * of successfully completed requests per device since the device
- * was detected and made available.
- *
- * ICAZ90STATUS (deprecated)
- * Return some device driver status in a ica_z90_status struct
- * This takes an ica_z90_status struct as its arg.
- *
- * NOTE: this ioctl() is deprecated, and has been replaced with
- * single ioctl()s for each type of status being requested
- *
- * Z90STAT_PCIXCCCOUNT (deprecated)
- * Return an integer count of all PCIXCCs (MCL2 + MCL3).
- * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
- * MCL2 PCIXCCs.
- *
- * Z90QUIESCE (not recommended)
- * Quiesce the driver. This is intended to stop all new
- * requests from being processed. Its use is NOT recommended,
- * except in circumstances where there is no other way to stop
- * callers from accessing the driver. Its original use was to
- * allow the driver to be "drained" of work in preparation for
- * a system shutdown.
- *
- * NOTE: once issued, this ban on new work cannot be undone
- * except by unloading and reloading the driver.
- */
-
-/**
- * Supported ioctl calls
- */
-#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
-#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
-
-/* DEPRECATED status calls (bound for removal at some point) */
-#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
-#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int)
-
-/* unrelated to ICA callers */
-#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11)
-
-/* New status calls */
-#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int)
-#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int)
-#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int)
-#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
-#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
-#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
-#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
-#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
-#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
-#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
-#define Z90STAT_DOMAIN_INDEX _IOR(Z90_IOCTL_MAGIC, 0x47, int)
-#define Z90STAT_STATUS_MASK _IOR(Z90_IOCTL_MAGIC, 0x48, char[64])
-#define Z90STAT_QDEPTH_MASK _IOR(Z90_IOCTL_MAGIC, 0x49, char[64])
-#define Z90STAT_PERDEV_REQCNT _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64])
+#include <asm/z90crypt.h>
/**
* local errno definitions
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 982acc7303ea..b2f20ab8431a 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -411,7 +411,6 @@ static struct miscdevice z90crypt_misc_device = {
.minor = Z90CRYPT_MINOR,
.name = DEV_NAME,
.fops = &z90crypt_fops,
- .devfs_name = DEV_NAME
};
/**
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index 7145e2134cf0..2c1db8036b7c 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -4,7 +4,6 @@
*/
#include "fsm.h"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/timer.h>
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index e0c7deb98831..189a49275433 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/config.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index f94419b334f7..2eded55ae88d 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1140,10 +1140,9 @@ list_modified:
}
}
/* re-insert all entries from the failed_list into ipm_list */
- list_for_each_entry_safe(ipm, tmp, &failed_list, list) {
- list_del_init(&ipm->list);
- list_add_tail(&ipm->list, &card->ipm_list);
- }
+ list_for_each_entry_safe(ipm, tmp, &failed_list, list)
+ list_move_tail(&ipm->list, &card->ipm_list);
+
spin_unlock_irqrestore(&card->ipm_lock, flags);
}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 0bab60a20309..8491598f9149 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -8,7 +8,6 @@
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/ip.h>
#include <linux/inetdevice.h>
@@ -420,7 +419,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
}
tcph = eddp->skb->h.th;
while (eddp->skb_offset < eddp->skb->len) {
- data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
+ data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
(int)(eddp->skb->len - eddp->skb_offset));
/* prepare qdio hdr */
if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
@@ -515,20 +514,20 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
QETH_DBF_TEXT(trace, 5, "eddpcanp");
/* can we put multiple skbs in one page? */
- skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
+ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
if (skbs_per_page > 1){
- ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
+ ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
skbs_per_page + 1;
ctx->elements_per_skb = 1;
} else {
/* no -> how many elements per skb? */
- ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
+ ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
PAGE_SIZE) >> PAGE_SHIFT;
ctx->num_pages = ctx->elements_per_skb *
- (skb_shinfo(skb)->tso_segs + 1);
+ (skb_shinfo(skb)->gso_segs + 1);
}
ctx->num_elements = ctx->elements_per_skb *
- (skb_shinfo(skb)->tso_segs + 1);
+ (skb_shinfo(skb)->gso_segs + 1);
}
static inline struct qeth_eddp_context *
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 9e671a48cd2f..36733b9823c6 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -27,7 +27,6 @@
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
@@ -4417,7 +4416,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
struct qeth_eddp_context *ctx = NULL;
int tx_bytes = skb->len;
unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
- unsigned short tso_size = skb_shinfo(skb)->tso_size;
+ unsigned short tso_size = skb_shinfo(skb)->gso_size;
int rc;
QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4453,7 +4452,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
queue = card->qdio.out_qs
[qeth_get_priority_queue(card, skb, ipv, cast_type)];
- if (skb_shinfo(skb)->tso_size)
+ if (skb_shinfo(skb)->gso_size)
large_send = card->options.large_send;
/*are we able to do TSO ? If so ,prepare and send it from here */
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 24ef40ca9562..593f298142c1 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
hdr->ext.hdr_version = 1;
hdr->ext.hdr_len = 28;
/*insert non-fix values */
- hdr->ext.mss = skb_shinfo(skb)->tso_size;
+ hdr->ext.mss = skb_shinfo(skb)->gso_size;
hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
sizeof(struct qeth_hdr_tso));
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index f99e55308b32..432136f96e64 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -8,12 +8,12 @@
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
#include <linux/time.h>
+#include <linux/kthread.h>
#include <asm/lowcore.h>
@@ -56,8 +56,6 @@ s390_collect_crw_info(void *param)
unsigned int chain;
sem = (struct semaphore *)param;
- /* Set a nice name. */
- daemonize("kmcheck");
repeat:
down_interruptible(sem);
slow = 0;
@@ -516,7 +514,7 @@ arch_initcall(machine_check_init);
static int __init
machine_check_crw_init (void)
{
- kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES);
+ kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
ctl_set_bit(14, 28); /* enable channel report MCH */
return 0;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 395cfc6a344f..9cd789b8acd4 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1,18 +1,8 @@
/*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * linux/drivers/s390/scsi/zfcp_aux.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -29,6 +19,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/*
+ * Driver authors:
+ * Martin Peschke (originator of the driver)
+ * Raimund Schroeder
+ * Aron Zeh
+ * Wolfgang Taphorn
+ * Stefan Bader
+ * Heiko Carstens (kernel 2.6 port of the driver)
+ * Andreas Herrmann
+ * Maxim Shchetynin
+ * Volker Sameske
+ * Ralph Wuerthner
+ */
+
#include "zfcp_ext.h"
/* accumulated log level (module parameter) */
@@ -75,15 +79,9 @@ static struct miscdevice zfcp_cfdc_misc = {
/* declare driver module init/cleanup functions */
module_init(zfcp_module_init);
-MODULE_AUTHOR("Heiko Carstens <heiko.carstens@de.ibm.com>, "
- "Andreas Herrman <aherrman@de.ibm.com>, "
- "Martin Peschke <mpeschke@de.ibm.com>, "
- "Raimund Schroeder <raimund.schroeder@de.ibm.com>, "
- "Wolfgang Taphorn <taphorn@de.ibm.com>, "
- "Aron Zeh <arzeh@de.ibm.com>, "
- "IBM Deutschland Entwicklung GmbH");
+MODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com");
MODULE_DESCRIPTION
- ("FCP (SCSI over Fibre Channel) HBA driver for IBM eServer zSeries");
+ ("FCP (SCSI over Fibre Channel) HBA driver for IBM System z9 and zSeries");
MODULE_LICENSE("GPL");
module_param(device, charp, 0400);
@@ -291,12 +289,11 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
goto out;
}
- sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
+ sg_list = kzalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
if (sg_list == NULL) {
retval = -ENOMEM;
goto out;
}
- memset(sg_list, 0, sizeof(*sg_list));
if (command != ZFCP_CFDC_IOC) {
ZFCP_LOG_INFO("IOC request code 0x%x invalid\n", command);
@@ -478,14 +475,13 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
sg_list->count = size >> PAGE_SHIFT;
if (size & ~PAGE_MASK)
sg_list->count++;
- sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist),
+ sg_list->sg = kcalloc(sg_list->count, sizeof(struct scatterlist),
GFP_KERNEL);
if (sg_list->sg == NULL) {
sg_list->count = 0;
retval = -ENOMEM;
goto out;
}
- memset(sg_list->sg, 0, sg_list->count * sizeof(struct scatterlist));
for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
sg->length = min(size, PAGE_SIZE);
@@ -744,7 +740,7 @@ struct zfcp_unit *
zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
{
struct zfcp_unit *unit, *tmp_unit;
- scsi_lun_t scsi_lun;
+ unsigned int scsi_lun;
int found;
/*
@@ -758,10 +754,9 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
if (unit)
return NULL;
- unit = kmalloc(sizeof (struct zfcp_unit), GFP_KERNEL);
+ unit = kzalloc(sizeof (struct zfcp_unit), GFP_KERNEL);
if (!unit)
return NULL;
- memset(unit, 0, sizeof (struct zfcp_unit));
/* initialise reference count stuff */
atomic_set(&unit->refcount, 0);
@@ -929,13 +924,12 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
*/
/* try to allocate new adapter data structure (zeroed) */
- adapter = kmalloc(sizeof (struct zfcp_adapter), GFP_KERNEL);
+ adapter = kzalloc(sizeof (struct zfcp_adapter), GFP_KERNEL);
if (!adapter) {
ZFCP_LOG_INFO("error: allocation of base adapter "
"structure failed\n");
goto out;
}
- memset(adapter, 0, sizeof (struct zfcp_adapter));
ccw_device->handler = NULL;
@@ -997,12 +991,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
/* intitialise SCSI ER timer */
init_timer(&adapter->scsi_er_timer);
- /* set FC service class used per default */
- adapter->fc_service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT;
-
- sprintf(adapter->name, "%s", zfcp_get_busid_by_adapter(adapter));
- ASCEBC(adapter->name, strlen(adapter->name));
-
/* mark adapter unusable as long as sysfs registration is not complete */
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -1139,10 +1127,9 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
return NULL;
}
- port = kmalloc(sizeof (struct zfcp_port), GFP_KERNEL);
+ port = kzalloc(sizeof (struct zfcp_port), GFP_KERNEL);
if (!port)
return NULL;
- memset(port, 0, sizeof (struct zfcp_port));
/* initialise reference count stuff */
atomic_set(&port->refcount, 0);
@@ -1354,18 +1341,19 @@ static void
zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
struct fsf_status_read_buffer *status_buffer)
{
- logi *els_logi = (logi *) status_buffer->payload;
+ struct fsf_plogi *els_plogi;
struct zfcp_port *port;
unsigned long flags;
+ els_plogi = (struct fsf_plogi *) status_buffer->payload;
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn))
+ if (port->wwpn == (*(wwn_t *) &els_plogi->serv_param.wwpn))
break;
}
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
- if (!port || (port->wwpn != (*(wwn_t *) & els_logi->nport_wwn))) {
+ if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) {
ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port "
"with d_id 0x%08x on adapter %s\n",
status_buffer->d_id,
@@ -1760,4 +1748,25 @@ zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par)
return ret;
}
+/**
+ * zfcp_plogi_evaluate - evaluate PLOGI playload and copy important fields
+ * into zfcp_port structure
+ * @port: zfcp_port structure
+ * @plogi: plogi payload
+ */
+void
+zfcp_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi)
+{
+ port->maxframe_size = plogi->serv_param.common_serv_param[7] |
+ ((plogi->serv_param.common_serv_param[6] & 0x0F) << 8);
+ if (plogi->serv_param.class1_serv_param[0] & 0x80)
+ port->supported_classes |= FC_COS_CLASS1;
+ if (plogi->serv_param.class2_serv_param[0] & 0x80)
+ port->supported_classes |= FC_COS_CLASS2;
+ if (plogi->serv_param.class3_serv_param[0] & 0x80)
+ port->supported_classes |= FC_COS_CLASS3;
+ if (plogi->serv_param.class4_serv_param[0] & 0x80)
+ port->supported_classes |= FC_COS_CLASS4;
+}
+
#undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 241136d0c6eb..57d8e4bfb8d9 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -1,16 +1,8 @@
/*
- * linux/drivers/s390/scsi/zfcp_ccw.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * FCP adapter driver for IBM eServer zSeries
- *
- * CCW driver related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- * Martin Peschke <mpeschke@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index a5f2ba9a8fdb..c033145d0f19 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1,12 +1,8 @@
/*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * linux/drivers/s390/scsi/zfcp_dbf.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * Debugging facilities
- *
- * (C) Copyright IBM Corp. 2005
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 6eba56cd89ba..2df512a18e2c 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -1,19 +1,8 @@
/*
- *
- * linux/drivers/s390/scsi/zfcp_def.h
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
- * Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -50,7 +39,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
-#include "../../fc4/fc.h"
#include "zfcp_fsf.h"
#include <asm/ccwdev.h>
#include <asm/qdio.h>
@@ -64,7 +52,7 @@
/********************* GENERAL DEFINES *********************************/
/* zfcp version number, it consists of major, minor, and patch-level number */
-#define ZFCP_VERSION "4.5.0"
+#define ZFCP_VERSION "4.7.0"
/**
* zfcp_sg_to_address - determine kernel address from struct scatterlist
@@ -89,13 +77,9 @@ zfcp_address_to_sg(void *address, struct scatterlist *list)
list->offset = ((unsigned long) address) & (PAGE_SIZE - 1);
}
-/********************* SCSI SPECIFIC DEFINES *********************************/
+#define REQUEST_LIST_SIZE 128
-/* 32 bit for SCSI ID and LUN as long as the SCSI stack uses this type */
-typedef u32 scsi_id_t;
-typedef u32 scsi_lun_t;
-
-#define ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT (100*HZ)
+/********************* SCSI SPECIFIC DEFINES *********************************/
#define ZFCP_SCSI_ER_TIMEOUT (100*HZ)
/********************* CIO/QDIO SPECIFIC DEFINES *****************************/
@@ -233,8 +217,9 @@ struct fcp_rsp_iu {
#define RSP_CODE_TASKMAN_FAILED 5
/* see fc-fs */
-#define LS_FAN 0x60000000
-#define LS_RSCN 0x61040000
+#define LS_RSCN 0x61040000
+#define LS_LOGO 0x05000000
+#define LS_PLOGI 0x03000000
struct fcp_rscn_head {
u8 command;
@@ -263,13 +248,6 @@ struct fcp_rscn_element {
#define ZFCP_NO_PORTS_PER_DOMAIN 0x10000
#define ZFCP_NO_PORTS_PER_FABRIC 0x1000000
-struct fcp_fan {
- u32 command;
- u32 fport_did;
- wwn_t fport_wwpn;
- wwn_t fport_wwname;
-} __attribute__((packed));
-
/* see fc-ph */
struct fcp_logo {
u32 command;
@@ -507,9 +485,6 @@ struct zfcp_rc_entry {
#define ZFCP_NAME "zfcp"
-/* read-only LUN sharing switch initial value */
-#define ZFCP_RO_LUN_SHARING_DEFAULTS 0
-
/* independent log areas */
#define ZFCP_LOG_AREA_OTHER 0
#define ZFCP_LOG_AREA_SCSI 1
@@ -608,7 +583,6 @@ do { \
* and unit
*/
#define ZFCP_COMMON_FLAGS 0xfff00000
-#define ZFCP_SPECIFIC_FLAGS 0x000fffff
/* common status bits */
#define ZFCP_STATUS_COMMON_REMOVE 0x80000000
@@ -633,11 +607,6 @@ do { \
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
#define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800
-#define ZFCP_STATUS_ADAPTER_SCSI_UP \
- (ZFCP_STATUS_COMMON_UNBLOCKED | \
- ZFCP_STATUS_ADAPTER_REGISTERED)
-
-
/* FC-PH/FC-GS well-known address identifiers for generic services */
#define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA
#define ZFCP_DID_TIME_SERVICE 0xFFFFFB
@@ -652,7 +621,6 @@ do { \
#define ZFCP_STATUS_PORT_NO_WWPN 0x00000008
#define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010
#define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020
-#define ZFCP_STATUS_PORT_ACCESS_DENIED 0x00000040
/* for ports with well known addresses */
#define ZFCP_STATUS_PORT_WKA \
@@ -908,15 +876,12 @@ struct zfcp_adapter {
wwn_t peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
- u8 fc_service_class;
u32 hydra_version; /* Hydra version */
u32 fsf_lic_version;
u32 adapter_features; /* FCP channel features */
u32 connection_features; /* host connection features */
u32 hardware_version; /* of FCP channel */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
- unsigned short scsi_host_no; /* Assigned host number */
- unsigned char name[9];
struct list_head port_list_head; /* remote port list */
struct list_head port_remove_lh; /* head of ports to be
removed */
@@ -994,6 +959,8 @@ struct zfcp_port {
u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
+ u32 maxframe_size;
+ u32 supported_classes;
};
/* the struct device sysfs_device must be at the beginning of this structure.
@@ -1008,7 +975,7 @@ struct zfcp_unit {
refcount drop to zero */
struct zfcp_port *port; /* remote port of unit */
atomic_t status; /* status of this logical unit */
- scsi_lun_t scsi_lun; /* own SCSI LUN */
+ unsigned int scsi_lun; /* own SCSI LUN */
fcp_lun_t fcp_lun; /* own FCP_LUN */
u32 handle; /* handle assigned by FSF */
struct scsi_device *device; /* scsi device struct pointer */
@@ -1052,11 +1019,6 @@ struct zfcp_data {
struct list_head adapter_list_head; /* head of adapter list */
struct list_head adapter_remove_lh; /* head of adapters to be
removed */
- rwlock_t status_read_lock; /* for status read thread */
- struct list_head status_read_receive_head;
- struct list_head status_read_send_head;
- struct semaphore status_read_sema;
- wait_queue_head_t status_read_thread_wqh;
u32 adapters; /* # of adapters in list */
rwlock_t config_lock; /* serialises changes
to adapter/port/unit
@@ -1095,9 +1057,6 @@ struct zfcp_fsf_req_pool_element {
/********************** ZFCP SPECIFIC DEFINES ********************************/
-#define ZFCP_FSFREQ_CLEANUP_TIMEOUT HZ/10
-
-#define ZFCP_KNOWN 0x00000001
#define ZFCP_REQ_AUTO_CLEANUP 0x00000002
#define ZFCP_WAIT_FOR_SBAL 0x00000004
#define ZFCP_REQ_NO_QTCB 0x00000008
@@ -1105,9 +1064,6 @@ struct zfcp_fsf_req_pool_element {
#define ZFCP_SET 0x00000100
#define ZFCP_CLEAR 0x00000200
-#define ZFCP_INTERRUPTIBLE 1
-#define ZFCP_UNINTERRUPTIBLE 0
-
#ifndef atomic_test_mask
#define atomic_test_mask(mask, target) \
((atomic_read(target) & mask) == mask)
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 57cb628a05aa..909731b99d26 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1,18 +1,8 @@
/*
- *
- * linux/drivers/s390/scsi/zfcp_erp.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
+ *
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -177,7 +167,7 @@ zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
* initiates adapter recovery which is done
* asynchronously
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
int
@@ -213,7 +203,7 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
* purpose: Wrappper for zfcp_erp_adapter_reopen_internal
* used to ensure the correct locking
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
int
@@ -231,13 +221,6 @@ zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
int
zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask)
{
@@ -251,13 +234,6 @@ zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
int
zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask)
{
@@ -271,13 +247,6 @@ zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
int
zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
{
@@ -306,20 +275,17 @@ zfcp_erp_adisc(struct zfcp_port *port)
int retval = 0;
struct timer_list *timer;
- send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
+ send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
if (send_els == NULL)
goto nomem;
- memset(send_els, 0, sizeof(*send_els));
- send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+ send_els->req = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC);
if (send_els->req == NULL)
goto nomem;
- memset(send_els->req, 0, sizeof(*send_els->req));
- send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+ send_els->resp = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC);
if (send_els->resp == NULL)
goto nomem;
- memset(send_els->resp, 0, sizeof(*send_els->resp));
address = (void *) get_zeroed_page(GFP_ATOMIC);
if (address == NULL)
@@ -503,7 +469,7 @@ zfcp_test_link(struct zfcp_port *port)
* initiates Forced Reopen recovery which is done
* asynchronously
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
static int
@@ -543,7 +509,7 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
* purpose: Wrappper for zfcp_erp_port_forced_reopen_internal
* used to ensure the correct locking
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
int
@@ -570,7 +536,7 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
* initiates Reopen recovery which is done
* asynchronously
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
static int
@@ -639,7 +605,7 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
* initiates Reopen recovery which is done
* asynchronously
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
static int
@@ -812,13 +778,6 @@ zfcp_erp_unit_unblock(struct zfcp_unit *unit)
atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static void
zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
{
@@ -1356,13 +1315,6 @@ zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
{
@@ -1538,13 +1490,6 @@ zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result)
return result;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_strategy_statechange(int action,
u32 status,
@@ -1586,13 +1531,6 @@ zfcp_erp_strategy_statechange(int action,
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static inline int
zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
{
@@ -1605,13 +1543,6 @@ zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
!(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status));
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
{
@@ -1642,13 +1573,6 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
return result;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
{
@@ -1678,13 +1602,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
return result;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
{
@@ -1764,13 +1681,6 @@ zfcp_erp_strategy_followup_actions(int action,
return 0;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
{
@@ -1809,12 +1719,6 @@ zfcp_erp_wait(struct zfcp_adapter *adapter)
return retval;
}
-/*
- * function: zfcp_erp_modify_adapter_status
- *
- * purpose:
- *
- */
void
zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
u32 mask, int set_or_clear)
@@ -1901,7 +1805,7 @@ zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
* purpose: Wrappper for zfcp_erp_port_reopen_all_internal
* used to ensure the correct locking
*
- * returns: 0 - initiated action succesfully
+ * returns: 0 - initiated action successfully
* <0 - failed to initiate action
*/
int
@@ -1919,13 +1823,6 @@ zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns: FIXME
- */
static int
zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
{
@@ -2370,13 +2267,6 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
return ret;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
*erp_action)
@@ -2545,13 +2435,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action)
{
@@ -2566,15 +2449,6 @@ zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- *
- * FIXME(design): currently only prepared for fabric (nameserver!)
- */
static int
zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
{
@@ -2690,13 +2564,6 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
{
@@ -2813,13 +2680,6 @@ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
{
@@ -3022,13 +2882,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
{
@@ -3129,13 +2982,6 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static inline void
zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action)
{
@@ -3331,13 +3177,6 @@ zfcp_erp_action_enqueue(int action,
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
{
@@ -3402,9 +3241,13 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
+ &port->status)) {
+ zfcp_port_put(port);
+ break;
+ }
+
if ((result == ZFCP_ERP_SUCCEEDED)
- && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
- &port->status)
&& !port->rport) {
struct fc_rport_identifiers ids;
ids.node_name = port->wwnn;
@@ -3418,12 +3261,30 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
"(adapter %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port),
port->wwpn);
- else
+ else {
scsi_flush_work(adapter->scsi_host);
+ port->rport->maxframe_size = port->maxframe_size;
+ port->rport->supported_classes =
+ port->supported_classes;
+ }
+ }
+ if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) {
+ fc_remote_port_delete(port->rport);
+ port->rport = NULL;
}
zfcp_port_put(port);
break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ if (result != ZFCP_ERP_SUCCEEDED) {
+ struct zfcp_port *port;
+ list_for_each_entry(port, &adapter->port_list_head, list)
+ if (port->rport &&
+ !atomic_test_mask(ZFCP_STATUS_PORT_WKA,
+ &port->status)) {
+ fc_remote_port_delete(port->rport);
+ port->rport = NULL;
+ }
+ }
zfcp_adapter_put(adapter);
break;
default:
@@ -3432,13 +3293,6 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
}
-/*
- * function:
- *
- * purpose:
- *
- * returns: FIXME
- */
static int
zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
{
@@ -3455,13 +3309,6 @@ zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns: FIXME
- */
static int
zfcp_erp_action_dismiss_port(struct zfcp_port *port)
{
@@ -3480,13 +3327,6 @@ zfcp_erp_action_dismiss_port(struct zfcp_port *port)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns: FIXME
- */
static int
zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
{
@@ -3501,13 +3341,6 @@ zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
return retval;
}
-/*
- * function:
- *
- * purpose: moves erp_action to 'erp running list'
- *
- * returns:
- */
static inline void
zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
{
@@ -3518,13 +3351,6 @@ zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
}
-/*
- * function:
- *
- * purpose: moves erp_action to 'erp ready list'
- *
- * returns:
- */
static inline void
zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
{
@@ -3535,11 +3361,6 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
}
-/*
- * function: zfcp_erp_port_boxed
- *
- * purpose:
- */
void
zfcp_erp_port_boxed(struct zfcp_port *port)
{
@@ -3556,11 +3377,6 @@ zfcp_erp_port_boxed(struct zfcp_port *port)
zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
}
-/*
- * function: zfcp_erp_unit_boxed
- *
- * purpose:
- */
void
zfcp_erp_unit_boxed(struct zfcp_unit *unit)
{
@@ -3574,11 +3390,6 @@ zfcp_erp_unit_boxed(struct zfcp_unit *unit)
zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
}
-/*
- * function: zfcp_erp_port_access_denied
- *
- * purpose:
- */
void
zfcp_erp_port_access_denied(struct zfcp_port *port)
{
@@ -3595,11 +3406,6 @@ zfcp_erp_port_access_denied(struct zfcp_port *port)
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
-/*
- * function: zfcp_erp_unit_access_denied
- *
- * purpose:
- */
void
zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
{
@@ -3613,11 +3419,6 @@ zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
ZFCP_SET);
}
-/*
- * function: zfcp_erp_adapter_access_changed
- *
- * purpose:
- */
void
zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
{
@@ -3628,7 +3429,7 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
return;
debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
- debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
+ debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8);
read_lock_irqsave(&zfcp_data.config_lock, flags);
if (adapter->nameserver_port)
@@ -3639,11 +3440,6 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
-/*
- * function: zfcp_erp_port_access_changed
- *
- * purpose:
- */
void
zfcp_erp_port_access_changed(struct zfcp_port *port)
{
@@ -3672,11 +3468,6 @@ zfcp_erp_port_access_changed(struct zfcp_port *port)
zfcp_get_busid_by_adapter(adapter), port->wwpn);
}
-/*
- * function: zfcp_erp_unit_access_changed
- *
- * purpose:
- */
void
zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
{
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 700f5402a978..d02366004cdd 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -1,18 +1,8 @@
/*
- *
- * linux/drivers/s390/scsi/zfcp_ext.h
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -125,6 +115,7 @@ extern int zfcp_nameserver_enqueue(struct zfcp_adapter *);
extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
extern int zfcp_check_ct_response(struct ct_hdr *);
extern int zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *);
+extern void zfcp_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
/******************************* SCSI ****************************************/
extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
@@ -141,8 +132,6 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
struct timer_list *);
-extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
-extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 662ec571d73b..6335f9229184 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1,19 +1,8 @@
/*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * linux/drivers/s390/scsi/zfcp_fsf.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
- * Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -877,6 +866,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
struct zfcp_adapter *adapter = fsf_req->adapter;
struct fsf_status_read_buffer *status_buffer =
(struct fsf_status_read_buffer *) fsf_req->data;
+ struct fsf_bit_error_payload *fsf_bit_error;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer);
@@ -903,10 +893,37 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
- ZFCP_LOG_NORMAL("Bit error threshold data received:\n");
- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
- (char *) status_buffer,
- sizeof (struct fsf_status_read_buffer));
+ fsf_bit_error = (struct fsf_bit_error_payload *)
+ status_buffer->payload;
+ ZFCP_LOG_NORMAL("Warning: bit error threshold data "
+ "received (adapter %s, "
+ "link failures = %i, loss of sync errors = %i, "
+ "loss of signal errors = %i, "
+ "primitive sequence errors = %i, "
+ "invalid transmission word errors = %i, "
+ "CRC errors = %i)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ fsf_bit_error->link_failure_error_count,
+ fsf_bit_error->loss_of_sync_error_count,
+ fsf_bit_error->loss_of_signal_error_count,
+ fsf_bit_error->primitive_sequence_error_count,
+ fsf_bit_error->invalid_transmission_word_error_count,
+ fsf_bit_error->crc_error_count);
+ ZFCP_LOG_INFO("Additional bit error threshold data "
+ "(adapter %s, "
+ "primitive sequence event time-outs = %i, "
+ "elastic buffer overrun errors = %i, "
+ "advertised receive buffer-to-buffer credit = %i, "
+ "current receice buffer-to-buffer credit = %i, "
+ "advertised transmit buffer-to-buffer credit = %i, "
+ "current transmit buffer-to-buffer credit = %i)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ fsf_bit_error->primitive_sequence_event_timeout_count,
+ fsf_bit_error->elastic_buffer_overrun_error_count,
+ fsf_bit_error->advertised_receive_b2b_credit,
+ fsf_bit_error->current_receive_b2b_credit,
+ fsf_bit_error->advertised_transmit_b2b_credit,
+ fsf_bit_error->current_transmit_b2b_credit);
break;
case FSF_STATUS_READ_LINK_DOWN:
@@ -1427,7 +1444,8 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
/* settings in QTCB */
fsf_req->qtcb->header.port_handle = port->handle;
- fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
+ fsf_req->qtcb->bottom.support.service_class =
+ ZFCP_FC_SERVICE_CLASS_DEFAULT;
fsf_req->qtcb->bottom.support.timeout = ct->timeout;
fsf_req->data = (unsigned long) ct;
@@ -1496,18 +1514,10 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- if (adapter->fc_service_class <= 3) {
- ZFCP_LOG_INFO("error: adapter %s does not support fc "
- "class %d.\n",
- zfcp_get_busid_by_port(port),
- adapter->fc_service_class);
- } else {
- ZFCP_LOG_INFO("bug: The fibre channel class at the "
- "adapter %s is invalid. "
- "(debug info %d)\n",
- zfcp_get_busid_by_port(port),
- adapter->fc_service_class);
- }
+ ZFCP_LOG_INFO("error: adapter %s does not support fc "
+ "class %d.\n",
+ zfcp_get_busid_by_port(port),
+ ZFCP_FC_SERVICE_CLASS_DEFAULT);
/* stop operation for this adapter */
debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
zfcp_erp_adapter_shutdown(adapter, 0);
@@ -1730,7 +1740,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
/* settings in QTCB */
fsf_req->qtcb->bottom.support.d_id = d_id;
- fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
+ fsf_req->qtcb->bottom.support.service_class =
+ ZFCP_FC_SERVICE_CLASS_DEFAULT;
fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT;
fsf_req->data = (unsigned long) els;
@@ -1800,18 +1811,10 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- if (adapter->fc_service_class <= 3) {
- ZFCP_LOG_INFO("error: adapter %s does "
- "not support fibrechannel class %d.\n",
- zfcp_get_busid_by_adapter(adapter),
- adapter->fc_service_class);
- } else {
- ZFCP_LOG_INFO("bug: The fibrechannel class at "
- "adapter %s is invalid. "
- "(debug info %d)\n",
- zfcp_get_busid_by_adapter(adapter),
- adapter->fc_service_class);
- }
+ ZFCP_LOG_INFO("error: adapter %s does not support fc "
+ "class %d.\n",
+ zfcp_get_busid_by_adapter(adapter),
+ ZFCP_FC_SERVICE_CLASS_DEFAULT);
/* stop operation for this adapter */
debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
zfcp_erp_adapter_shutdown(adapter, 0);
@@ -1940,14 +1943,6 @@ skip_fsfstatus:
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns: address of initiated FSF request
- * NULL - request could not be initiated
- */
int
zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
{
@@ -2565,8 +2560,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status))
{
if (fsf_req->qtcb->bottom.support.els1_length <
- ((((unsigned long) &plogi->serv_param.wwpn) -
- ((unsigned long) plogi)) + sizeof (u64))) {
+ sizeof (struct fsf_plogi)) {
ZFCP_LOG_INFO(
"warning: insufficient length of "
"PLOGI payload (%i)\n",
@@ -2585,8 +2579,10 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
atomic_clear_mask(
ZFCP_STATUS_PORT_DID_DID,
&port->status);
- } else
+ } else {
port->wwnn = plogi->serv_param.wwnn;
+ zfcp_plogi_evaluate(port, plogi);
+ }
}
}
break;
@@ -2993,8 +2989,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
erp_action->unit->fcp_lun;
if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE))
- erp_action->fsf_req->qtcb->bottom.support.option =
- FSF_OPEN_LUN_SUPPRESS_BOXING;
+ erp_action->fsf_req->qtcb->bottom.support.option =
+ FSF_OPEN_LUN_SUPPRESS_BOXING;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
erp_action->fsf_req->data = (unsigned long) erp_action->unit;
erp_action->fsf_req->erp_action = erp_action;
@@ -3569,7 +3565,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
}
/* set FC service class in QTCB (3 per default) */
- fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class;
+ fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT;
/* set FCP_LUN in FCP_CMND IU in QTCB */
fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
@@ -3667,18 +3663,6 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
return retval;
}
-/*
- * function: zfcp_fsf_send_fcp_command_task_management
- *
- * purpose:
- *
- * returns:
- *
- * FIXME(design): should be watched by a timeout!!!
- * FIXME(design) shouldn't this be modified to return an int
- * also...don't know how though
- *
- */
struct zfcp_fsf_req *
zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
struct zfcp_unit *unit,
@@ -3720,7 +3704,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
fsf_req->qtcb->header.lun_handle = unit->handle;
fsf_req->qtcb->header.port_handle = unit->port->handle;
fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
- fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class;
+ fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT;
fsf_req->qtcb->bottom.io.fcp_cmnd_length =
sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t);
@@ -3843,18 +3827,10 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- if (fsf_req->adapter->fc_service_class <= 3) {
- ZFCP_LOG_NORMAL("error: The adapter %s does "
- "not support fibrechannel class %d.\n",
- zfcp_get_busid_by_unit(unit),
- fsf_req->adapter->fc_service_class);
- } else {
- ZFCP_LOG_NORMAL("bug: The fibrechannel class at "
- "adapter %s is invalid. "
- "(debug info %d)\n",
- zfcp_get_busid_by_unit(unit),
- fsf_req->adapter->fc_service_class);
- }
+ ZFCP_LOG_INFO("error: adapter %s does not support fc "
+ "class %d.\n",
+ zfcp_get_busid_by_unit(unit),
+ ZFCP_FC_SERVICE_CLASS_DEFAULT);
/* stop operation for this adapter */
debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"fsf_s_class_nsup");
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index e734415cae6d..71186618947c 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -1,19 +1,8 @@
/*
- *
- * linux/drivers/s390/scsi/zfcp_fsf.h
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
- * Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -33,8 +22,7 @@
#ifndef FSF_H
#define FSF_H
-#define FSF_QTCB_VERSION1 0x00000001
-#define FSF_QTCB_CURRENT_VERSION FSF_QTCB_VERSION1
+#define FSF_QTCB_CURRENT_VERSION 0x00000001
/* FSF commands */
#define FSF_QTCB_FCP_CMND 0x00000001
@@ -64,7 +52,7 @@
#define FSF_CFDC_OPTION_FULL_ACCESS 0x00000002
#define FSF_CFDC_OPTION_RESTRICTED_ACCESS 0x00000004
-/* FSF protocol stati */
+/* FSF protocol states */
#define FSF_PROT_GOOD 0x00000001
#define FSF_PROT_QTCB_VERSION_ERROR 0x00000010
#define FSF_PROT_SEQ_NUMB_ERROR 0x00000020
@@ -76,7 +64,7 @@
#define FSF_PROT_REEST_QUEUE 0x00000800
#define FSF_PROT_ERROR_STATE 0x01000000
-/* FSF stati */
+/* FSF states */
#define FSF_GOOD 0x00000000
#define FSF_PORT_ALREADY_OPEN 0x00000001
#define FSF_LUN_ALREADY_OPEN 0x00000002
@@ -269,20 +257,6 @@
#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000
#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000
-struct fsf_queue_designator;
-struct fsf_status_read_buffer;
-struct fsf_port_closed_payload;
-struct fsf_bit_error_payload;
-union fsf_prot_status_qual;
-struct fsf_qual_version_error;
-struct fsf_qual_sequence_error;
-struct fsf_qtcb_prefix;
-struct fsf_qtcb_header;
-struct fsf_qtcb_bottom_config;
-struct fsf_qtcb_bottom_support;
-struct fsf_qtcb_bottom_io;
-union fsf_qtcb_bottom;
-
struct fsf_queue_designator {
u8 cssid;
u8 chpid;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 1c3275163c91..345a191926a4 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -1,18 +1,8 @@
/*
- * linux/drivers/s390/scsi/zfcp_qdio.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * FCP adapter driver for IBM eServer zSeries
- *
- * QDIO related routines
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Authors:
- * Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Wolfgang Taphorn
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -178,7 +168,8 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter)
init_data->cdev = adapter->ccw_device;
init_data->q_format = QDIO_SCSI_QFMT;
- memcpy(init_data->adapter_name, &adapter->name, 8);
+ memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 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;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 9e6d07d7b3c8..46e14f22ec18 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -1,18 +1,8 @@
/*
- *
- * linux/drivers/s390/scsi/zfcp_scsi.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- * Raimund Schroeder <raimund.schroeder@de.ibm.com>
- * Aron Zeh
- * Wolfgang Taphorn
- * Stefan Bader <stefan.bader@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
@@ -45,8 +35,8 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
static int zfcp_task_management_function(struct zfcp_unit *, u8,
struct scsi_cmnd *);
-static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
- scsi_lun_t);
+static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
+ unsigned int, unsigned int);
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
@@ -161,14 +151,6 @@ set_driver_byte(u32 * result, char status)
set_byte(result, status, 3);
}
-/*
- * function: zfcp_scsi_slave_alloc
- *
- * purpose:
- *
- * returns:
- */
-
static int
zfcp_scsi_slave_alloc(struct scsi_device *sdp)
{
@@ -195,14 +177,6 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp)
return retval;
}
-/*
- * function: zfcp_scsi_slave_destroy
- *
- * purpose:
- *
- * returns:
- */
-
static void
zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
{
@@ -374,18 +348,9 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return zfcp_scsi_command_async(adapter, unit, scpnt, NULL);
}
-/*
- * function: zfcp_unit_lookup
- *
- * purpose:
- *
- * returns:
- *
- * context:
- */
static struct zfcp_unit *
-zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
- scsi_lun_t lun)
+zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
+ unsigned int lun)
{
struct zfcp_port *port;
struct zfcp_unit *unit, *retval = NULL;
@@ -491,13 +456,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
return retval;
}
-/*
- * function: zfcp_scsi_eh_device_reset_handler
- *
- * purpose:
- *
- * returns:
- */
int
zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
@@ -625,13 +583,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
return SUCCESS;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
int
zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
{
@@ -657,10 +608,6 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
adapter->scsi_host->unique_id = unique_id++; /* FIXME */
adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;
adapter->scsi_host->transportt = zfcp_transport_template;
- /*
- * Reverse mapping of the host number to avoid race condition
- */
- adapter->scsi_host_no = adapter->scsi_host->host_no;
/*
* save a pointer to our own adapter data structure within
@@ -678,13 +625,6 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
return retval;
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
void
zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
{
@@ -703,7 +643,6 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
- adapter->scsi_host_no = 0;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return;
@@ -817,10 +756,9 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost)
if (!fc_stats)
return NULL;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return NULL;
- memset(data, 0, sizeof(*data));
ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
if (ret) {
@@ -848,10 +786,9 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
int ret;
adapter = (struct zfcp_adapter *)shost->hostdata[0];
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return;
- memset(data, 0, sizeof(*data));
ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
if (ret == 0) {
@@ -863,11 +800,18 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
}
}
+static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+ rport->dev_loss_tmo = timeout;
+}
+
struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
.show_starget_node_name = 1,
.show_rport_supported_classes = 1,
+ .show_rport_maxframe_size = 1,
+ .show_rport_dev_loss_tmo = 1,
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_permanent_port_name = 1,
@@ -877,6 +821,7 @@ struct fc_function_template zfcp_transport_functions = {
.show_host_serial_number = 1,
.get_fc_host_stats = zfcp_get_fc_host_stats,
.reset_fc_host_stats = zfcp_reset_fc_host_stats,
+ .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
/* no functions registered for following dynamic attributes but
directly set by LLDD */
.show_host_port_type = 1,
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index b29ac25e07f3..705c6d4428f3 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -1,16 +1,8 @@
/*
- * linux/drivers/s390/scsi/zfcp_sysfs_adapter.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs adapter related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- * Martin Peschke <mpeschke@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c
index 6622d55e0a45..005e62f8593b 100644
--- a/drivers/s390/scsi/zfcp_sysfs_driver.c
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c
@@ -1,16 +1,8 @@
/*
- * linux/drivers/s390/scsi/zfcp_sysfs_driver.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs driver related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- * Martin Peschke <mpeschke@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index f401d42db21c..1320c0591431 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -1,17 +1,8 @@
/*
- * linux/drivers/s390/scsi/zfcp_sysfs_port.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs port related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- * Martin Peschke <mpeschke@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
- * Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index ad5dfb889bee..81a484175863 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -1,17 +1,8 @@
/*
- * linux/drivers/s390/scsi/zfcp_sysfs_unit.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
*
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs unit related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- * Martin Peschke <mpeschke@de.ibm.com>
- * Heiko Carstens <heiko.carstens@de.ibm.com>
- * Andreas Herrmann <aherrman@de.ibm.com>
- * Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
*
* 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
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 66da840c9316..d1c1e75bfd60 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -5,7 +5,6 @@
* Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com)
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>