Commit 31598e87 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
  [S390] kexec: Disable ftrace during kexec
  [S390] support XZ compressed kernel
  [S390] css_bus_type: make it static
  [S390] css_driver: remove duplicate members
  [S390] css: remove subchannel private
  [S390] css: move chsc_private to drv_data
  [S390] css: move io_private to drv_data
  [S390] cio: move cdev pointer to io_subchannel_private
  [S390] cio: move options to io_sch_private
  [S390] cio: move asms to generic header
  [S390] cio: move orb definitions to separate header
  [S390] Write protect module text and RO data
  [S390] dasd: get rid of compile warning
  [S390] remove superfluous check from do_IRQ
  [S390] remove redundant stack check option
parents 241eb956 6966727d
......@@ -85,6 +85,7 @@ config S390
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_LZMA
select HAVE_KERNEL_LZO
select HAVE_KERNEL_XZ
select HAVE_GET_USER_PAGES_FAST
select HAVE_ARCH_MUTEX_CPU_RELAX
select ARCH_INLINE_SPIN_TRYLOCK
......@@ -341,26 +342,16 @@ config STACK_GUARD
The minimum size for the stack guard should be 256 for 31 bit and
512 for 64 bit.
config WARN_STACK
config WARN_DYNAMIC_STACK
def_bool n
prompt "Emit compiler warnings for function with broken stack usage"
prompt "Emit compiler warnings for function with dynamic stack usage"
help
This option enables the compiler options -mwarn-framesize and
-mwarn-dynamicstack. If the compiler supports these options it
will generate warnings for function which either use alloca or
create a stack frame bigger than CONFIG_WARN_STACK_SIZE.
This option enables the compiler option -mwarn-dynamicstack. If the
compiler supports this options generates warnings for functions
that dynamically allocate stack space using alloca.
Say N if you are unsure.
config WARN_STACK_SIZE
int "Maximum frame size considered safe (128-2048)"
range 128 2048
depends on WARN_STACK
default "2048"
help
This allows you to specify the maximum frame size a function may
have without the compiler complaining about it.
config ARCH_POPULATES_NODE_MAP
def_bool y
......
......@@ -31,4 +31,7 @@ config DEBUG_STRICT_USER_COPY_CHECKS
If unsure, or if you run an older (pre 4.4) gcc, say N.
config DEBUG_SET_MODULE_RONX
def_bool y
depends on MODULES
endmenu
......@@ -80,8 +80,7 @@ endif
endif
ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
endif
KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y)
......
......@@ -7,7 +7,8 @@
BITS := $(if $(CONFIG_64BIT),64,31)
targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \
vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o sizes.h head$(BITS).o
vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \
sizes.h head$(BITS).o
KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
KBUILD_CFLAGS += $(cflags-y)
......@@ -48,6 +49,7 @@ suffix-$(CONFIG_KERNEL_GZIP) := gz
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
suffix-$(CONFIG_KERNEL_LZMA) := lzma
suffix-$(CONFIG_KERNEL_LZO) := lzo
suffix-$(CONFIG_KERNEL_XZ) := xz
$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y)
$(call if_changed,gzip)
......@@ -57,6 +59,8 @@ $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y)
$(call if_changed,lzma)
$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y)
$(call if_changed,lzo)
$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y)
$(call if_changed,xzkern)
LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y)
......
......@@ -19,6 +19,7 @@
#undef memset
#undef memcpy
#undef memmove
#define memmove memmove
#define memzero(s, n) memset((s), 0, (n))
/* Symbols defined by linker scripts */
......@@ -54,6 +55,10 @@ static unsigned long free_mem_end_ptr;
#include "../../../../lib/decompress_unlzo.c"
#endif
#ifdef CONFIG_KERNEL_XZ
#include "../../../../lib/decompress_unxz.c"
#endif
extern _sclp_print_early(const char *);
int puts(const char *s)
......
......@@ -8,4 +8,8 @@
void kernel_map_pages(struct page *page, int numpages, int enable);
#endif
int set_memory_ro(unsigned long addr, int numpages);
int set_memory_rw(unsigned long addr, int numpages);
int set_memory_nx(unsigned long addr, int numpages);
#endif /* _S390_CACHEFLUSH_H */
......@@ -12,6 +12,7 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/ftrace.h>
#include <asm/cio.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
......@@ -71,6 +72,7 @@ static void __machine_kexec(void *data)
void machine_kexec(struct kimage *image)
{
tracer_disable();
smp_send_stop();
smp_switch_to_ipl_cpu(__machine_kexec, image);
}
......@@ -6,3 +6,4 @@ obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
page-states.o gup.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
/*
* Copyright IBM Corp. 2011
* Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
*/
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <asm/pgtable.h>
static void change_page_attr(unsigned long addr, int numpages,
pte_t (*set) (pte_t))
{
pte_t *ptep, pte;
pmd_t *pmdp;
pud_t *pudp;
pgd_t *pgdp;
int i;
for (i = 0; i < numpages; i++) {
pgdp = pgd_offset(&init_mm, addr);
pudp = pud_offset(pgdp, addr);
pmdp = pmd_offset(pudp, addr);
if (pmd_huge(*pmdp)) {
WARN_ON_ONCE(1);
continue;
}
ptep = pte_offset_kernel(pmdp, addr + i * PAGE_SIZE);
pte = *ptep;
pte = set(pte);
ptep_invalidate(&init_mm, addr + i * PAGE_SIZE, ptep);
*ptep = pte;
}
}
int set_memory_ro(unsigned long addr, int numpages)
{
change_page_attr(addr, numpages, pte_wrprotect);
return 0;
}
EXPORT_SYMBOL_GPL(set_memory_ro);
int set_memory_rw(unsigned long addr, int numpages)
{
change_page_attr(addr, numpages, pte_mkwrite);
return 0;
}
EXPORT_SYMBOL_GPL(set_memory_rw);
/* not possible */
int set_memory_nx(unsigned long addr, int numpages)
{
return 0;
}
EXPORT_SYMBOL_GPL(set_memory_nx);
......@@ -2648,6 +2648,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
dasd_sfree_request(cqr, startdev);
return ERR_PTR(-EAGAIN);
}
len_to_track_end = 0;
/*
* A tidaw can address 4k of memory, but must not cross page boundaries
* We can let the block layer handle this by setting
......
......@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
static void chsc_subchannel_irq(struct subchannel *sch)
{
struct chsc_private *private = sch->private;
struct chsc_private *private = dev_get_drvdata(&sch->dev);
struct chsc_request *request = private->request;
struct irb *irb = (struct irb *)&S390_lowcore.irb;
......@@ -80,13 +80,14 @@ static int chsc_subchannel_probe(struct subchannel *sch)
private = kzalloc(sizeof(*private), GFP_KERNEL);
if (!private)
return -ENOMEM;
dev_set_drvdata(&sch->dev, private);
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
if (ret) {
CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
sch->schid.ssid, sch->schid.sch_no, ret);
dev_set_drvdata(&sch->dev, NULL);
kfree(private);
} else {
sch->private = private;
if (dev_get_uevent_suppress(&sch->dev)) {
dev_set_uevent_suppress(&sch->dev, 0);
kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
......@@ -100,8 +101,8 @@ static int chsc_subchannel_remove(struct subchannel *sch)
struct chsc_private *private;
cio_disable_subchannel(sch);
private = sch->private;
sch->private = NULL;
private = dev_get_drvdata(&sch->dev);
dev_set_drvdata(&sch->dev, NULL);
if (private->request) {
complete(&private->request->completion);
put_device(&sch->dev);
......@@ -147,7 +148,10 @@ static struct css_device_id chsc_subchannel_ids[] = {
MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
static struct css_driver chsc_subchannel_driver = {
.drv = {
.owner = THIS_MODULE,
.name = "chsc_subchannel",
},
.subchannel_type = chsc_subchannel_ids,
.irq = chsc_subchannel_irq,
.probe = chsc_subchannel_probe,
......@@ -157,7 +161,6 @@ static struct css_driver chsc_subchannel_driver = {
.freeze = chsc_subchannel_freeze,
.thaw = chsc_subchannel_restore,
.restore = chsc_subchannel_restore,
.name = "chsc_subchannel",
};
static int __init chsc_init_dbfs(void)
......@@ -241,7 +244,7 @@ static int chsc_async(struct chsc_async_area *chsc_area,
chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
while ((sch = chsc_get_next_subchannel(sch))) {
spin_lock(sch->lock);
private = sch->private;
private = dev_get_drvdata(&sch->dev);
if (private->request) {
spin_unlock(sch->lock);
ret = -EBUSY;
......
......@@ -84,29 +84,14 @@ static int __init cio_debug_init(void)
arch_initcall (cio_debug_init);
int
cio_set_options (struct subchannel *sch, int flags)
int cio_set_options(struct subchannel *sch, int flags)
{
sch->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
sch->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
sch->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
return 0;
}
struct io_subchannel_private *priv = to_io_private(sch);
/* FIXME: who wants to use this? */
int
cio_get_options (struct subchannel *sch)
{
int flags;
flags = 0;
if (sch->options.suspend)
flags |= DOIO_ALLOW_SUSPEND;
if (sch->options.prefetch)
flags |= DOIO_DENY_PREFETCH;
if (sch->options.inter)
flags |= DOIO_SUPPRESS_INTER;
return flags;
priv->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
priv->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
priv->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
return 0;
}
static int
......@@ -139,21 +124,21 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
__u8 lpm, /* logical path mask */
__u8 key) /* storage key */
{
struct io_subchannel_private *priv = to_io_private(sch);
union orb *orb = &priv->orb;
int ccode;
union orb *orb;
CIO_TRACE_EVENT(5, "stIO");
CIO_TRACE_EVENT(5, dev_name(&sch->dev));
orb = &to_io_private(sch)->orb;
memset(orb, 0, sizeof(union orb));
/* sch is always under 2G. */
orb->cmd.intparm = (u32)(addr_t)sch;
orb->cmd.fmt = 1;
orb->cmd.pfch = sch->options.prefetch == 0;
orb->cmd.spnd = sch->options.suspend;
orb->cmd.ssic = sch->options.suspend && sch->options.inter;
orb->cmd.pfch = priv->options.prefetch == 0;
orb->cmd.spnd = priv->options.suspend;
orb->cmd.ssic = priv->options.suspend && priv->options.inter;
orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm;
#ifdef CONFIG_64BIT
/*
......@@ -630,11 +615,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
irb = (struct irb *)&S390_lowcore.irb;
do {
kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
/*
* Non I/O-subchannel thin interrupts are processed differently
*/
if (tpi_info->adapter_IO == 1 &&
tpi_info->int_type == IO_INTERRUPT_TYPE) {
if (tpi_info->adapter_IO) {
do_adapter_IO(tpi_info->isc);
continue;
}
......
......@@ -84,13 +84,6 @@ struct subchannel {
SUBCHANNEL_TYPE_MSG = 2,
SUBCHANNEL_TYPE_ADM = 3,
} st; /* subchannel type */
struct {
unsigned int suspend:1; /* allow suspend */
unsigned int prefetch:1;/* deny prefetch */
unsigned int inter:1; /* suppress intermediate interrupts */
} __attribute__ ((packed)) options;
__u8 vpm; /* verified path mask */
__u8 lpm; /* logical path mask */
__u8 opm; /* operational path mask */
......@@ -99,14 +92,11 @@ struct subchannel {
struct chsc_ssd_info ssd_info; /* subchannel description */
struct device dev; /* entry in device tree */
struct css_driver *driver;
void *private; /* private per subchannel type data */
enum sch_todo todo;
struct work_struct todo_work;
struct schib_config config;
} __attribute__ ((aligned(8)));
#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
#define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
......@@ -120,7 +110,6 @@ extern int cio_start (struct subchannel *, struct ccw1 *, __u8);
extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8);
extern int cio_cancel (struct subchannel *);
extern int cio_set_options (struct subchannel *, int);
extern int cio_get_options (struct subchannel *);
extern int cio_update_schib(struct subchannel *sch);
extern int cio_commit_config(struct subchannel *sch);
......
......@@ -35,6 +35,7 @@ int css_init_done = 0;
int max_ssid;
struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1];
static struct bus_type css_bus_type;
int
for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
......@@ -1214,7 +1215,7 @@ static const struct dev_pm_ops css_pm_ops = {
.restore = css_pm_restore,
};
struct bus_type css_bus_type = {
static struct bus_type css_bus_type = {
.name = "css",
.match = css_bus_match,
.probe = css_probe,
......@@ -1233,9 +1234,7 @@ struct bus_type css_bus_type = {
*/
int css_driver_register(struct css_driver *cdrv)
{
cdrv->drv.name = cdrv->name;
cdrv->drv.bus = &css_bus_type;
cdrv->drv.owner = cdrv->owner;
return driver_register(&cdrv->drv);
}
EXPORT_SYMBOL_GPL(css_driver_register);
......@@ -1253,4 +1252,3 @@ void css_driver_unregister(struct css_driver *cdrv)
EXPORT_SYMBOL_GPL(css_driver_unregister);
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(css_bus_type);
......@@ -63,7 +63,6 @@ struct subchannel;
struct chp_link;
/**
* struct css_driver - device driver for subchannels
* @owner: owning module
* @subchannel_type: subchannel type supported by this driver
* @drv: embedded device driver structure
* @irq: called on interrupts
......@@ -78,10 +77,8 @@ struct chp_link;
* @thaw: undo work done in @freeze
* @restore: callback for restoring after hibernation
* @settle: wait for asynchronous work to finish
* @name: name of the device driver
*/
struct css_driver {
struct module *owner;
struct css_device_id *subchannel_type;
struct device_driver drv;
void (*irq)(struct subchannel *);
......@@ -96,16 +93,10 @@ struct css_driver {
int (*thaw) (struct subchannel *);
int (*restore)(struct subchannel *);
int (*settle)(void);
const char *name;
};
#define to_cssdriver(n) container_of(n, struct css_driver, drv)
/*
* all css_drivers have the css_bus_type
*/
extern struct bus_type css_bus_type;
extern int css_driver_register(struct css_driver *);
extern void css_driver_unregister(struct css_driver *);
......@@ -140,7 +131,6 @@ struct channel_subsystem {
};
#define to_css(dev) container_of(dev, struct channel_subsystem, device)
extern struct bus_type css_bus_type;
extern struct channel_subsystem *channel_subsystems[];
/* Helper functions to build lists for the slow path. */
......
......@@ -172,9 +172,11 @@ static int io_subchannel_settle(void)
}
static struct css_driver io_subchannel_driver = {
.drv = {
.owner = THIS_MODULE,
.subchannel_type = io_subchannel_ids,
.name = "io_subchannel",
},
.subchannel_type = io_subchannel_ids,
.irq = io_subchannel_irq,
.sch_event = io_subchannel_sch_event,
.chp_event = io_subchannel_chp_event,
......@@ -1030,6 +1032,7 @@ static void io_subchannel_init_fields(struct subchannel *sch)
*/
static int io_subchannel_probe(struct subchannel *sch)
{
struct io_subchannel_private *io_priv;
struct ccw_device *cdev;
int rc;
......@@ -1073,10 +1076,11 @@ static int io_subchannel_probe(struct subchannel *sch)
if (rc)
goto out_schedule;
/* Allocate I/O subchannel private data. */
sch->private = kzalloc(sizeof(struct io_subchannel_private),
GFP_KERNEL | GFP_DMA);
if (!sch->private)
io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
if (!io_priv)
goto out_schedule;
set_io_private(sch, io_priv);
css_schedule_eval(sch->schid);
return 0;
......@@ -1090,6 +1094,7 @@ static int io_subchannel_probe(struct subchannel *sch)
static int
io_subchannel_remove (struct subchannel *sch)
{
struct io_subchannel_private *io_priv = to_io_private(sch);
struct ccw_device *cdev;
cdev = sch_get_cdev(sch);
......@@ -1099,11 +1104,12 @@ io_subchannel_remove (struct subchannel *sch)
/* Set ccw device to not operational and drop reference. */
spin_lock_irq(cdev->ccwlock);
sch_set_cdev(sch, NULL);
set_io_private(sch, NULL);
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irq(cdev->ccwlock);
ccw_device_unregister(cdev);
out_free:
kfree(sch->private);
kfree(io_priv);
sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
return 0;
}
......@@ -1553,11 +1559,12 @@ spinlock_t * cio_get_console_lock(void)
static int ccw_device_console_enable(struct ccw_device *cdev,
struct subchannel *sch)
{
struct io_subchannel_private *io_priv = cio_get_console_priv();
int rc;
/* Attach subchannel private data. */
sch->private = cio_get_console_priv();
memset(sch->private, 0, sizeof(struct io_subchannel_private));
memset(io_priv, 0, sizeof(*io_priv));
set_io_private(sch, io_priv);
io_subchannel_init_fields(sch);
rc = cio_commit_config(sch);
if (rc)
......
......@@ -5,68 +5,36 @@
#include <asm/schid.h>
#include <asm/ccwdev.h>
#include "css.h"
/*
* command-mode operation request block
*/
struct cmd_orb {
u32 intparm; /* interruption parameter */
u32 key : 4; /* flags, like key, suspend control, etc. */
u32 spnd : 1; /* suspend control */
u32 res1 : 1; /* reserved */
u32 mod : 1; /* modification control */
u32 sync : 1; /* synchronize control */
u32 fmt : 1; /* format control */
u32 pfch : 1; /* prefetch control */
u32 isic : 1; /* initial-status-interruption control */
u32 alcc : 1; /* address-limit-checking control */
u32 ssic : 1; /* suppress-suspended-interr. control */
u32 res2 : 1; /* reserved */
u32 c64 : 1; /* IDAW/QDIO 64 bit control */
u32 i2k : 1; /* IDAW 2/4kB block size control */
u32 lpm : 8; /* logical path mask */
u32 ils : 1; /* incorrect length */
u32 zero : 6; /* reserved zeros */
u32 orbx : 1; /* ORB extension control */
u32 cpa; /* channel program address */
} __attribute__ ((packed, aligned(4)));
/*
* transport-mode operation request block
*/
struct tm_orb {
u32 intparm;
u32 key:4;
u32 :9;
u32 b:1;
u32 :2;
u32 lpm:8;
u32 :7;
u32 x:1;
u32 tcw;
u32 prio:8;
u32 :8;
u32 rsvpgm:8;
u32 :8;
u32 :32;
u32 :32;
u32 :32;
u32 :32;
} __attribute__ ((packed, aligned(4)));
union orb {
struct cmd_orb cmd;
struct tm_orb tm;
} __attribute__ ((packed, aligned(4)));
#include "orb.h"
struct io_subchannel_private {
union orb orb; /* operation request block */
struct ccw1 sense_ccw; /* static ccw for sense command */
} __attribute__ ((aligned(8)));
struct ccw_device *cdev;/* pointer to the child ccw device */
struct {
unsigned int suspend:1; /* allow suspend */
unsigned int prefetch:1;/* deny prefetch */
unsigned int inter:1; /* suppress intermediate interrupts */
} __packed options;
} __aligned(8);
#define to_io_private(n) ((struct io_subchannel_private *)n->private)
#define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
#define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
#define to_io_private(n) ((struct io_subchannel_private *) \
dev_get_drvdata(&(n)->dev))
#define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p))
static inline struct ccw_device *sch_get_cdev(struct subchannel *sch)
{
struct io_subchannel_private *priv = to_io_private(sch);
return priv ? priv->cdev : NULL;
}
static inline void sch_set_cdev(struct subchannel *sch,
struct ccw_device *cdev)
{
struct io_subchannel_private *priv = to_io_private(sch);
if (priv)
priv->cdev = cdev;
}
#define MAX_CIWS 8
......@@ -191,23 +159,6 @@ struct ccw_device_private {
void *cmb_wait; /* deferred cmb enable/disable */
};
static inline int ssch(struct subchannel_id schid, union orb *addr)
{
register struct subchannel_id reg1 asm("1") = schid;
int ccode = -EIO;
asm volatile(
" ssch 0(%2)\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
EX_TABLE(0b, 1b)
: "+d" (ccode)
: "d" (reg1), "a" (addr), "m" (*addr)
: "cc", "memory");
return ccode;
}
static inline int rsch(struct subchannel_id schid)
{
register struct subchannel_id reg1 asm("1") = schid;
......@@ -223,21 +174,6 @@ static inline int rsch(struct subchannel_id schid)
return ccode;
}
static inline int csch(struct subchannel_id schid)
{
register struct subchannel_id reg1 asm("1") = schid;
int ccode;
asm volatile(
" csch\n"
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
: "d" (reg1)
: "cc");
return ccode;
}
static inline int hsch(struct subchannel_id schid)
{
register struct subchannel_id reg1 asm("1") = schid;
......
......@@ -3,6 +3,8 @@
#include <asm/chpid.h>
#include <asm/schid.h>
#include "orb.h"
#include "cio.h"
/*
* TPI info structure
......@@ -87,6 +89,38 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr)
return ccode;
}
static inline int ssch(struct subchannel_id schid, union orb *addr)
{
register struct subchannel_id reg1 asm("1") = schid;
int ccode = -EIO;
asm volatile(
" ssch 0(%2)\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
EX_TABLE(0b, 1b)
: "+d" (ccode)
: "d" (reg1), "a" (addr), "m" (*addr)
: "cc", "memory");
return ccode;
}
static inline int csch(struct subchannel_id schid)
{
register struct subchannel_id reg1 asm("1") = schid;
int ccode;
asm volatile(
" csch\n"
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
: "d" (reg1)
: "cc");
return ccode;
}
static inline int tpi(struct tpi_info *addr)
{
int ccode;
......
/*
* Orb related data structures.
*
* Copyright IBM Corp. 2007, 2011
*
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
* Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
* Sebastian Ott <sebott@linux.vnet.ibm.com>
*/
#ifndef S390_ORB_H
#define S390_ORB_H
/*
* Command-mode operation request block
*/
struct cmd_orb {
u32 intparm; /* interruption parameter */
u32 key:4; /* flags, like key, suspend control, etc. */
u32 spnd:1; /* suspend control */
u32 res1:1; /* reserved */
u32 mod:1; /* modification control */
u32 sync:1; /* synchronize control */
u32 fmt:1; /* format control */
u32 pfch:1; /* prefetch control */
u32 isic:1; /* initial-status-interruption control */
u32 alcc:1; /* address-limit-checking control */
u32 ssic:1; /* suppress-suspended-interr. control */
u32 res2:1; /* reserved */
u32 c64:1; /* IDAW/QDIO 64 bit control */
u32 i2k:1; /* IDAW 2/4kB block size control */
u32 lpm:8; /* logical path mask */
u32 ils:1; /* incorrect length */
u32 zero:6; /* reserved zeros */
u32 orbx:1; /* ORB extension control */
u32 cpa; /* channel program address */
} __packed __aligned(4);
/*
* Transport-mode operation request block
*/
struct tm_orb {
u32 intparm;
u32 key:4;
u32:9;
u32 b:1;
u32:2;
u32 lpm:8;
u32:7;
u32 x:1;
u32 tcw;
u32 prio:8;
u32:8;
u32 rsvpgm:8;
u32:8;
u32:32;
u32:32;
u32:32;
u32:32;
} __packed __aligned(4);
union orb {
struct cmd_orb cmd;
struct tm_orb tm;
} __packed __aligned(4);
#endif /* S390_ORB_H */
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