mirror of
https://github.com/torvalds/linux.git
synced 2024-12-08 20:21:34 +00:00
s390/tty3270: add support for diag 8c
The current code uses diag210 to infer the 3270 geometry from the model number when running on z/VM. This doesn't work well as almost all 3270 software clients report as 3279-2 with a custom resolution. tty3270 assumes it has a 80x24 terminal connected because of the -2 suffix. Use diag 8c to fetch the realy geometry from z/VM. Note that this doesn't allow dynamic resizing, i.e. reconnecting to a z/VM session with a different geometry. Signed-off-by: Sven Schnelle <svens@linux.ibm.com> Acked-by: Heiko Carstens <hca@linux.ibm.com> Tested-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
9603cb334a
commit
fbaee7464f
@ -12,6 +12,7 @@
|
|||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <asm/asm-extable.h>
|
#include <asm/asm-extable.h>
|
||||||
|
#include <asm/cio.h>
|
||||||
|
|
||||||
enum diag_stat_enum {
|
enum diag_stat_enum {
|
||||||
DIAG_STAT_X008,
|
DIAG_STAT_X008,
|
||||||
@ -20,6 +21,7 @@ enum diag_stat_enum {
|
|||||||
DIAG_STAT_X014,
|
DIAG_STAT_X014,
|
||||||
DIAG_STAT_X044,
|
DIAG_STAT_X044,
|
||||||
DIAG_STAT_X064,
|
DIAG_STAT_X064,
|
||||||
|
DIAG_STAT_X08C,
|
||||||
DIAG_STAT_X09C,
|
DIAG_STAT_X09C,
|
||||||
DIAG_STAT_X0DC,
|
DIAG_STAT_X0DC,
|
||||||
DIAG_STAT_X204,
|
DIAG_STAT_X204,
|
||||||
@ -83,6 +85,16 @@ struct diag210 {
|
|||||||
|
|
||||||
extern int diag210(struct diag210 *addr);
|
extern int diag210(struct diag210 *addr);
|
||||||
|
|
||||||
|
struct diag8c {
|
||||||
|
u8 flags;
|
||||||
|
u8 num_partitions;
|
||||||
|
u16 width;
|
||||||
|
u16 height;
|
||||||
|
u8 data[0];
|
||||||
|
} __packed __aligned(4);
|
||||||
|
|
||||||
|
extern int diag8c(struct diag8c *out, struct ccw_dev_id *devno);
|
||||||
|
|
||||||
/* bit is set in flags, when physical cpu info is included in diag 204 data */
|
/* bit is set in flags, when physical cpu info is included in diag 204 data */
|
||||||
#define DIAG204_LPAR_PHYS_FLG 0x80
|
#define DIAG204_LPAR_PHYS_FLG 0x80
|
||||||
#define DIAG204_LPAR_NAME_LEN 8 /* lpar name len in diag 204 data */
|
#define DIAG204_LPAR_NAME_LEN 8 /* lpar name len in diag 204 data */
|
||||||
@ -318,6 +330,7 @@ struct diag_ops {
|
|||||||
int (*diag210)(struct diag210 *addr);
|
int (*diag210)(struct diag210 *addr);
|
||||||
int (*diag26c)(void *req, void *resp, enum diag26c_sc subcode);
|
int (*diag26c)(void *req, void *resp, enum diag26c_sc subcode);
|
||||||
int (*diag14)(unsigned long rx, unsigned long ry1, unsigned long subcode);
|
int (*diag14)(unsigned long rx, unsigned long ry1, unsigned long subcode);
|
||||||
|
int (*diag8c)(struct diag8c *addr, struct ccw_dev_id *devno, size_t len);
|
||||||
void (*diag0c)(struct hypfs_diag0c_entry *entry);
|
void (*diag0c)(struct hypfs_diag0c_entry *entry);
|
||||||
void (*diag308_reset)(void);
|
void (*diag308_reset)(void);
|
||||||
};
|
};
|
||||||
@ -330,5 +343,6 @@ int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode);
|
|||||||
int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode);
|
int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode);
|
||||||
void _diag0c_amode31(struct hypfs_diag0c_entry *entry);
|
void _diag0c_amode31(struct hypfs_diag0c_entry *entry);
|
||||||
void _diag308_reset_amode31(void);
|
void _diag308_reset_amode31(void);
|
||||||
|
int _diag8c_amode31(struct diag8c *addr, struct ccw_dev_id *devno, size_t len);
|
||||||
|
|
||||||
#endif /* _ASM_S390_DIAG_H */
|
#endif /* _ASM_S390_DIAG_H */
|
||||||
|
@ -35,6 +35,7 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = {
|
|||||||
[DIAG_STAT_X014] = { .code = 0x014, .name = "Spool File Services" },
|
[DIAG_STAT_X014] = { .code = 0x014, .name = "Spool File Services" },
|
||||||
[DIAG_STAT_X044] = { .code = 0x044, .name = "Voluntary Timeslice End" },
|
[DIAG_STAT_X044] = { .code = 0x044, .name = "Voluntary Timeslice End" },
|
||||||
[DIAG_STAT_X064] = { .code = 0x064, .name = "NSS Manipulation" },
|
[DIAG_STAT_X064] = { .code = 0x064, .name = "NSS Manipulation" },
|
||||||
|
[DIAG_STAT_X08C] = { .code = 0x08c, .name = "Access 3270 Display Device Information" },
|
||||||
[DIAG_STAT_X09C] = { .code = 0x09c, .name = "Relinquish Timeslice" },
|
[DIAG_STAT_X09C] = { .code = 0x09c, .name = "Relinquish Timeslice" },
|
||||||
[DIAG_STAT_X0DC] = { .code = 0x0dc, .name = "Appldata Control" },
|
[DIAG_STAT_X0DC] = { .code = 0x0dc, .name = "Appldata Control" },
|
||||||
[DIAG_STAT_X204] = { .code = 0x204, .name = "Logical-CPU Utilization" },
|
[DIAG_STAT_X204] = { .code = 0x204, .name = "Logical-CPU Utilization" },
|
||||||
@ -57,12 +58,16 @@ struct diag_ops __amode31_ref diag_amode31_ops = {
|
|||||||
.diag26c = _diag26c_amode31,
|
.diag26c = _diag26c_amode31,
|
||||||
.diag14 = _diag14_amode31,
|
.diag14 = _diag14_amode31,
|
||||||
.diag0c = _diag0c_amode31,
|
.diag0c = _diag0c_amode31,
|
||||||
|
.diag8c = _diag8c_amode31,
|
||||||
.diag308_reset = _diag308_reset_amode31
|
.diag308_reset = _diag308_reset_amode31
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct diag210 _diag210_tmp_amode31 __section(".amode31.data");
|
static struct diag210 _diag210_tmp_amode31 __section(".amode31.data");
|
||||||
struct diag210 __amode31_ref *__diag210_tmp_amode31 = &_diag210_tmp_amode31;
|
struct diag210 __amode31_ref *__diag210_tmp_amode31 = &_diag210_tmp_amode31;
|
||||||
|
|
||||||
|
static struct diag8c _diag8c_tmp_amode31 __section(".amode31.data");
|
||||||
|
struct diag8c __amode31_ref *__diag8c_tmp_amode31 = &_diag8c_tmp_amode31;
|
||||||
|
|
||||||
static int show_diag_stat(struct seq_file *m, void *v)
|
static int show_diag_stat(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
struct diag_stat *stat;
|
struct diag_stat *stat;
|
||||||
@ -194,6 +199,27 @@ int diag210(struct diag210 *addr)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(diag210);
|
EXPORT_SYMBOL(diag210);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Diagnose 210: Get information about a virtual device
|
||||||
|
*/
|
||||||
|
int diag8c(struct diag8c *addr, struct ccw_dev_id *devno)
|
||||||
|
{
|
||||||
|
static DEFINE_SPINLOCK(diag8c_lock);
|
||||||
|
unsigned long flags;
|
||||||
|
int ccode;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&diag8c_lock, flags);
|
||||||
|
|
||||||
|
diag_stat_inc(DIAG_STAT_X08C);
|
||||||
|
ccode = diag_amode31_ops.diag8c(__diag8c_tmp_amode31, devno, sizeof(*addr));
|
||||||
|
|
||||||
|
*addr = *__diag8c_tmp_amode31;
|
||||||
|
spin_unlock_irqrestore(&diag8c_lock, flags);
|
||||||
|
|
||||||
|
return ccode;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(diag8c);
|
||||||
|
|
||||||
int diag224(void *ptr)
|
int diag224(void *ptr)
|
||||||
{
|
{
|
||||||
int rc = -EOPNOTSUPP;
|
int rc = -EOPNOTSUPP;
|
||||||
|
@ -62,6 +62,19 @@ ENTRY(_diag210_amode31)
|
|||||||
EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault)
|
EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault)
|
||||||
ENDPROC(_diag210_amode31)
|
ENDPROC(_diag210_amode31)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int diag8c(struct diag8c *addr, struct ccw_dev_id *devno, size_t len)
|
||||||
|
*/
|
||||||
|
ENTRY(_diag8c_amode31)
|
||||||
|
llgf %r3,0(%r3)
|
||||||
|
sam31
|
||||||
|
diag %r2,%r4,0x8c
|
||||||
|
.Ldiag8c_ex:
|
||||||
|
sam64
|
||||||
|
lgfr %r2,%r3
|
||||||
|
BR_EX_AMODE31_r14
|
||||||
|
EX_TABLE_AMODE31(.Ldiag8c_ex, .Ldiag8c_ex)
|
||||||
|
ENDPROC(_diag8c_amode31)
|
||||||
/*
|
/*
|
||||||
* int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode)
|
* int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode)
|
||||||
*/
|
*/
|
||||||
|
@ -421,8 +421,19 @@ raw3270_size_device_vm(struct raw3270 *rp)
|
|||||||
int rc, model;
|
int rc, model;
|
||||||
struct ccw_dev_id dev_id;
|
struct ccw_dev_id dev_id;
|
||||||
struct diag210 diag_data;
|
struct diag210 diag_data;
|
||||||
|
struct diag8c diag8c_data;
|
||||||
|
|
||||||
ccw_device_get_id(rp->cdev, &dev_id);
|
ccw_device_get_id(rp->cdev, &dev_id);
|
||||||
|
rc = diag8c(&diag8c_data, &dev_id);
|
||||||
|
if (!rc) {
|
||||||
|
rp->model = 2;
|
||||||
|
rp->rows = diag8c_data.height;
|
||||||
|
rp->cols = diag8c_data.width;
|
||||||
|
if (diag8c_data.flags & 1)
|
||||||
|
set_bit(RAW3270_FLAGS_14BITADDR, &rp->flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
diag_data.vrdcdvno = dev_id.devno;
|
diag_data.vrdcdvno = dev_id.devno;
|
||||||
diag_data.vrdclen = sizeof(struct diag210);
|
diag_data.vrdclen = sizeof(struct diag210);
|
||||||
rc = diag210(&diag_data);
|
rc = diag210(&diag_data);
|
||||||
|
Loading…
Reference in New Issue
Block a user