Commit ba3f8ae2 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: sclp driver.

Add error recovery for sclp failures. Fix endless loop in sclp_process_evbufs.
parent a50082c6
......@@ -2,7 +2,7 @@
# S/390 character devices
#
export-objs := sclp_rw.o tape_core.o tape_devmap.o tape_std.o
export-objs := sclp.o tape_core.o tape_devmap.o tape_std.o
tub3270-objs := tuball.o tubfs.o tubtty.o \
tubttyaid.o tubttybld.o tubttyscl.o \
......@@ -10,8 +10,8 @@ tub3270-objs := tuball.o tubfs.o tubtty.o \
obj-y += ctrlchar.o
obj-$(CONFIG_TN3215) += con3215.o
obj-$(CONFIG_SCLP) += sclp.o
obj-$(CONFIG_SCLP_TTY) += sclp_rw.o sclp_tty.o
obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o
obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
obj-$(CONFIG_TN3270) += tub3270.o
......
This diff is collapsed.
......@@ -45,10 +45,6 @@
#define LnTpFlgs_EndText 0x1000
#define LnTpFlgs_PromptText 0x0800
#define SCLP_COMMAND_INITIATED 0
#define SCLP_BUSY 2
#define SCLP_NOT_OPERATIONAL 3
typedef unsigned int sclp_cmdw_t;
#define SCLP_CMDW_READDATA 0x00770005
......@@ -129,6 +125,7 @@ void sclp_add_request(struct sclp_req *req);
void sclp_sync_wait(void);
int sclp_register(struct sclp_register *reg);
void sclp_unregister(struct sclp_register *reg);
char *sclp_error_message(u16 response_code);
/* useful inlines */
......
......@@ -51,13 +51,14 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
struct sclp_buffer *next;
void *page;
/* FIXME: what if rc != 0x0020 */
/* Ignore return code - because console-writes aren't critical,
we do without a sophisticated error recovery mechanism. */
page = sclp_unmake_buffer(buffer);
spin_lock_irqsave(&sclp_con_lock, flags);
list_add_tail((struct list_head *) page, &sclp_con_pages);
sclp_con_buffer_count--;
/* Remove buffer from outqueue */
list_del(&buffer->list);
sclp_con_buffer_count--;
list_add_tail((struct list_head *) page, &sclp_con_pages);
/* Check if there is a pending buffer on the out queue. */
next = NULL;
if (!list_empty(&sclp_con_outqueue))
......@@ -104,7 +105,7 @@ sclp_console_write(struct console *console, const char *message,
void *page;
int written;
if (count <= 0)
if (count == 0)
return;
spin_lock_irqsave(&sclp_con_lock, flags);
/*
......@@ -125,7 +126,8 @@ sclp_console_write(struct console *console, const char *message,
sclp_con_width_htab);
}
/* try to write the string to the current output buffer */
written = sclp_write(sclp_conbuf, message, count, 0);
written = sclp_write(sclp_conbuf, (const unsigned char *)
message, count, 0);
if (written == -EFAULT || written == count)
break;
/*
......@@ -232,6 +234,6 @@ sclp_console_init(void)
sclp_con_columns = 80;
sclp_con_width_htab = 8;
/* enable printks access to this driver */
/* enable printk-access to this driver */
register_console(&sclp_console);
}
......@@ -130,7 +130,7 @@ cpi_prepare_req(void)
req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
if (req == NULL)
return ERR_PTR(-ENOMEM);
sccb = (struct cpi_sccb *) get_free_page(GFP_KERNEL);
sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL);
if (sccb == NULL) {
kfree(req);
return ERR_PTR(-ENOMEM);
......@@ -227,6 +227,7 @@ cpi_module_init(void)
rc = 0;
cpi_free_req(req);
sclp_unregister(&sclp_cpi_event);
return rc;
}
......
This diff is collapsed.
......@@ -11,6 +11,9 @@
#ifndef __SCLP_RW_H__
#define __SCLP_RW_H__
#include <linux/list.h>
#include <linux/timer.h>
struct mto {
u16 length;
u16 type;
......@@ -70,6 +73,8 @@ struct sclp_buffer {
struct write_sccb *sccb;
char *current_line;
int current_length;
int retry_count;
struct timer_list retry_timer;
/* output format settings */
unsigned short columns;
unsigned short htab;
......@@ -84,8 +89,7 @@ int sclp_rw_init(void);
struct sclp_buffer *sclp_make_buffer(void *, unsigned short, unsigned short);
void *sclp_unmake_buffer(struct sclp_buffer *);
int sclp_buffer_space(struct sclp_buffer *);
int sclp_write(struct sclp_buffer *buffer, const char *, int, int);
void sclp_move_current_line(struct sclp_buffer *, struct sclp_buffer *);
int sclp_write(struct sclp_buffer *buffer, const unsigned char *, int, int);
void sclp_emit_buffer(struct sclp_buffer *,void (*)(struct sclp_buffer *,int));
void sclp_set_columns(struct sclp_buffer *, unsigned short);
void sclp_set_htab(struct sclp_buffer *, unsigned short);
......
......@@ -32,7 +32,7 @@
#define SCLP_TTY_BUF_SIZE 512
/*
* There is excatly one SCLP terminal, so we can keep things simple
* There is exactly one SCLP terminal, so we can keep things simple
* and allocate all variables statically.
*/
......@@ -265,13 +265,14 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
struct sclp_buffer *next;
void *page;
/* FIXME: what if rc != 0x0020 */
/* Ignore return code - because tty-writes aren't critical,
we do without a sophisticated error recovery mechanism. */
page = sclp_unmake_buffer(buffer);
spin_lock_irqsave(&sclp_tty_lock, flags);
list_add_tail((struct list_head *) page, &sclp_tty_pages);
sclp_tty_buffer_count--;
/* Remove buffer from outqueue */
list_del(&buffer->list);
sclp_tty_buffer_count--;
list_add_tail((struct list_head *) page, &sclp_tty_pages);
/* Check if there is a pending buffer on the out queue. */
next = NULL;
if (!list_empty(&sclp_tty_outqueue))
......@@ -489,8 +490,8 @@ void sclp_tty_input(unsigned char* buf, unsigned int count)
/* send (normal) input to line discipline */
memcpy(sclp_tty->flip.char_buf_ptr, buf, count);
if (count < 2 ||
strncmp (buf + count - 2, "^n", 2) ||
strncmp (buf + count - 2, "\0252n", 2)) {
strncmp ((const char *) buf + count - 2, "^n", 2) ||
strncmp ((const char *) buf + count - 2, "\0252n", 2)) {
sclp_tty->flip.char_buf_ptr[count] = '\n';
count++;
} else
......@@ -558,7 +559,7 @@ sclp_switch_cases(unsigned char *buf, int count,
}
static void
sclp_get_input(char *start, char *end)
sclp_get_input(unsigned char *start, unsigned char *end)
{
int count;
......@@ -572,7 +573,7 @@ sclp_get_input(char *start, char *end)
/*
* if set in ioctl find out characters in lower or upper case
* (depends on current case) seperated by a special character,
* (depends on current case) separated by a special character,
* works on EBCDIC
*/
if (sclp_ioctls.delim)
......@@ -625,8 +626,8 @@ sclp_eval_selfdeftextmsg(struct gds_subvector *start,
subvec = find_gds_subvector(subvec, end, 0x30);
if (!subvec)
break;
sclp_get_input((void *)(subvec + 1),
(void *) subvec + subvec->length);
sclp_get_input((unsigned char *)(subvec + 1),
(unsigned char *) subvec + subvec->length);
(void *) subvec += subvec->length;
}
}
......
......@@ -18,9 +18,9 @@ struct sclp_ioctls {
unsigned short htab;
unsigned char echo;
unsigned short columns;
signed char final_nl;
unsigned char final_nl;
unsigned short max_sccb;
unsigned short kmem_sccb; /* cant be modified at run time */
unsigned short kmem_sccb; /* can't be modified at run time */
unsigned char tolower;
unsigned char delim;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment