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 ...
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bootmem.h>
|
||||
@@ -80,6 +81,8 @@ struct tty3270 {
|
||||
unsigned int highlight; /* Blink/reverse/underscore */
|
||||
unsigned int f_color; /* Foreground color */
|
||||
struct tty3270_line *screen;
|
||||
unsigned int n_model, n_cols, n_rows; /* New model & size */
|
||||
struct work_struct resize_work;
|
||||
|
||||
/* Input stuff. */
|
||||
struct string *prompt; /* Output string for input area. */
|
||||
@@ -115,6 +118,7 @@ struct tty3270 {
|
||||
#define TTY_UPDATE_ALL 16 /* Recreate screen. */
|
||||
|
||||
static void tty3270_update(struct tty3270 *);
|
||||
static void tty3270_resize_work(struct work_struct *work);
|
||||
|
||||
/*
|
||||
* Setup timeout for a device. On timeout trigger an update.
|
||||
@@ -683,12 +687,6 @@ tty3270_alloc_view(void)
|
||||
INIT_LIST_HEAD(&tp->update);
|
||||
INIT_LIST_HEAD(&tp->rcl_lines);
|
||||
tp->rcl_max = 20;
|
||||
tty_port_init(&tp->port);
|
||||
setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
|
||||
(unsigned long) tp);
|
||||
tasklet_init(&tp->readlet,
|
||||
(void (*)(unsigned long)) tty3270_read_tasklet,
|
||||
(unsigned long) tp->read);
|
||||
|
||||
for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
|
||||
tp->freemem_pages[pages] = (void *)
|
||||
@@ -710,6 +708,15 @@ tty3270_alloc_view(void)
|
||||
tp->kbd = kbd_alloc();
|
||||
if (!tp->kbd)
|
||||
goto out_reset;
|
||||
|
||||
tty_port_init(&tp->port);
|
||||
setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
|
||||
(unsigned long) tp);
|
||||
tasklet_init(&tp->readlet,
|
||||
(void (*)(unsigned long)) tty3270_read_tasklet,
|
||||
(unsigned long) tp->read);
|
||||
INIT_WORK(&tp->resize_work, tty3270_resize_work);
|
||||
|
||||
return tp;
|
||||
|
||||
out_reset:
|
||||
@@ -752,42 +759,96 @@ tty3270_free_view(struct tty3270 *tp)
|
||||
/*
|
||||
* Allocate tty3270 screen.
|
||||
*/
|
||||
static int
|
||||
tty3270_alloc_screen(struct tty3270 *tp)
|
||||
static struct tty3270_line *
|
||||
tty3270_alloc_screen(unsigned int rows, unsigned int cols)
|
||||
{
|
||||
struct tty3270_line *screen;
|
||||
unsigned long size;
|
||||
int lines;
|
||||
|
||||
size = sizeof(struct tty3270_line) * (tp->view.rows - 2);
|
||||
tp->screen = kzalloc(size, GFP_KERNEL);
|
||||
if (!tp->screen)
|
||||
size = sizeof(struct tty3270_line) * (rows - 2);
|
||||
screen = kzalloc(size, GFP_KERNEL);
|
||||
if (!screen)
|
||||
goto out_err;
|
||||
for (lines = 0; lines < tp->view.rows - 2; lines++) {
|
||||
size = sizeof(struct tty3270_cell) * tp->view.cols;
|
||||
tp->screen[lines].cells = kzalloc(size, GFP_KERNEL);
|
||||
if (!tp->screen[lines].cells)
|
||||
for (lines = 0; lines < rows - 2; lines++) {
|
||||
size = sizeof(struct tty3270_cell) * cols;
|
||||
screen[lines].cells = kzalloc(size, GFP_KERNEL);
|
||||
if (!screen[lines].cells)
|
||||
goto out_screen;
|
||||
}
|
||||
return 0;
|
||||
return screen;
|
||||
out_screen:
|
||||
while (lines--)
|
||||
kfree(tp->screen[lines].cells);
|
||||
kfree(tp->screen);
|
||||
kfree(screen[lines].cells);
|
||||
kfree(screen);
|
||||
out_err:
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tty3270 screen.
|
||||
*/
|
||||
static void
|
||||
tty3270_free_screen(struct tty3270 *tp)
|
||||
tty3270_free_screen(struct tty3270_line *screen, unsigned int rows)
|
||||
{
|
||||
int lines;
|
||||
|
||||
for (lines = 0; lines < tp->view.rows - 2; lines++)
|
||||
kfree(tp->screen[lines].cells);
|
||||
kfree(tp->screen);
|
||||
for (lines = 0; lines < rows - 2; lines++)
|
||||
kfree(screen[lines].cells);
|
||||
kfree(screen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize tty3270 screen
|
||||
*/
|
||||
static void tty3270_resize_work(struct work_struct *work)
|
||||
{
|
||||
struct tty3270 *tp = container_of(work, struct tty3270, resize_work);
|
||||
struct tty3270_line *screen, *oscreen;
|
||||
struct tty_struct *tty;
|
||||
unsigned int orows;
|
||||
struct winsize ws;
|
||||
|
||||
screen = tty3270_alloc_screen(tp->n_rows, tp->n_cols);
|
||||
if (!screen)
|
||||
return;
|
||||
/* Switch to new output size */
|
||||
spin_lock_bh(&tp->view.lock);
|
||||
oscreen = tp->screen;
|
||||
orows = tp->view.rows;
|
||||
tp->view.model = tp->n_model;
|
||||
tp->view.rows = tp->n_rows;
|
||||
tp->view.cols = tp->n_cols;
|
||||
tp->screen = screen;
|
||||
free_string(&tp->freemem, tp->prompt);
|
||||
free_string(&tp->freemem, tp->status);
|
||||
tty3270_create_prompt(tp);
|
||||
tty3270_create_status(tp);
|
||||
tp->nr_up = 0;
|
||||
while (tp->nr_lines < tp->view.rows - 2)
|
||||
tty3270_blank_line(tp);
|
||||
tp->update_flags = TTY_UPDATE_ALL;
|
||||
spin_unlock_bh(&tp->view.lock);
|
||||
tty3270_free_screen(oscreen, orows);
|
||||
tty3270_set_timer(tp, 1);
|
||||
/* Informat tty layer about new size */
|
||||
tty = tty_port_tty_get(&tp->port);
|
||||
if (!tty)
|
||||
return;
|
||||
ws.ws_row = tp->view.rows - 2;
|
||||
ws.ws_col = tp->view.cols;
|
||||
tty_do_resize(tty, &ws);
|
||||
}
|
||||
|
||||
static void
|
||||
tty3270_resize(struct raw3270_view *view, int model, int rows, int cols)
|
||||
{
|
||||
struct tty3270 *tp = container_of(view, struct tty3270, view);
|
||||
|
||||
tp->n_model = model;
|
||||
tp->n_rows = rows;
|
||||
tp->n_cols = cols;
|
||||
schedule_work(&tp->resize_work);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -815,7 +876,8 @@ static void
|
||||
tty3270_free(struct raw3270_view *view)
|
||||
{
|
||||
struct tty3270 *tp = container_of(view, struct tty3270, view);
|
||||
tty3270_free_screen(tp);
|
||||
|
||||
tty3270_free_screen(tp->screen, tp->view.rows);
|
||||
tty3270_free_view(tp);
|
||||
}
|
||||
|
||||
@@ -827,9 +889,8 @@ tty3270_del_views(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tty3270_max_index; i++) {
|
||||
struct raw3270_view *view =
|
||||
raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
|
||||
for (i = RAW3270_FIRSTMINOR; i <= tty3270_max_index; i++) {
|
||||
struct raw3270_view *view = raw3270_find_view(&tty3270_fn, i);
|
||||
if (!IS_ERR(view))
|
||||
raw3270_del_view(view);
|
||||
}
|
||||
@@ -840,7 +901,8 @@ static struct raw3270_fn tty3270_fn = {
|
||||
.deactivate = tty3270_deactivate,
|
||||
.intv = (void *) tty3270_irq,
|
||||
.release = tty3270_release,
|
||||
.free = tty3270_free
|
||||
.free = tty3270_free,
|
||||
.resize = tty3270_resize
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -853,8 +915,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
int i, rc;
|
||||
|
||||
/* Check if the tty3270 is already there. */
|
||||
view = raw3270_find_view(&tty3270_fn,
|
||||
tty->index + RAW3270_FIRSTMINOR);
|
||||
view = raw3270_find_view(&tty3270_fn, tty->index);
|
||||
if (!IS_ERR(view)) {
|
||||
tp = container_of(view, struct tty3270, view);
|
||||
tty->driver_data = tp;
|
||||
@@ -866,29 +927,26 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
tp->inattr = TF_INPUT;
|
||||
return tty_port_install(&tp->port, driver, tty);
|
||||
}
|
||||
if (tty3270_max_index < tty->index + 1)
|
||||
tty3270_max_index = tty->index + 1;
|
||||
|
||||
/* Quick exit if there is no device for tty->index. */
|
||||
if (PTR_ERR(view) == -ENODEV)
|
||||
return -ENODEV;
|
||||
if (tty3270_max_index < tty->index)
|
||||
tty3270_max_index = tty->index;
|
||||
|
||||
/* Allocate tty3270 structure on first open. */
|
||||
tp = tty3270_alloc_view();
|
||||
if (IS_ERR(tp))
|
||||
return PTR_ERR(tp);
|
||||
|
||||
rc = raw3270_add_view(&tp->view, &tty3270_fn,
|
||||
tty->index + RAW3270_FIRSTMINOR);
|
||||
rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
|
||||
if (rc) {
|
||||
tty3270_free_view(tp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = tty3270_alloc_screen(tp);
|
||||
if (rc) {
|
||||
tp->screen = tty3270_alloc_screen(tp->view.cols, tp->view.rows);
|
||||
if (IS_ERR(tp->screen)) {
|
||||
rc = PTR_ERR(tp->screen);
|
||||
raw3270_put_view(&tp->view);
|
||||
raw3270_del_view(&tp->view);
|
||||
tty3270_free_view(tp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -925,6 +983,20 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called whenever a 3270 tty is opened.
|
||||
*/
|
||||
static int
|
||||
tty3270_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct tty3270 *tp = tty->driver_data;
|
||||
struct tty_port *port = &tp->port;
|
||||
|
||||
port->count++;
|
||||
tty_port_tty_set(port, tty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called when the 3270 tty is closed. We wait
|
||||
* for the remaining request to be completed. Then we clean up.
|
||||
@@ -1753,6 +1825,7 @@ static long tty3270_compat_ioctl(struct tty_struct *tty,
|
||||
static const struct tty_operations tty3270_ops = {
|
||||
.install = tty3270_install,
|
||||
.cleanup = tty3270_cleanup,
|
||||
.open = tty3270_open,
|
||||
.close = tty3270_close,
|
||||
.write = tty3270_write,
|
||||
.put_char = tty3270_put_char,
|
||||
@@ -1771,6 +1844,22 @@ static const struct tty_operations tty3270_ops = {
|
||||
.set_termios = tty3270_set_termios
|
||||
};
|
||||
|
||||
void tty3270_create_cb(int minor)
|
||||
{
|
||||
tty_register_device(tty3270_driver, minor, NULL);
|
||||
}
|
||||
|
||||
void tty3270_destroy_cb(int minor)
|
||||
{
|
||||
tty_unregister_device(tty3270_driver, minor);
|
||||
}
|
||||
|
||||
struct raw3270_notifier tty3270_notifier =
|
||||
{
|
||||
.create = tty3270_create_cb,
|
||||
.destroy = tty3270_destroy_cb,
|
||||
};
|
||||
|
||||
/*
|
||||
* 3270 tty registration code called from tty_init().
|
||||
* Most kernel services (incl. kmalloc) are available at this poimt.
|
||||
@@ -1780,23 +1869,25 @@ static int __init tty3270_init(void)
|
||||
struct tty_driver *driver;
|
||||
int ret;
|
||||
|
||||
driver = alloc_tty_driver(RAW3270_MAXDEVS);
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
driver = tty_alloc_driver(RAW3270_MAXDEVS,
|
||||
TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV |
|
||||
TTY_DRIVER_RESET_TERMIOS);
|
||||
if (IS_ERR(driver))
|
||||
return PTR_ERR(driver);
|
||||
|
||||
/*
|
||||
* Initialize the tty_driver structure
|
||||
* Entries in tty3270_driver that are NOT initialized:
|
||||
* proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
|
||||
*/
|
||||
driver->driver_name = "ttyTUB";
|
||||
driver->name = "ttyTUB";
|
||||
driver->driver_name = "tty3270";
|
||||
driver->name = "3270/tty";
|
||||
driver->major = IBM_TTY3270_MAJOR;
|
||||
driver->minor_start = RAW3270_FIRSTMINOR;
|
||||
driver->minor_start = 0;
|
||||
driver->type = TTY_DRIVER_TYPE_SYSTEM;
|
||||
driver->subtype = SYSTEM_TYPE_TTY;
|
||||
driver->init_termios = tty_std_termios;
|
||||
driver->flags = TTY_DRIVER_RESET_TERMIOS;
|
||||
tty_set_operations(driver, &tty3270_ops);
|
||||
ret = tty_register_driver(driver);
|
||||
if (ret) {
|
||||
@@ -1804,6 +1895,7 @@ static int __init tty3270_init(void)
|
||||
return ret;
|
||||
}
|
||||
tty3270_driver = driver;
|
||||
raw3270_register_notifier(&tty3270_notifier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1812,6 +1904,7 @@ tty3270_exit(void)
|
||||
{
|
||||
struct tty_driver *driver;
|
||||
|
||||
raw3270_unregister_notifier(&tty3270_notifier);
|
||||
driver = tty3270_driver;
|
||||
tty3270_driver = NULL;
|
||||
tty_unregister_driver(driver);
|
||||
|
Reference in New Issue
Block a user