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 @@ ...@@ -2,7 +2,7 @@
# S/390 character devices # 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 \ tub3270-objs := tuball.o tubfs.o tubtty.o \
tubttyaid.o tubttybld.o tubttyscl.o \ tubttyaid.o tubttybld.o tubttyscl.o \
...@@ -10,8 +10,8 @@ tub3270-objs := tuball.o tubfs.o tubtty.o \ ...@@ -10,8 +10,8 @@ tub3270-objs := tuball.o tubfs.o tubtty.o \
obj-y += ctrlchar.o obj-y += ctrlchar.o
obj-$(CONFIG_TN3215) += con3215.o obj-$(CONFIG_TN3215) += con3215.o
obj-$(CONFIG_SCLP) += sclp.o obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o
obj-$(CONFIG_SCLP_TTY) += sclp_rw.o sclp_tty.o obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
obj-$(CONFIG_TN3270) += tub3270.o obj-$(CONFIG_TN3270) += tub3270.o
......
This diff is collapsed.
...@@ -45,10 +45,6 @@ ...@@ -45,10 +45,6 @@
#define LnTpFlgs_EndText 0x1000 #define LnTpFlgs_EndText 0x1000
#define LnTpFlgs_PromptText 0x0800 #define LnTpFlgs_PromptText 0x0800
#define SCLP_COMMAND_INITIATED 0
#define SCLP_BUSY 2
#define SCLP_NOT_OPERATIONAL 3
typedef unsigned int sclp_cmdw_t; typedef unsigned int sclp_cmdw_t;
#define SCLP_CMDW_READDATA 0x00770005 #define SCLP_CMDW_READDATA 0x00770005
...@@ -129,6 +125,7 @@ void sclp_add_request(struct sclp_req *req); ...@@ -129,6 +125,7 @@ void sclp_add_request(struct sclp_req *req);
void sclp_sync_wait(void); void sclp_sync_wait(void);
int sclp_register(struct sclp_register *reg); int sclp_register(struct sclp_register *reg);
void sclp_unregister(struct sclp_register *reg); void sclp_unregister(struct sclp_register *reg);
char *sclp_error_message(u16 response_code);
/* useful inlines */ /* useful inlines */
......
...@@ -51,13 +51,14 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) ...@@ -51,13 +51,14 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
struct sclp_buffer *next; struct sclp_buffer *next;
void *page; 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); page = sclp_unmake_buffer(buffer);
spin_lock_irqsave(&sclp_con_lock, flags); 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 */ /* Remove buffer from outqueue */
list_del(&buffer->list); 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. */ /* Check if there is a pending buffer on the out queue. */
next = NULL; next = NULL;
if (!list_empty(&sclp_con_outqueue)) if (!list_empty(&sclp_con_outqueue))
...@@ -104,7 +105,7 @@ sclp_console_write(struct console *console, const char *message, ...@@ -104,7 +105,7 @@ sclp_console_write(struct console *console, const char *message,
void *page; void *page;
int written; int written;
if (count <= 0) if (count == 0)
return; return;
spin_lock_irqsave(&sclp_con_lock, flags); spin_lock_irqsave(&sclp_con_lock, flags);
/* /*
...@@ -125,7 +126,8 @@ sclp_console_write(struct console *console, const char *message, ...@@ -125,7 +126,8 @@ sclp_console_write(struct console *console, const char *message,
sclp_con_width_htab); sclp_con_width_htab);
} }
/* try to write the string to the current output buffer */ /* 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) if (written == -EFAULT || written == count)
break; break;
/* /*
...@@ -232,6 +234,6 @@ sclp_console_init(void) ...@@ -232,6 +234,6 @@ sclp_console_init(void)
sclp_con_columns = 80; sclp_con_columns = 80;
sclp_con_width_htab = 8; sclp_con_width_htab = 8;
/* enable printks access to this driver */ /* enable printk-access to this driver */
register_console(&sclp_console); register_console(&sclp_console);
} }
...@@ -130,7 +130,7 @@ cpi_prepare_req(void) ...@@ -130,7 +130,7 @@ cpi_prepare_req(void)
req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL); req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
if (req == NULL) if (req == NULL)
return ERR_PTR(-ENOMEM); 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) { if (sccb == NULL) {
kfree(req); kfree(req);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -227,6 +227,7 @@ cpi_module_init(void) ...@@ -227,6 +227,7 @@ cpi_module_init(void)
rc = 0; rc = 0;
cpi_free_req(req); cpi_free_req(req);
sclp_unregister(&sclp_cpi_event);
return rc; return rc;
} }
......
This diff is collapsed.
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#ifndef __SCLP_RW_H__ #ifndef __SCLP_RW_H__
#define __SCLP_RW_H__ #define __SCLP_RW_H__
#include <linux/list.h>
#include <linux/timer.h>
struct mto { struct mto {
u16 length; u16 length;
u16 type; u16 type;
...@@ -70,6 +73,8 @@ struct sclp_buffer { ...@@ -70,6 +73,8 @@ struct sclp_buffer {
struct write_sccb *sccb; struct write_sccb *sccb;
char *current_line; char *current_line;
int current_length; int current_length;
int retry_count;
struct timer_list retry_timer;
/* output format settings */ /* output format settings */
unsigned short columns; unsigned short columns;
unsigned short htab; unsigned short htab;
...@@ -84,8 +89,7 @@ int sclp_rw_init(void); ...@@ -84,8 +89,7 @@ int sclp_rw_init(void);
struct sclp_buffer *sclp_make_buffer(void *, unsigned short, unsigned short); struct sclp_buffer *sclp_make_buffer(void *, unsigned short, unsigned short);
void *sclp_unmake_buffer(struct sclp_buffer *); void *sclp_unmake_buffer(struct sclp_buffer *);
int sclp_buffer_space(struct sclp_buffer *); int sclp_buffer_space(struct sclp_buffer *);
int sclp_write(struct sclp_buffer *buffer, const char *, int, int); int sclp_write(struct sclp_buffer *buffer, const unsigned char *, int, int);
void sclp_move_current_line(struct sclp_buffer *, struct sclp_buffer *);
void sclp_emit_buffer(struct sclp_buffer *,void (*)(struct sclp_buffer *,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_columns(struct sclp_buffer *, unsigned short);
void sclp_set_htab(struct sclp_buffer *, unsigned short); void sclp_set_htab(struct sclp_buffer *, unsigned short);
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#define SCLP_TTY_BUF_SIZE 512 #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. * and allocate all variables statically.
*/ */
...@@ -265,13 +265,14 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) ...@@ -265,13 +265,14 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
struct sclp_buffer *next; struct sclp_buffer *next;
void *page; 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); page = sclp_unmake_buffer(buffer);
spin_lock_irqsave(&sclp_tty_lock, flags); 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 */ /* Remove buffer from outqueue */
list_del(&buffer->list); 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. */ /* Check if there is a pending buffer on the out queue. */
next = NULL; next = NULL;
if (!list_empty(&sclp_tty_outqueue)) if (!list_empty(&sclp_tty_outqueue))
...@@ -489,8 +490,8 @@ void sclp_tty_input(unsigned char* buf, unsigned int count) ...@@ -489,8 +490,8 @@ void sclp_tty_input(unsigned char* buf, unsigned int count)
/* send (normal) input to line discipline */ /* send (normal) input to line discipline */
memcpy(sclp_tty->flip.char_buf_ptr, buf, count); memcpy(sclp_tty->flip.char_buf_ptr, buf, count);
if (count < 2 || if (count < 2 ||
strncmp (buf + count - 2, "^n", 2) || strncmp ((const char *) buf + count - 2, "^n", 2) ||
strncmp (buf + count - 2, "\0252n", 2)) { strncmp ((const char *) buf + count - 2, "\0252n", 2)) {
sclp_tty->flip.char_buf_ptr[count] = '\n'; sclp_tty->flip.char_buf_ptr[count] = '\n';
count++; count++;
} else } else
...@@ -558,7 +559,7 @@ sclp_switch_cases(unsigned char *buf, int count, ...@@ -558,7 +559,7 @@ sclp_switch_cases(unsigned char *buf, int count,
} }
static void static void
sclp_get_input(char *start, char *end) sclp_get_input(unsigned char *start, unsigned char *end)
{ {
int count; int count;
...@@ -572,7 +573,7 @@ sclp_get_input(char *start, char *end) ...@@ -572,7 +573,7 @@ sclp_get_input(char *start, char *end)
/* /*
* if set in ioctl find out characters in lower or upper case * 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 * works on EBCDIC
*/ */
if (sclp_ioctls.delim) if (sclp_ioctls.delim)
...@@ -625,8 +626,8 @@ sclp_eval_selfdeftextmsg(struct gds_subvector *start, ...@@ -625,8 +626,8 @@ sclp_eval_selfdeftextmsg(struct gds_subvector *start,
subvec = find_gds_subvector(subvec, end, 0x30); subvec = find_gds_subvector(subvec, end, 0x30);
if (!subvec) if (!subvec)
break; break;
sclp_get_input((void *)(subvec + 1), sclp_get_input((unsigned char *)(subvec + 1),
(void *) subvec + subvec->length); (unsigned char *) subvec + subvec->length);
(void *) subvec += subvec->length; (void *) subvec += subvec->length;
} }
} }
......
...@@ -18,9 +18,9 @@ struct sclp_ioctls { ...@@ -18,9 +18,9 @@ struct sclp_ioctls {
unsigned short htab; unsigned short htab;
unsigned char echo; unsigned char echo;
unsigned short columns; unsigned short columns;
signed char final_nl; unsigned char final_nl;
unsigned short max_sccb; 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 tolower;
unsigned char delim; 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