summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 17:54:03 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 17:54:03 -0800
commit81ec44a6c69342fec1b1140c60a604027e429f69 (patch)
treeee6bec8a94ef28e111bf766cf4b7a9366cb4f7c1 /drivers/s390
parent48a732dfaa77a4dfec803aa8f248373998704f76 (diff)
parente80cfc31d872b6b85b8966bce6ba80bee401a7dd (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 update from Martin Schwidefsky: "The most prominent change in this patch set is the software dirty bit patch for s390. It removes __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY and the page_test_and_clear_dirty primitive which makes the common memory management code a bit less obscure. Heiko fixed most of the PCI related fallout, more often than not missing GENERIC_HARDIRQS dependencies. Notable is one of the 3270 patches which adds an export to tty_io to be able to resize a tty. The rest is the usual bunch of cleanups and bug fixes." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (42 commits) s390/module: Add missing R_390_NONE relocation type drivers/gpio: add missing GENERIC_HARDIRQ dependency drivers/input: add couple of missing GENERIC_HARDIRQS dependencies s390/cleanup: rename SPP to LPP s390/mm: implement software dirty bits s390/mm: Fix crst upgrade of mmap with MAP_FIXED s390/linker skript: discard exit.data at runtime drivers/media: add missing GENERIC_HARDIRQS dependency s390/bpf,jit: add vlan tag support drivers/net,AT91RM9200: add missing GENERIC_HARDIRQS dependency iucv: fix kernel panic at reboot s390/Kconfig: sort list of arch selected config options phylib: remove !S390 dependeny from Kconfig uio: remove !S390 dependency from Kconfig dasd: fix sysfs cleanup in dasd_generic_remove s390/pci: fix hotplug module init s390/pci: cleanup clp page allocation s390/pci: cleanup clp inline assembly s390/perf: cpum_cf: fallback to software sampling events s390/mm: provide PAGE_SHARED define ...
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c23
-rw-r--r--drivers/s390/block/dasd_3990_erp.c8
-rw-r--r--drivers/s390/block/dasd_alias.c4
-rw-r--r--drivers/s390/block/dasd_diag.c10
-rw-r--r--drivers/s390/block/dasd_eckd.c30
-rw-r--r--drivers/s390/block/dasd_eer.c2
-rw-r--r--drivers/s390/block/dasd_erp.c4
-rw-r--r--drivers/s390/block/dasd_fba.c2
-rw-r--r--drivers/s390/block/scm_blk.h41
-rw-r--r--drivers/s390/char/fs3270.c29
-rw-r--r--drivers/s390/char/raw3270.c611
-rw-r--r--drivers/s390/char/raw3270.h12
-rw-r--r--drivers/s390/char/sclp.c4
-rw-r--r--drivers/s390/char/sclp_cmd.c10
-rw-r--r--drivers/s390/char/tty3270.c187
-rw-r--r--drivers/s390/char/zcore.c64
-rw-r--r--drivers/s390/cio/chsc.c68
-rw-r--r--drivers/s390/cio/chsc.h2
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/cmf.c6
-rw-r--r--drivers/s390/cio/css.c2
-rw-r--r--drivers/s390/cio/device.c10
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/device_pgid.c123
-rw-r--r--drivers/s390/cio/io_sch.h5
-rw-r--r--drivers/s390/cio/qdio_main.c12
-rw-r--r--drivers/s390/net/qeth_core.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c2
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c2
29 files changed, 741 insertions, 540 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 29225e1c159c..f1b7fdc58a5f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1352,7 +1352,7 @@ int dasd_term_IO(struct dasd_ccw_req *cqr)
switch (rc) {
case 0: /* termination successful */
cqr->status = DASD_CQR_CLEAR_PENDING;
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
cqr->starttime = 0;
DBF_DEV_EVENT(DBF_DEBUG, device,
"terminate cqr %p successful",
@@ -1420,7 +1420,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
cqr->status = DASD_CQR_ERROR;
return -EIO;
}
- cqr->startclk = get_clock();
+ cqr->startclk = get_tod_clock();
cqr->starttime = jiffies;
cqr->retries--;
if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
@@ -1623,7 +1623,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
return;
}
- now = get_clock();
+ now = get_tod_clock();
cqr = (struct dasd_ccw_req *) intparm;
/* check for conditions that should be handled immediately */
if (!cqr ||
@@ -1963,7 +1963,7 @@ int dasd_flush_device_queue(struct dasd_device *device)
}
break;
case DASD_CQR_QUEUED:
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
cqr->status = DASD_CQR_CLEARED;
break;
default: /* no need to modify the others */
@@ -2210,7 +2210,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
wait_event(generic_waitq, _wait_for_wakeup(cqr));
}
- maincqr->endclk = get_clock();
+ maincqr->endclk = get_tod_clock();
if ((maincqr->status != DASD_CQR_DONE) &&
(maincqr->intrc != -ERESTARTSYS))
dasd_log_sense(maincqr, &maincqr->irb);
@@ -2340,7 +2340,7 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr)
"Cancelling request %p failed with rc=%d\n",
cqr, rc);
} else {
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
}
break;
default: /* already finished or clear pending - do nothing */
@@ -2568,7 +2568,7 @@ restart:
}
/* Rechain finished requests to final queue */
- cqr->endclk = get_clock();
+ cqr->endclk = get_tod_clock();
list_move_tail(&cqr->blocklist, final_queue);
}
}
@@ -2711,7 +2711,7 @@ restart_cb:
}
/* call the callback function */
spin_lock_irq(&block->request_queue_lock);
- cqr->endclk = get_clock();
+ cqr->endclk = get_tod_clock();
list_del_init(&cqr->blocklist);
__dasd_cleanup_cqr(cqr);
spin_unlock_irq(&block->request_queue_lock);
@@ -3042,12 +3042,15 @@ void dasd_generic_remove(struct ccw_device *cdev)
cdev->handler = NULL;
device = dasd_device_from_cdev(cdev);
- if (IS_ERR(device))
+ if (IS_ERR(device)) {
+ dasd_remove_sysfs_files(cdev);
return;
+ }
if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags) &&
!test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
/* Already doing offline processing */
dasd_put_device(device);
+ dasd_remove_sysfs_files(cdev);
return;
}
/*
@@ -3504,7 +3507,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
cqr->memdev = device;
cqr->expires = 10*HZ;
cqr->retries = 256;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index f8212d54013a..d26134713682 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -229,7 +229,7 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
dctl_cqr->expires = 5 * 60 * HZ;
dctl_cqr->retries = 2;
- dctl_cqr->buildclk = get_clock();
+ dctl_cqr->buildclk = get_tod_clock();
dctl_cqr->status = DASD_CQR_FILLED;
@@ -1719,7 +1719,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
erp->magic = default_erp->magic;
erp->expires = default_erp->expires;
erp->retries = 256;
- erp->buildclk = get_clock();
+ erp->buildclk = get_tod_clock();
erp->status = DASD_CQR_FILLED;
/* remove the default erp */
@@ -2322,7 +2322,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
DBF_DEV_EVENT(DBF_ERR, device, "%s",
"Unable to allocate ERP request");
cqr->status = DASD_CQR_FAILED;
- cqr->stopclk = get_clock ();
+ cqr->stopclk = get_tod_clock();
} else {
DBF_DEV_EVENT(DBF_ERR, device,
"Unable to allocate ERP request "
@@ -2364,7 +2364,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
erp->magic = cqr->magic;
erp->expires = cqr->expires;
erp->retries = 256;
- erp->buildclk = get_clock();
+ erp->buildclk = get_tod_clock();
erp->status = DASD_CQR_FILLED;
return erp;
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 6b556995bb33..a2597e683e79 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -448,7 +448,7 @@ static int read_unit_address_configuration(struct dasd_device *device,
ccw->count = sizeof(*(lcu->uac));
ccw->cda = (__u32)(addr_t) lcu->uac;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
/* need to unset flag here to detect race with summary unit check */
@@ -733,7 +733,7 @@ static int reset_summary_unit_check(struct alias_lcu *lcu,
cqr->memdev = device;
cqr->block = NULL;
cqr->expires = 5 * HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
rc = dasd_sleep_on_immediatly(cqr);
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 704488d0f819..cc0603358522 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -184,14 +184,14 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
private->iob.bio_list = dreq->bio;
private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
- cqr->startclk = get_clock();
+ cqr->startclk = get_tod_clock();
cqr->starttime = jiffies;
cqr->retries--;
rc = dia250(&private->iob, RW_BIO);
switch (rc) {
case 0: /* Synchronous I/O finished successfully */
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
cqr->status = DASD_CQR_SUCCESS;
/* Indicate to calling function that only a dasd_schedule_bh()
and no timer is needed */
@@ -222,7 +222,7 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr)
mdsk_term_io(device);
mdsk_init_io(device, device->block->bp_block, 0, NULL);
cqr->status = DASD_CQR_CLEAR_PENDING;
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
dasd_schedule_device_bh(device);
return 0;
}
@@ -276,7 +276,7 @@ static void dasd_ext_handler(struct ext_code ext_code,
return;
}
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
expires = 0;
if ((ext_code.subcode & 0xff) == 0) {
@@ -556,7 +556,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
}
}
cqr->retries = DIAG_MAX_RETRIES;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
if (blk_noretry_request(req) ||
block->base->features & DASD_FEATURE_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index e37bc1620d14..33f26bfa62f2 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -862,7 +862,7 @@ static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device,
cqr->expires = 10*HZ;
cqr->lpm = lpm;
cqr->retries = 256;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
}
@@ -1449,7 +1449,7 @@ static int dasd_eckd_read_features(struct dasd_device *device)
ccw->count = sizeof(struct dasd_rssd_features);
ccw->cda = (__u32)(addr_t) features;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
rc = dasd_sleep_on(cqr);
if (rc == 0) {
@@ -1501,7 +1501,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,
cqr->block = NULL;
cqr->retries = 256;
cqr->expires = 10*HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
@@ -1841,7 +1841,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
cqr->startdev = device;
cqr->memdev = device;
cqr->retries = 255;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
@@ -2241,7 +2241,7 @@ dasd_eckd_format_device(struct dasd_device * device,
fcp->startdev = device;
fcp->memdev = device;
fcp->retries = 256;
- fcp->buildclk = get_clock();
+ fcp->buildclk = get_tod_clock();
fcp->status = DASD_CQR_FILLED;
return fcp;
}
@@ -2530,7 +2530,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
cqr->lpm = startdev->path_data.ppm;
cqr->retries = 256;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
@@ -2705,7 +2705,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
cqr->lpm = startdev->path_data.ppm;
cqr->retries = 256;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
@@ -2998,7 +2998,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
cqr->lpm = startdev->path_data.ppm;
cqr->retries = 256;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
out_error:
@@ -3201,7 +3201,7 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev,
cqr->expires = startdev->default_expires * HZ;
cqr->lpm = startdev->path_data.ppm;
cqr->retries = 256;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
@@ -3402,7 +3402,7 @@ dasd_eckd_release(struct dasd_device *device)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 2; /* set retry counter to enable basic ERP */
cqr->expires = 2 * HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
rc = dasd_sleep_on_immediatly(cqr);
@@ -3457,7 +3457,7 @@ dasd_eckd_reserve(struct dasd_device *device)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 2; /* set retry counter to enable basic ERP */
cqr->expires = 2 * HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
rc = dasd_sleep_on_immediatly(cqr);
@@ -3511,7 +3511,7 @@ dasd_eckd_steal_lock(struct dasd_device *device)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 2; /* set retry counter to enable basic ERP */
cqr->expires = 2 * HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
rc = dasd_sleep_on_immediatly(cqr);
@@ -3572,7 +3572,7 @@ static int dasd_eckd_snid(struct dasd_device *device,
set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
cqr->retries = 5;
cqr->expires = 10 * HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
cqr->lpm = usrparm.path_mask;
@@ -3642,7 +3642,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp)
ccw->count = sizeof(struct dasd_rssd_perf_stats_t);
ccw->cda = (__u32)(addr_t) stats;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
rc = dasd_sleep_on(cqr);
if (rc == 0) {
@@ -3768,7 +3768,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
cqr->memdev = device;
cqr->retries = 3;
cqr->expires = 10 * HZ;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
/* Build the ccws */
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index ff901b5509c1..21ef63cf0960 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -481,7 +481,7 @@ int dasd_eer_enable(struct dasd_device *device)
ccw->flags = 0;
ccw->cda = (__u32)(addr_t) cqr->data;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
cqr->callback = dasd_eer_snss_cb;
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index d01ef82f8757..3250cb471f78 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -102,7 +102,7 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr)
pr_err("%s: default ERP has run out of retries and failed\n",
dev_name(&device->cdev->dev));
cqr->status = DASD_CQR_FAILED;
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
}
return cqr;
} /* end dasd_default_erp_action */
@@ -146,7 +146,7 @@ struct dasd_ccw_req *dasd_default_erp_postaction(struct dasd_ccw_req *cqr)
cqr->status = DASD_CQR_DONE;
else {
cqr->status = DASD_CQR_FAILED;
- cqr->stopclk = get_clock();
+ cqr->stopclk = get_tod_clock();
}
return cqr;
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 414698584344..4dd0e2f6047e 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -370,7 +370,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
cqr->block = block;
cqr->expires = memdev->default_expires * HZ; /* default 5 minutes */
cqr->retries = 32;
- cqr->buildclk = get_clock();
+ cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
diff --git a/drivers/s390/block/scm_blk.h b/drivers/s390/block/scm_blk.h
index 7ac6bad919ef..3c1ccf494647 100644
--- a/drivers/s390/block/scm_blk.h
+++ b/drivers/s390/block/scm_blk.h
@@ -68,19 +68,34 @@ void scm_initiate_cluster_request(struct scm_request *);
void scm_cluster_request_irq(struct scm_request *);
bool scm_test_cluster_request(struct scm_request *);
bool scm_cluster_size_valid(void);
-#else
-#define __scm_free_rq_cluster(scmrq) {}
-#define __scm_alloc_rq_cluster(scmrq) 0
-#define scm_request_cluster_init(scmrq) {}
-#define scm_reserve_cluster(scmrq) true
-#define scm_release_cluster(scmrq) {}
-#define scm_blk_dev_cluster_setup(bdev) {}
-#define scm_need_cluster_request(scmrq) false
-#define scm_initiate_cluster_request(scmrq) {}
-#define scm_cluster_request_irq(scmrq) {}
-#define scm_test_cluster_request(scmrq) false
-#define scm_cluster_size_valid() true
-#endif
+#else /* CONFIG_SCM_BLOCK_CLUSTER_WRITE */
+static inline void __scm_free_rq_cluster(struct scm_request *scmrq) {}
+static inline int __scm_alloc_rq_cluster(struct scm_request *scmrq)
+{
+ return 0;
+}
+static inline void scm_request_cluster_init(struct scm_request *scmrq) {}
+static inline bool scm_reserve_cluster(struct scm_request *scmrq)
+{
+ return true;
+}
+static inline void scm_release_cluster(struct scm_request *scmrq) {}
+static inline void scm_blk_dev_cluster_setup(struct scm_blk_dev *bdev) {}
+static inline bool scm_need_cluster_request(struct scm_request *scmrq)
+{
+ return false;
+}
+static inline void scm_initiate_cluster_request(struct scm_request *scmrq) {}
+static inline void scm_cluster_request_irq(struct scm_request *scmrq) {}
+static inline bool scm_test_cluster_request(struct scm_request *scmrq)
+{
+ return false;
+}
+static inline bool scm_cluster_size_valid(void)
+{
+ return true;
+}
+#endif /* CONFIG_SCM_BLOCK_CLUSTER_WRITE */
extern debug_info_t *scm_debug;
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 911704571b9c..230697aac94b 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -443,7 +443,7 @@ fs3270_open(struct inode *inode, struct file *filp)
tty_kref_put(tty);
return -ENODEV;
}
- minor = tty->index + RAW3270_FIRSTMINOR;
+ minor = tty->index;
tty_kref_put(tty);
}
mutex_lock(&fs3270_mutex);
@@ -524,6 +524,25 @@ static const struct file_operations fs3270_fops = {
.llseek = no_llseek,
};
+void fs3270_create_cb(int minor)
+{
+ __register_chrdev(IBM_FS3270_MAJOR, minor, 1, "tub", &fs3270_fops);
+ device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, minor),
+ NULL, "3270/tub%d", minor);
+}
+
+void fs3270_destroy_cb(int minor)
+{
+ device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, minor));
+ __unregister_chrdev(IBM_FS3270_MAJOR, minor, 1, "tub");
+}
+
+struct raw3270_notifier fs3270_notifier =
+{
+ .create = fs3270_create_cb,
+ .destroy = fs3270_destroy_cb,
+};
+
/*
* 3270 fullscreen driver initialization.
*/
@@ -532,16 +551,20 @@ fs3270_init(void)
{
int rc;
- rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
+ rc = __register_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270", &fs3270_fops);
if (rc)
return rc;
+ device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, 0),
+ NULL, "3270/tub");
+ raw3270_register_notifier(&fs3270_notifier);
return 0;
}
static void __exit
fs3270_exit(void)
{
- unregister_chrdev(IBM_FS3270_MAJOR, "fs3270");
+ raw3270_unregister_notifier(&fs3270_notifier);
+ __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270");
}
MODULE_LICENSE("GPL");
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 9a6c140c5f07..4c9030a5b9f2 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -28,7 +28,7 @@
#include <linux/device.h>
#include <linux/mutex.h>
-static struct class *class3270;
+struct class *class3270;
/* The main 3270 data structure. */
struct raw3270 {
@@ -37,6 +37,7 @@ struct raw3270 {
int minor;
short model, rows, cols;
+ unsigned int state;
unsigned long flags;
struct list_head req_queue; /* Request queue. */
@@ -46,20 +47,26 @@ struct raw3270 {
struct timer_list timer; /* Device timer. */
unsigned char *ascebc; /* ascii -> ebcdic table */
- struct device *clttydev; /* 3270-class tty device ptr */
- struct device *cltubdev; /* 3270-class tub device ptr */
- struct raw3270_request init_request;
+ struct raw3270_view init_view;
+ struct raw3270_request init_reset;
+ struct raw3270_request init_readpart;
+ struct raw3270_request init_readmod;
unsigned char init_data[256];
};
+/* raw3270->state */
+#define RAW3270_STATE_INIT 0 /* Initial state */
+#define RAW3270_STATE_RESET 1 /* Reset command is pending */
+#define RAW3270_STATE_W4ATTN 2 /* Wait for attention interrupt */
+#define RAW3270_STATE_READMOD 3 /* Read partition is pending */
+#define RAW3270_STATE_READY 4 /* Device is usable by views */
+
/* raw3270->flags */
#define RAW3270_FLAGS_14BITADDR 0 /* 14-bit buffer addresses */
#define RAW3270_FLAGS_BUSY 1 /* Device busy, leave it alone */
-#define RAW3270_FLAGS_ATTN 2 /* Device sent an ATTN interrupt */
-#define RAW3270_FLAGS_READY 4 /* Device is useable by views */
-#define RAW3270_FLAGS_CONSOLE 8 /* Device is the console. */
-#define RAW3270_FLAGS_FROZEN 16 /* set if 3270 is frozen for suspend */
+#define RAW3270_FLAGS_CONSOLE 2 /* Device is the console. */
+#define RAW3270_FLAGS_FROZEN 3 /* set if 3270 is frozen for suspend */
/* Semaphore to protect global data of raw3270 (devices, views, etc). */
static DEFINE_MUTEX(raw3270_mutex);
@@ -97,6 +104,17 @@ static unsigned char raw3270_ebcgraf[64] = {
0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
};
+static inline int raw3270_state_ready(struct raw3270 *rp)
+{
+ return rp->state == RAW3270_STATE_READY;
+}
+
+static inline int raw3270_state_final(struct raw3270 *rp)
+{
+ return rp->state == RAW3270_STATE_INIT ||
+ rp->state == RAW3270_STATE_READY;
+}
+
void
raw3270_buffer_address(struct raw3270 *rp, char *cp, unsigned short addr)
{
@@ -214,7 +232,7 @@ raw3270_request_set_idal(struct raw3270_request *rq, struct idal_buffer *ib)
* Stop running ccw.
*/
static int
-raw3270_halt_io_nolock(struct raw3270 *rp, struct raw3270_request *rq)
+__raw3270_halt_io(struct raw3270 *rp, struct raw3270_request *rq)
{
int retries;
int rc;
@@ -233,18 +251,6 @@ raw3270_halt_io_nolock(struct raw3270 *rp, struct raw3270_request *rq)
return rc;
}
-static int
-raw3270_halt_io(struct raw3270 *rp, struct raw3270_request *rq)
-{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
- rc = raw3270_halt_io_nolock(rp, rq);
- spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
- return rc;
-}
-
/*
* Add the request to the request queue, try to start it if the
* 3270 device is idle. Return without waiting for end of i/o.
@@ -281,8 +287,8 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
if (!rp || rp->view != view ||
test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
rc = -EACCES;
- else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
- rc = -ENODEV;
+ else if (!raw3270_state_ready(rp))
+ rc = -EBUSY;
else
rc = __raw3270_start(rp, view, rq);
spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
@@ -299,8 +305,8 @@ raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
if (!rp || rp->view != view ||
test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
rc = -EACCES;
- else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
- rc = -ENODEV;
+ else if (!raw3270_state_ready(rp))
+ rc = -EBUSY;
else
rc = __raw3270_start(rp, view, rq);
return rc;
@@ -378,7 +384,7 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
case RAW3270_IO_STOP:
if (!rq)
break;
- raw3270_halt_io_nolock(rp, rq);
+ __raw3270_halt_io(rp, rq);
rq->rc = -EIO;
break;
default:
@@ -413,9 +419,14 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
/*
- * Size sensing.
+ * To determine the size of the 3270 device we need to do:
+ * 1) send a 'read partition' data stream to the device
+ * 2) wait for the attn interrupt that precedes the query reply
+ * 3) do a read modified to get the query reply
+ * To make things worse we have to cope with intervention
+ * required (3270 device switched to 'stand-by') and command
+ * rejects (old devices that can't do 'read partition').
*/
-
struct raw3270_ua { /* Query Reply structure for Usable Area */
struct { /* Usable Area Query Reply Base */
short l; /* Length of this structured field */
@@ -451,117 +462,21 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */
} __attribute__ ((packed)) aua;
} __attribute__ ((packed));
-static struct diag210 raw3270_init_diag210;
-static DEFINE_MUTEX(raw3270_init_mutex);
-
-static int
-raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
- struct irb *irb)
-{
- /*
- * Unit-Check Processing:
- * Expect Command Reject or Intervention Required.
- */
- if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
- /* Request finished abnormally. */
- if (irb->ecw[0] & SNS0_INTERVENTION_REQ) {
- set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags);
- return RAW3270_IO_BUSY;
- }
- }
- if (rq) {
- if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
- if (irb->ecw[0] & SNS0_CMD_REJECT)
- rq->rc = -EOPNOTSUPP;
- else
- rq->rc = -EIO;
- } else
- /* Request finished normally. Copy residual count. */
- rq->rescnt = irb->scsw.cmd.count;
- }
- if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
- set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags);
- wake_up(&raw3270_wait_queue);
- }
- return RAW3270_IO_DONE;
-}
-
-static struct raw3270_fn raw3270_init_fn = {
- .intv = raw3270_init_irq
-};
-
-static struct raw3270_view raw3270_init_view = {
- .fn = &raw3270_init_fn
-};
-
-/*
- * raw3270_wait/raw3270_wait_interruptible/__raw3270_wakeup
- * Wait for end of request. The request must have been started
- * with raw3270_start, rc = 0. The device lock may NOT have been
- * released between calling raw3270_start and raw3270_wait.
- */
static void
-raw3270_wake_init(struct raw3270_request *rq, void *data)
-{
- wake_up((wait_queue_head_t *) data);
-}
-
-/*
- * Special wait function that can cope with console initialization.
- */
-static int
-raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
- struct raw3270_request *rq)
-{
- unsigned long flags;
- int rc;
-
-#ifdef CONFIG_TN3270_CONSOLE
- if (raw3270_registered == 0) {
- spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
- rq->callback = NULL;
- rc = __raw3270_start(rp, view, rq);
- if (rc == 0)
- while (!raw3270_request_final(rq)) {
- wait_cons_dev();
- barrier();
- }
- spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
- return rq->rc;
- }
-#endif
- rq->callback = raw3270_wake_init;
- rq->callback_data = &raw3270_wait_queue;
- spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
- rc = __raw3270_start(rp, view, rq);
- spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
- if (rc)
- return rc;
- /* Now wait for the completion. */
- rc = wait_event_interruptible(raw3270_wait_queue,
- raw3270_request_final(rq));
- if (rc == -ERESTARTSYS) { /* Interrupted by a signal. */
- raw3270_halt_io(view->dev, rq);
- /* No wait for the halt to complete. */
- wait_event(raw3270_wait_queue, raw3270_request_final(rq));
- return -ERESTARTSYS;
- }
- return rq->rc;
-}
-
-static int
-__raw3270_size_device_vm(struct raw3270 *rp)
+raw3270_size_device_vm(struct raw3270 *rp)
{
int rc, model;
struct ccw_dev_id dev_id;
+ struct diag210 diag_data;
ccw_device_get_id(rp->cdev, &dev_id);
- raw3270_init_diag210.vrdcdvno = dev_id.devno;
- raw3270_init_diag210.vrdclen = sizeof(struct diag210);
- rc = diag210(&raw3270_init_diag210);
- if (rc)
- return rc;
- model = raw3270_init_diag210.vrdccrmd;