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 ...@@ -85,6 +85,7 @@ config S390
select HAVE_KERNEL_BZIP2 select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_LZMA select HAVE_KERNEL_LZMA
select HAVE_KERNEL_LZO select HAVE_KERNEL_LZO
select HAVE_KERNEL_XZ
select HAVE_GET_USER_PAGES_FAST select HAVE_GET_USER_PAGES_FAST
select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_MUTEX_CPU_RELAX
select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK
...@@ -341,26 +342,16 @@ config STACK_GUARD ...@@ -341,26 +342,16 @@ config STACK_GUARD
The minimum size for the stack guard should be 256 for 31 bit and The minimum size for the stack guard should be 256 for 31 bit and
512 for 64 bit. 512 for 64 bit.
config WARN_STACK config WARN_DYNAMIC_STACK
def_bool n def_bool n
prompt "Emit compiler warnings for function with broken stack usage" prompt "Emit compiler warnings for function with dynamic stack usage"
help help
This option enables the compiler options -mwarn-framesize and This option enables the compiler option -mwarn-dynamicstack. If the
-mwarn-dynamicstack. If the compiler supports these options it compiler supports this options generates warnings for functions
will generate warnings for function which either use alloca or that dynamically allocate stack space using alloca.
create a stack frame bigger than CONFIG_WARN_STACK_SIZE.
Say N if you are unsure. 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 config ARCH_POPULATES_NODE_MAP
def_bool y def_bool y
......
...@@ -31,4 +31,7 @@ config DEBUG_STRICT_USER_COPY_CHECKS ...@@ -31,4 +31,7 @@ config DEBUG_STRICT_USER_COPY_CHECKS
If unsure, or if you run an older (pre 4.4) gcc, say N. 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 endmenu
...@@ -80,8 +80,7 @@ endif ...@@ -80,8 +80,7 @@ endif
endif endif
ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y) ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
endif endif
KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y)
......
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
BITS := $(if $(CONFIG_64BIT),64,31) BITS := $(if $(CONFIG_64BIT),64,31)
targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ 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 := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
KBUILD_CFLAGS += $(cflags-y) KBUILD_CFLAGS += $(cflags-y)
...@@ -48,6 +49,7 @@ suffix-$(CONFIG_KERNEL_GZIP) := gz ...@@ -48,6 +49,7 @@ suffix-$(CONFIG_KERNEL_GZIP) := gz
suffix-$(CONFIG_KERNEL_BZIP2) := bz2 suffix-$(CONFIG_KERNEL_BZIP2) := bz2
suffix-$(CONFIG_KERNEL_LZMA) := lzma suffix-$(CONFIG_KERNEL_LZMA) := lzma
suffix-$(CONFIG_KERNEL_LZO) := lzo suffix-$(CONFIG_KERNEL_LZO) := lzo
suffix-$(CONFIG_KERNEL_XZ) := xz
$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y)
$(call if_changed,gzip) $(call if_changed,gzip)
...@@ -57,6 +59,8 @@ $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) ...@@ -57,6 +59,8 @@ $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y)
$(call if_changed,lzma) $(call if_changed,lzma)
$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y)
$(call if_changed,lzo) $(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 LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#undef memset #undef memset
#undef memcpy #undef memcpy
#undef memmove #undef memmove
#define memmove memmove
#define memzero(s, n) memset((s), 0, (n)) #define memzero(s, n) memset((s), 0, (n))
/* Symbols defined by linker scripts */ /* Symbols defined by linker scripts */
...@@ -54,6 +55,10 @@ static unsigned long free_mem_end_ptr; ...@@ -54,6 +55,10 @@ static unsigned long free_mem_end_ptr;
#include "../../../../lib/decompress_unlzo.c" #include "../../../../lib/decompress_unlzo.c"
#endif #endif
#ifdef CONFIG_KERNEL_XZ
#include "../../../../lib/decompress_unxz.c"
#endif
extern _sclp_print_early(const char *); extern _sclp_print_early(const char *);
int puts(const char *s) int puts(const char *s)
......
...@@ -8,4 +8,8 @@ ...@@ -8,4 +8,8 @@
void kernel_map_pages(struct page *page, int numpages, int enable); void kernel_map_pages(struct page *page, int numpages, int enable);
#endif #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 */ #endif /* _S390_CACHEFLUSH_H */
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/ftrace.h>
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -71,6 +72,7 @@ static void __machine_kexec(void *data) ...@@ -71,6 +72,7 @@ static void __machine_kexec(void *data)
void machine_kexec(struct kimage *image) void machine_kexec(struct kimage *image)
{ {
tracer_disable();
smp_send_stop(); smp_send_stop();
smp_switch_to_ipl_cpu(__machine_kexec, image); 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 \ ...@@ -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 page-states.o gup.o
obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.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( ...@@ -2648,6 +2648,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
dasd_sfree_request(cqr, startdev); dasd_sfree_request(cqr, startdev);
return ERR_PTR(-EAGAIN); return ERR_PTR(-EAGAIN);
} }
len_to_track_end = 0;
/* /*
* A tidaw can address 4k of memory, but must not cross page boundaries * A tidaw can address 4k of memory, but must not cross page boundaries
* We can let the block layer handle this by setting * We can let the block layer handle this by setting
......
...@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL"); ...@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
static void chsc_subchannel_irq(struct subchannel *sch) 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 chsc_request *request = private->request;
struct irb *irb = (struct irb *)&S390_lowcore.irb; struct irb *irb = (struct irb *)&S390_lowcore.irb;
...@@ -80,13 +80,14 @@ static int chsc_subchannel_probe(struct subchannel *sch) ...@@ -80,13 +80,14 @@ static int chsc_subchannel_probe(struct subchannel *sch)
private = kzalloc(sizeof(*private), GFP_KERNEL); private = kzalloc(sizeof(*private), GFP_KERNEL);
if (!private) if (!private)
return -ENOMEM; return -ENOMEM;
dev_set_drvdata(&sch->dev, private);
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
if (ret) { if (ret) {
CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n", CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
sch->schid.ssid, sch->schid.sch_no, ret); sch->schid.ssid, sch->schid.sch_no, ret);
dev_set_drvdata(&sch->dev, NULL);
kfree(private); kfree(private);
} else { } else {
sch->private = private;
if (dev_get_uevent_suppress(&sch->dev)) { if (dev_get_uevent_suppress(&sch->dev)) {
dev_set_uevent_suppress(&sch->dev, 0); dev_set_uevent_suppress(&sch->dev, 0);
kobject_uevent(&sch->dev.kobj, KOBJ_ADD); kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
...@@ -100,8 +101,8 @@ static int chsc_subchannel_remove(struct subchannel *sch) ...@@ -100,8 +101,8 @@ static int chsc_subchannel_remove(struct subchannel *sch)
struct chsc_private *private; struct chsc_private *private;
cio_disable_subchannel(sch); cio_disable_subchannel(sch);
private = sch->private; private = dev_get_drvdata(&sch->dev);
sch->private = NULL; dev_set_drvdata(&sch->dev, NULL);
if (private->request) { if (private->request) {
complete(&private->request->completion); complete(&private->request->completion);
put_device(&sch->dev); put_device(&sch->dev);
...@@ -147,7 +148,10 @@ static struct css_device_id chsc_subchannel_ids[] = { ...@@ -147,7 +148,10 @@ static struct css_device_id chsc_subchannel_ids[] = {
MODULE_DEVICE_TABLE(css, chsc_subchannel_ids); MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
static struct css_driver chsc_subchannel_driver = { static struct css_driver chsc_subchannel_driver = {
.drv = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "chsc_subchannel",
},
.subchannel_type = chsc_subchannel_ids, .subchannel_type = chsc_subchannel_ids,
.irq = chsc_subchannel_irq, .irq = chsc_subchannel_irq,
.probe = chsc_subchannel_probe, .probe = chsc_subchannel_probe,
...@@ -157,7 +161,6 @@ static struct css_driver chsc_subchannel_driver = { ...@@ -157,7 +161,6 @@ static struct css_driver chsc_subchannel_driver = {
.freeze = chsc_subchannel_freeze, .freeze = chsc_subchannel_freeze,
.thaw = chsc_subchannel_restore, .thaw = chsc_subchannel_restore,
.restore = chsc_subchannel_restore, .restore = chsc_subchannel_restore,
.name = "chsc_subchannel",
}; };
static int __init chsc_init_dbfs(void) static int __init chsc_init_dbfs(void)
...@@ -241,7 +244,7 @@ static int chsc_async(struct chsc_async_area *chsc_area, ...@@ -241,7 +244,7 @@ static int chsc_async(struct chsc_async_area *chsc_area,
chsc_area->header.key = PAGE_DEFAULT_KEY >> 4; chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
while ((sch = chsc_get_next_subchannel(sch))) { while ((sch = chsc_get_next_subchannel(sch))) {
spin_lock(sch->lock); spin_lock(sch->lock);
private = sch->private; private = dev_get_drvdata(&sch->dev);
if (private->request) { if (private->request) {
spin_unlock(sch->lock); spin_unlock(sch->lock);
ret = -EBUSY; ret = -EBUSY;
......
...@@ -84,29 +84,14 @@ static int __init cio_debug_init(void) ...@@ -84,29 +84,14 @@ static int __init cio_debug_init(void)
arch_initcall (cio_debug_init); arch_initcall (cio_debug_init);
int int cio_set_options(struct subchannel *sch, int flags)
cio_set_options (struct subchannel *sch, int flags)
{ {
sch->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0; struct io_subchannel_private *priv = to_io_private(sch);
sch->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
sch->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
return 0;
}
/* FIXME: who wants to use this? */ priv->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
int priv->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
cio_get_options (struct subchannel *sch) priv->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
{ return 0;
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;
} }
static int static int
...@@ -139,21 +124,21 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ ...@@ -139,21 +124,21 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
__u8 lpm, /* logical path mask */ __u8 lpm, /* logical path mask */
__u8 key) /* storage key */ __u8 key) /* storage key */
{ {
struct io_subchannel_private *priv = to_io_private(sch);
union orb *orb = &priv->orb;
int ccode; int ccode;
union orb *orb;
CIO_TRACE_EVENT(5, "stIO"); CIO_TRACE_EVENT(5, "stIO");
CIO_TRACE_EVENT(5, dev_name(&sch->dev)); CIO_TRACE_EVENT(5, dev_name(&sch->dev));
orb = &to_io_private(sch)->orb;
memset(orb, 0, sizeof(union orb)); memset(orb, 0, sizeof(union orb));
/* sch is always under 2G. */ /* sch is always under 2G. */
orb->cmd.intparm = (u32)(addr_t)sch; orb->cmd.intparm = (u32)(addr_t)sch;
orb->cmd.fmt = 1; orb->cmd.fmt = 1;
orb->cmd.pfch = sch->options.prefetch == 0; orb->cmd.pfch = priv->options.prefetch == 0;
orb->cmd.spnd = sch->options.suspend; orb->cmd.spnd = priv->options.suspend;
orb->cmd.ssic = sch->options.suspend && sch->options.inter; orb->cmd.ssic = priv->options.suspend && priv->options.inter;
orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm; orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm;
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
/* /*
...@@ -630,11 +615,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) ...@@ -630,11 +615,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
irb = (struct irb *)&S390_lowcore.irb; irb = (struct irb *)&S390_lowcore.irb;
do { do {
kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
/* if (tpi_info->adapter_IO) {
* Non I/O-subchannel thin interrupts are processed differently
*/
if (tpi_info->adapter_IO == 1 &&
tpi_info->int_type == IO_INTERRUPT_TYPE) {
do_adapter_IO(tpi_info->isc); do_adapter_IO(tpi_info->isc);
continue; continue;
} }
......
...@@ -84,13 +84,6 @@ struct subchannel { ...@@ -84,13 +84,6 @@ struct subchannel {
SUBCHANNEL_TYPE_MSG = 2, SUBCHANNEL_TYPE_MSG = 2,
SUBCHANNEL_TYPE_ADM = 3, SUBCHANNEL_TYPE_ADM = 3,
} st; /* subchannel type */ } 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 vpm; /* verified path mask */
__u8 lpm; /* logical path mask */ __u8 lpm; /* logical path mask */
__u8 opm; /* operational path mask */ __u8 opm; /* operational path mask */
...@@ -99,14 +92,11 @@ struct subchannel { ...@@ -99,14 +92,11 @@ struct subchannel {
struct chsc_ssd_info ssd_info; /* subchannel description */ struct chsc_ssd_info ssd_info; /* subchannel description */
struct device dev; /* entry in device tree */ struct device dev; /* entry in device tree */
struct css_driver *driver; struct css_driver *driver;
void *private; /* private per subchannel type data */
enum sch_todo todo; enum sch_todo todo;
struct work_struct todo_work; struct work_struct todo_work;
struct schib_config config; struct schib_config config;
} __attribute__ ((aligned(8))); } __attribute__ ((aligned(8)));
#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
#define to_subchannel(n) container_of(n, struct subchannel, dev) #define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
...@@ -120,7 +110,6 @@ extern int cio_start (struct subchannel *, struct ccw1 *, __u8); ...@@ -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_start_key (struct subchannel *, struct ccw1 *, __u8, __u8);
extern int cio_cancel (struct subchannel *); extern int cio_cancel (struct subchannel *);
extern int cio_set_options (struct subchannel *, int); 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_update_schib(struct subchannel *sch);
extern int cio_commit_config(struct subchannel *sch); extern int cio_commit_config(struct subchannel *sch);
......
...@@ -35,6 +35,7 @@ int css_init_done = 0; ...@@ -35,6 +35,7 @@ int css_init_done = 0;
int max_ssid; int max_ssid;
struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1];
static struct bus_type css_bus_type;
int int
for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
...@@ -1214,7 +1215,7 @@ static const struct dev_pm_ops css_pm_ops = { ...@@ -1214,7 +1215,7 @@ static const struct dev_pm_ops css_pm_ops = {
.restore = css_pm_restore, .restore = css_pm_restore,
}; };
struct bus_type css_bus_type = { static struct bus_type css_bus_type = {
.name = "css", .name = "css",
.match = css_bus_match, .match = css_bus_match,
.probe = css_probe, .probe = css_probe,
...@@ -1233,9 +1234,7 @@ struct bus_type css_bus_type = { ...@@ -1233,9 +1234,7 @@ struct bus_type css_bus_type = {
*/ */
int css_driver_register(struct css_driver *cdrv) int css_driver_register(struct css_driver *cdrv)
{ {
cdrv->drv.name = cdrv->name;
cdrv->drv.bus = &css_bus_type; cdrv->drv.bus = &css_bus_type;
cdrv->drv.owner = cdrv->owner;
return driver_register(&cdrv->drv); return driver_register(&cdrv->drv);
} }
EXPORT_SYMBOL_GPL(css_driver_register); EXPORT_SYMBOL_GPL(css_driver_register);
...@@ -1253,4 +1252,3 @@ void css_driver_unregister(struct css_driver *cdrv) ...@@ -1253,4 +1252,3 @@ void css_driver_unregister(struct css_driver *cdrv)
EXPORT_SYMBOL_GPL(css_driver_unregister); EXPORT_SYMBOL_GPL(css_driver_unregister);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(css_bus_type);
...@@ -63,7 +63,6 @@ struct subchannel; ...@@ -63,7 +63,6 @@ struct subchannel;
struct chp_link; struct chp_link;
/** /**
* struct css_driver - device driver for subchannels * struct css_driver - device driver for subchannels
* @owner: owning module
* @subchannel_type: subchannel type supported by this driver * @subchannel_type: subchannel type supported by this driver
* @drv: embedded device driver structure * @drv: embedded device driver structure
* @irq: called on interrupts * @irq: called on interrupts
...@@ -78,10 +77,8 @@ struct chp_link; ...@@ -78,10 +77,8 @@ struct chp_link;
* @thaw: undo work done in @freeze * @thaw: undo work done in @freeze
* @restore: callback for restoring after hibernation * @restore: callback for restoring after hibernation
* @settle: wait for asynchronous work to finish * @settle: wait for asynchronous work to finish
* @name: name of the device driver
*/ */
struct css_driver { struct css_driver {
struct module *owner;
struct css_device_id *subchannel_type; struct css_device_id *subchannel_type;
struct device_driver drv; struct device_driver drv;
void (*irq)(struct subchannel *); void (*irq)(struct subchannel *);
...@@ -96,16 +93,10 @@ struct css_driver { ...@@ -96,16 +93,10 @@ struct css_driver {
int (*thaw) (struct subchannel *); int (*thaw) (struct subchannel *);
int (*restore)(struct subchannel *); int (*restore)(struct subchannel *);
int (*settle)(void); int (*settle)(void);
const char *name;
}; };
#define to_cssdriver(n) container_of(n, struct css_driver, drv) #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 int css_driver_register(struct css_driver *);
extern void css_driver_unregister(struct css_driver *); extern void css_driver_unregister(struct css_driver *);
...@@ -140,7 +131,6 @@ struct channel_subsystem { ...@@ -140,7 +131,6 @@ struct channel_subsystem {
}; };
#define to_css(dev) container_of(dev, struct channel_subsystem, device) #define to_css(dev) container_of(dev, struct channel_subsystem, device)
extern struct bus_type css_bus_type;
extern struct channel_subsystem *channel_subsystems[]; extern struct channel_subsystem *channel_subsystems[];
/* Helper functions to build lists for the slow path. */ /* Helper functions to build lists for the slow path. */
......
...@@ -172,9 +172,11 @@ static int io_subchannel_settle(void) ...@@ -172,9 +172,11 @@ static int io_subchannel_settle(void)
} }
static struct css_driver io_subchannel_driver = { static struct css_driver io_subchannel_driver = {
.drv = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.subchannel_type = io_subchannel_ids,
.name = "io_subchannel", .name = "io_subchannel",
},
.subchannel_type = io_subchannel_ids,
.irq = io_subchannel_irq, .irq = io_subchannel_irq,
.sch_event = io_subchannel_sch_event, .sch_event = io_subchannel_sch_event,
.chp_event = io_subchannel_chp_event, .chp_event = io_subchannel_chp_event,
...@@ -1030,6 +1032,7 @@ static void io_subchannel_init_fields(struct subchannel *sch) ...@@ -1030,6 +1032,7 @@ static void io_subchannel_init_fields(struct subchannel *sch)
*/ */
static int io_subchannel_probe(struct subchannel *sch) static int io_subchannel_probe(struct subchannel *sch)
{ {
struct io_subchannel_private *io_priv;
struct ccw_device *cdev; struct ccw_device *cdev;
int rc; int rc;
...@@ -1073,10 +1076,11 @@ static int io_subchannel_probe(struct subchannel *sch) ...@@ -1073,10 +1076,11 @@ static int io_subchannel_probe(struct subchannel *sch)
if (rc) if (rc)
goto out_schedule; goto out_schedule;
/* Allocate I/O subchannel private data. */ /* Allocate I/O subchannel private data. */
sch->private = kzalloc(sizeof(struct io_subchannel_private), io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
GFP_KERNEL | GFP_DMA); if (!io_priv)
if (!sch->private)
goto out_schedule; goto out_schedule;
set_io_private(sch, io_priv);
css_schedule_eval(sch->schid); css_schedule_eval(sch->schid);
return 0; return 0;
...@@ -1090,6 +1094,7 @@ static int io_subchannel_probe(struct subchannel *sch) ...@@ -1090,6 +1094,7 @@ static int io_subchannel_probe(struct subchannel *sch)
static int static int
io_subchannel_remove (struct subchannel *sch) io_subchannel_remove (struct subchannel *sch)
{ {
struct io_subchannel_private *io_priv = to_io_private(sch);
struct ccw_device *cdev; struct ccw_device *cdev;
cdev = sch_get_cdev(sch); cdev = sch_get_cdev(sch);
...@@ -1099,11 +1104,12 @@ io_subchannel_remove (struct subchannel *sch) ...@@ -1099,11 +1104,12 @@ io_subchannel_remove (struct subchannel *sch)
/* Set ccw device to not operational and drop reference. */ /* Set ccw device to not operational and drop reference. */
spin_lock_irq(cdev->ccwlock); spin_lock_irq(cdev->ccwlock);
sch_set_cdev(sch, NULL); sch_set_cdev(sch, NULL);
set_io_private(sch, NULL);
cdev->private->state = DEV_STATE_NOT_OPER; cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irq(cdev->ccwlock); spin_unlock_irq(cdev->ccwlock);
ccw_device_unregister(cdev); ccw_device_unregister(cdev);
out_free: out_free:
kfree(sch->private); kfree(io_priv);
sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
return 0; return 0;
} }
...@@ -1553,11 +1559,12 @@ spinlock_t * cio_get_console_lock(void) ...@@ -1553,11 +1559,12 @@ spinlock_t * cio_get_console_lock(void)
static int ccw_device_console_enable(struct ccw_device *cdev, static int ccw_device_console_enable(struct ccw_device *cdev,
struct subchannel *sch) struct subchannel *sch)
{ {
struct io_subchannel_private *io_priv = cio_get_console_priv();
int rc; int rc;
/* Attach subchannel private data. */ /* Attach subchannel private data. */
sch->private = cio_get_console_priv(); memset(io_priv, 0, sizeof(*io_priv));
memset(sch->private, 0, sizeof(struct io_subchannel_private)); set_io_private(sch, io_priv);
io_subchannel_init_fields(sch); io_subchannel_init_fields(sch);
rc = cio_commit_config(sch); rc = cio_commit_config(sch);
if (rc) if (rc)
......
...@@ -5,68 +5,36 @@ ...@@ -5,68 +5,36 @@
#include <asm/schid.h> #include <asm/schid.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include "css.h" #include "css.h"
#include "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 */
} __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)));
struct io_subchannel_private { struct io_subchannel_private {
union orb orb; /* operation request block */ union orb orb; /* operation request block */
struct ccw1 sense_ccw; /* static ccw for sense command */ 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 to_io_private(n) ((struct io_subchannel_private *) \
#define sch_get_cdev(n) (dev_get_drvdata(&n->dev)) dev_get_drvdata(&(n)->dev))
#define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c)) #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 #define MAX_CIWS 8
...@@ -191,23 +159,6 @@ struct ccw_device_private { ...@@ -191,23 +159,6 @@ struct ccw_device_private {
void *cmb_wait; /* deferred cmb enable/disable */ 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) static inline int rsch(struct subchannel_id schid)
{ {
register struct subchannel_id reg1 asm("1") = schid; register struct subchannel_id reg1 asm("1") = schid;
...@@ -223,21 +174,6 @@ static inline int rsch(struct subchannel_id schid) ...@@ -223,21 +174,6 @@ static inline int rsch(struct subchannel_id schid)
return ccode; 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) static inline int hsch(struct subchannel_id schid)
{ {
register struct subchannel_id reg1 asm("1") = schid; register struct subchannel_id reg1 asm("1") = schid;
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include <asm/chpid.h> #include <asm/chpid.h>
#include <asm/schid.h> #include <asm/schid.h>
#include "orb.h"
#include "cio.h"
/* /*
* TPI info structure * TPI info structure
...@@ -87,6 +89,38 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr) ...@@ -87,6 +89,38 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr)
return ccode; 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) static inline int tpi(struct tpi_info *addr)
{ {
int ccode; 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