* Please pull git390 'for-linus' branch
@ 2007-03-19 13:16 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-03-19 13:16 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/kernel/compat_wrapper.S | 17 +++++++++++++++++
arch/s390/kernel/debug.c | 2 +-
arch/s390/kernel/early.c | 10 ++++++++--
arch/s390/kernel/ipl.c | 9 ++++-----
arch/s390/kernel/syscalls.S | 3 ++-
drivers/s390/cio/qdio.c | 26 ++++++++++++++++++--------
drivers/s390/crypto/ap_bus.c | 30 +++++++++++++++++++++++-------
drivers/s390/crypto/ap_bus.h | 1 +
drivers/s390/crypto/zcrypt_api.c | 12 ++++++------
include/asm-s390/ipl.h | 5 +++++
include/asm-s390/unistd.h | 3 ++-
11 files changed, 87 insertions(+), 31 deletions(-)
Heiko Carstens (3):
[S390] memory detection: fix off by one bug.
[S390] Wire up compat_sys_epoll_pwait.
[S390] Wire up sys_utimes.
Jean Delvare (1):
[S390] strlcpy is smart enough
Michael Holzheu (1):
[S390] reboot from and dump to SCSI under z/VM fails.
Ralph Wuerthner (2):
[S390] zcrypt: fix possible dead lock in AP bus module
[S390] zcrypt: fix possible race when unloading zcrypt driver modules
Ursula Braun (1):
[S390] cio: qdio slsb setup
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 9790129..32a69a1 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1665,3 +1665,20 @@ sys_getcpu_wrapper:
llgtr %r3,%r3 # unsigned *
llgtr %r4,%r4 # struct getcpu_cache *
jg sys_getcpu
+
+ .globl compat_sys_epoll_pwait_wrapper
+compat_sys_epoll_pwait_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # struct compat_epoll_event *
+ lgfr %r4,%r4 # int
+ lgfr %r5,%r5 # int
+ llgtr %r6,%r6 # compat_sigset_t *
+ llgf %r0,164(%r15) # compat_size_t
+ stg %r0,160(%r15)
+ jg compat_sys_epoll_pwait
+
+ .globl compat_sys_utimes_wrapper
+compat_sys_utimes_wrapper:
+ llgtr %r2,%r2 # char *
+ llgtr %r3,%r3 # struct compat_timeval *
+ jg compat_sys_utimes
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index eca3fe5..dca6eaf 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -268,7 +268,7 @@ debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size,
rc->level = level;
rc->buf_size = buf_size;
rc->entry_size = sizeof(debug_entry_t) + buf_size;
- strlcpy(rc->name, name, sizeof(rc->name)-1);
+ strlcpy(rc->name, name, sizeof(rc->name));
memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
sizeof(struct dentry*));
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index afca1c6..5e47936 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -141,9 +141,9 @@ static noinline __init void detect_machine_type(void)
machine_flags |= 4;
}
+#ifdef CONFIG_64BIT
static noinline __init int memory_fast_detect(void)
{
-
unsigned long val0 = 0;
unsigned long val1 = 0xc;
int ret = -ENOSYS;
@@ -161,9 +161,15 @@ static noinline __init int memory_fast_detect(void)
if (ret || val0 != val1)
return -ENOSYS;
- memory_chunk[0].size = val0;
+ memory_chunk[0].size = val0 + 1;
return 0;
}
+#else
+static inline int memory_fast_detect(void)
+{
+ return -ENOSYS;
+}
+#endif
#define ADDR2G (1UL << 31)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index d125a4e..f731185 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -839,7 +839,7 @@ static int __init reipl_ccw_init(void)
}
reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
- reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
+ reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
/* check if read scp info worked and set loadparm */
if (SCCB_VALID)
@@ -880,8 +880,7 @@ static int __init reipl_fcp_init(void)
} else {
reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
- reipl_block_fcp->hdr.blk0_len =
- sizeof(reipl_block_fcp->ipl_info.fcp);
+ reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
}
@@ -930,7 +929,7 @@ static int __init dump_ccw_init(void)
}
dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
- dump_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
+ dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
dump_capabilities |= IPL_TYPE_CCW;
return 0;
@@ -954,7 +953,7 @@ static int __init dump_fcp_init(void)
}
dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
- dump_block_fcp->hdr.blk0_len = sizeof(dump_block_fcp->ipl_info.fcp);
+ dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
dump_capabilities |= IPL_TYPE_FCP;
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index a52c444..c774f10 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -320,4 +320,5 @@ SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper)
NI_SYSCALL /* 310 sys_move_pages */
SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
-SYSCALL(sys_epoll_pwait,sys_epoll_pwait,sys_ni_syscall)
+SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
+SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 5b1e3ff..05fac07 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -210,9 +210,11 @@ again:
goto again;
}
if (rc < 0) {
- QDIO_DBF_TEXT3(1,trace,"sqberr");
- sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
- QDIO_DBF_TEXT3(1,trace,dbf_text);
+ QDIO_DBF_TEXT3(1,trace,"sqberr");
+ sprintf(dbf_text,"%2x,%2x",tmp_cnt,*cnt);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ sprintf(dbf_text,"%d,%d",ccq,q_no);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
QDIO_STATUS_LOOK_FOR_ERROR,
0, 0, 0, -1, -1, q->int_parm);
@@ -1250,7 +1252,6 @@ qdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used) {
QDIO_DBF_TEXT4(0,trace,"inqisdnA");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- QDIO_DBF_TEXT4(0,trace,dbf_text);
return 1;
}
if (irq->is_qebsm) {
@@ -3371,10 +3372,15 @@ qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+ int tmp = 0;
+
qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
if (irq->is_qebsm) {
- while (count)
- set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+ while (count) {
+ tmp = set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+ if (!tmp)
+ return;
+ }
return;
}
for (;;) {
@@ -3390,11 +3396,15 @@ qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+ int tmp = 0;
qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
if (irq->is_qebsm) {
- while (count)
- set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+ while (count) {
+ tmp = set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+ if (!tmp)
+ return;
+ }
return;
}
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index c7d1355..181b517 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -65,6 +65,8 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000);
MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on).");
static struct device *ap_root_device = NULL;
+static DEFINE_SPINLOCK(ap_device_lock);
+static LIST_HEAD(ap_device_list);
/**
* Workqueue & timer for bus rescan.
@@ -457,6 +459,9 @@ static int ap_device_probe(struct device *dev)
int rc;
ap_dev->drv = ap_drv;
+ spin_lock_bh(&ap_device_lock);
+ list_add(&ap_dev->list, &ap_device_list);
+ spin_unlock_bh(&ap_device_lock);
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
return rc;
}
@@ -497,6 +502,9 @@ static int ap_device_remove(struct device *dev)
ap_flush_queue(ap_dev);
if (ap_drv->remove)
ap_drv->remove(ap_dev);
+ spin_lock_bh(&ap_device_lock);
+ list_del_init(&ap_dev->list);
+ spin_unlock_bh(&ap_device_lock);
return 0;
}
@@ -772,6 +780,7 @@ static void ap_scan_bus(struct work_struct *unused)
spin_lock_init(&ap_dev->lock);
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
+ INIT_LIST_HEAD(&ap_dev->list);
if (device_type == 0)
ap_probe_device_type(ap_dev);
else
@@ -1033,14 +1042,13 @@ static void ap_poll_timeout(unsigned long unused)
* polling until bit 2^0 of the control flags is not set. If bit 2^1
* of the control flags has been set arm the poll timer.
*/
-static int __ap_poll_all(struct device *dev, void *data)
+static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
{
- struct ap_device *ap_dev = to_ap_dev(dev);
int rc;
spin_lock(&ap_dev->lock);
if (!ap_dev->unregistered) {
- rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
+ rc = ap_poll_queue(ap_dev, flags);
if (rc)
ap_dev->unregistered = 1;
} else
@@ -1054,10 +1062,15 @@ static int __ap_poll_all(struct device *dev, void *data)
static void ap_poll_all(unsigned long dummy)
{
unsigned long flags;
+ struct ap_device *ap_dev;
do {
flags = 0;
- bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all);
+ spin_lock(&ap_device_lock);
+ list_for_each_entry(ap_dev, &ap_device_list, list) {
+ __ap_poll_all(ap_dev, &flags);
+ }
+ spin_unlock(&ap_device_lock);
} while (flags & 1);
if (flags & 2)
ap_schedule_poll_timer();
@@ -1075,6 +1088,7 @@ static int ap_poll_thread(void *data)
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int requests;
+ struct ap_device *ap_dev;
set_user_nice(current, 19);
while (1) {
@@ -1092,10 +1106,12 @@ static int ap_poll_thread(void *data)
set_current_state(TASK_RUNNING);
remove_wait_queue(&ap_poll_wait, &wait);
- local_bh_disable();
flags = 0;
- bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all);
- local_bh_enable();
+ spin_lock_bh(&ap_device_lock);
+ list_for_each_entry(ap_dev, &ap_device_list, list) {
+ __ap_poll_all(ap_dev, &flags);
+ }
+ spin_unlock_bh(&ap_device_lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&ap_poll_wait, &wait);
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 83b69c0..008559e 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -106,6 +106,7 @@ struct ap_device {
struct device device;
struct ap_driver *drv; /* Pointer to AP device driver. */
spinlock_t lock; /* Per device lock. */
+ struct list_head list; /* private list of all AP devices. */
ap_qid_t qid; /* AP queue id. */
int queue_depth; /* AP queue depth.*/
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 9976139..e3625a4 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -298,14 +298,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
get_device(&zdev->ap_dev->device);
zdev->request_count++;
__zcrypt_decrease_preference(zdev);
- spin_unlock_bh(&zcrypt_device_lock);
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
rc = zdev->ops->rsa_modexpo(zdev, mex);
+ spin_lock_bh(&zcrypt_device_lock);
module_put(zdev->ap_dev->drv->driver.owner);
}
else
rc = -EAGAIN;
- spin_lock_bh(&zcrypt_device_lock);
zdev->request_count--;
__zcrypt_increase_preference(zdev);
put_device(&zdev->ap_dev->device);
@@ -373,14 +373,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
get_device(&zdev->ap_dev->device);
zdev->request_count++;
__zcrypt_decrease_preference(zdev);
- spin_unlock_bh(&zcrypt_device_lock);
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
rc = zdev->ops->rsa_modexpo_crt(zdev, crt);
+ spin_lock_bh(&zcrypt_device_lock);
module_put(zdev->ap_dev->drv->driver.owner);
}
else
rc = -EAGAIN;
- spin_lock_bh(&zcrypt_device_lock);
zdev->request_count--;
__zcrypt_increase_preference(zdev);
put_device(&zdev->ap_dev->device);
@@ -408,14 +408,14 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
get_device(&zdev->ap_dev->device);
zdev->request_count++;
__zcrypt_decrease_preference(zdev);
- spin_unlock_bh(&zcrypt_device_lock);
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
rc = zdev->ops->send_cprb(zdev, xcRB);
+ spin_lock_bh(&zcrypt_device_lock);
module_put(zdev->ap_dev->drv->driver.owner);
}
else
rc = -EAGAIN;
- spin_lock_bh(&zcrypt_device_lock);
zdev->request_count--;
__zcrypt_increase_preference(zdev);
put_device(&zdev->ap_dev->device);
diff --git a/include/asm-s390/ipl.h b/include/asm-s390/ipl.h
index 660f782..0eb6408 100644
--- a/include/asm-s390/ipl.h
+++ b/include/asm-s390/ipl.h
@@ -14,9 +14,13 @@
#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
sizeof(struct ipl_block_fcp))
+#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 8)
+
#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
sizeof(struct ipl_block_ccw))
+#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 8)
+
#define IPL_MAX_SUPPORTED_VERSION (0)
#define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \
@@ -58,6 +62,7 @@ struct ipl_block_ccw {
u8 vm_flags;
u8 reserved3[3];
u32 vm_parm_len;
+ u8 reserved4[80];
} __attribute__((packed));
struct ipl_parameter_block {
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index fb6fef9..5c6f00d 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -250,8 +250,9 @@
/* Number 310 is reserved for new sys_move_pages */
#define __NR_getcpu 311
#define __NR_epoll_pwait 312
+#define __NR_utimes 313
-#define NR_syscalls 313
+#define NR_syscalls 314
/*
* There are some system calls that are not present on 64 bit, some
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-04-04 16:39 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-04-04 16:39 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
drivers/s390/cio/device_status.c | 8 ++++++++
mm/rmap.c | 4 ++--
2 files changed, 10 insertions(+), 2 deletions(-)
Cornelia Huck (1):
[S390] cio: Fix handling of interrupt for csch().
Martin Schwidefsky (1):
[S390] page_mkclean data corruption.
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 25d99bd..aa96e67 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -221,6 +221,14 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
cdev_irb = &cdev->private->irb;
+ /*
+ * If the clear function had been performed, all formerly pending
+ * status at the subchannel has been cleared and we must not pass
+ * intermediate accumulated status to the device driver.
+ */
+ if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC)
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+
/* Copy bits which are valid only for the start function. */
if (irb->scsw.fctl & SCSW_FCTL_START_FUNC) {
/* Copy key. */
diff --git a/mm/rmap.c b/mm/rmap.c
index 22ed3f7..b82146e 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -498,9 +498,9 @@ int page_mkclean(struct page *page)
struct address_space *mapping = page_mapping(page);
if (mapping)
ret = page_mkclean_file(mapping, page);
+ if (page_test_and_clear_dirty(page))
+ ret = 1;
}
- if (page_test_and_clear_dirty(page))
- ret = 1;
return ret;
}
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-05-04 16:59 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-05-04 16:59 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
Documentation/feature-removal-schedule.txt | 17 ++
arch/s390/crypto/aes_s390.c | 15 ++-
arch/s390/kernel/kprobes.c | 3 +-
arch/s390/kernel/setup.c | 111 +++++++++++++-
arch/s390/mm/fault.c | 40 ++---
drivers/s390/block/dasd.c | 45 +++++
drivers/s390/block/dasd_eckd.c | 81 +++++++++-
drivers/s390/block/dasd_fba.c | 2 +-
drivers/s390/block/dasd_int.h | 2 +
drivers/s390/char/tape.h | 1 +
drivers/s390/char/tape_3590.c | 29 +++-
drivers/s390/char/tape_3590.h | 4 +
drivers/s390/char/tape_core.c | 3 +-
drivers/s390/cio/qdio.c | 240 ++++++++++++++++------------
drivers/s390/cio/qdio.h | 52 +++++--
drivers/s390/net/qeth.h | 3 +
drivers/s390/net/qeth_main.c | 77 +++++++++-
drivers/s390/net/qeth_mpc.h | 1 +
include/asm-s390/ccwdev.h | 6 +-
include/asm-s390/elf.h | 7 +-
include/asm-s390/kdebug.h | 18 ++-
include/asm-s390/kprobes.h | 16 +--
include/asm-s390/lowcore.h | 10 +-
23 files changed, 593 insertions(+), 190 deletions(-)
Christoph Hellwig (1):
[S390] get rid of kprobes notifier call chain.
Cornelia Huck (3):
[S390] cio: Deprecate read_dev_chars() and read_conf_data{,_lpm}().
[S390] dasd: New read device characteristics and read configuration data.
[S390] qeth: New read configuration data.
Jan Glauber (1):
[S390] aes-s390 key length.
Martin Schwidefsky (2):
[S390] Export uaccess as non-gpl symbol.
[S390] add hardware capability support (ELF_HWCAP).
Michael Holzheu (1):
[S390] tape: New read configuration data.
Ursula Braun (1):
[S390] qdio: make qdio statistics SMP-capable
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 5c88ba1..1a9e600 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -314,3 +314,20 @@ Why: Code was merged, then submitter immediately disappeared leaving
Who: David S. Miller <davem@davemloft.net>
---------------------------
+
+What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
+When: December 2007
+Why: These functions are a leftover from 2.4 times. They have several
+ problems:
+ - Duplication of checks that are done in the device driver's
+ interrupt handler
+ - common I/O layer can't do device specific error recovery
+ - device driver can't be notified for conditions happening during
+ execution of the function
+ Device drivers should issue the read device characteristics and read
+ configuration data ccws and do the appropriate error handling
+ themselves.
+Who: Cornelia Huck <cornelia.huck@de.ibm.com>
+
+---------------------------
+
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 9163635..3660ca6 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -119,7 +119,8 @@ static struct crypto_alg aes_alg = {
.cra_name = "aes",
.cra_driver_name = "aes-s390",
.cra_priority = CRYPT_S390_PRIORITY,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s390_aes_ctx),
.cra_module = THIS_MODULE,
@@ -206,7 +207,8 @@ static struct crypto_alg ecb_aes_alg = {
.cra_name = "ecb(aes)",
.cra_driver_name = "ecb-aes-s390",
.cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s390_aes_ctx),
.cra_type = &crypto_blkcipher_type,
@@ -300,7 +302,8 @@ static struct crypto_alg cbc_aes_alg = {
.cra_name = "cbc(aes)",
.cra_driver_name = "cbc-aes-s390",
.cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s390_aes_ctx),
.cra_type = &crypto_blkcipher_type,
@@ -333,10 +336,14 @@ static int __init aes_init(void)
return -EOPNOTSUPP;
/* z9 109 and z9 BC/EC only support 128 bit key length */
- if (keylen_flag == AES_KEYLEN_128)
+ if (keylen_flag == AES_KEYLEN_128) {
+ aes_alg.cra_u.cipher.cia_max_keysize = AES_MIN_KEY_SIZE;
+ ecb_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
+ cbc_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
printk(KERN_INFO
"aes_s390: hardware acceleration only available for"
"128 bit keys\n");
+ }
ret = crypto_register_alg(&aes_alg);
if (ret)
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 993f353..23c61f6 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -516,7 +516,7 @@ out:
return 1;
}
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -603,7 +603,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
ret = NOTIFY_STOP;
break;
case DIE_TRAP:
- case DIE_PAGE_FAULT:
/* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running() &&
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 3dfd098..6bfb088 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -65,7 +65,7 @@ long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
* User copy operations.
*/
struct uaccess_ops uaccess;
-EXPORT_SYMBOL_GPL(uaccess);
+EXPORT_SYMBOL(uaccess);
/*
* Machine setup..
@@ -74,6 +74,8 @@ unsigned int console_mode = 0;
unsigned int console_devno = -1;
unsigned int console_irq = -1;
unsigned long machine_flags = 0;
+unsigned long elf_hwcap = 0;
+char elf_platform[ELF_PLATFORM_SIZE];
struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
@@ -749,6 +751,98 @@ setup_memory(void)
#endif
}
+static __init unsigned int stfl(void)
+{
+ asm volatile(
+ " .insn s,0xb2b10000,0(0)\n" /* stfl */
+ "0:\n"
+ EX_TABLE(0b,0b));
+ return S390_lowcore.stfl_fac_list;
+}
+
+static __init int stfle(unsigned long long *list, int doublewords)
+{
+ typedef struct { unsigned long long _[doublewords]; } addrtype;
+ register unsigned long __nr asm("0") = doublewords - 1;
+
+ asm volatile(".insn s,0xb2b00000,%0" /* stfle */
+ : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc");
+ return __nr + 1;
+}
+
+/*
+ * Setup hardware capabilities.
+ */
+static void __init setup_hwcaps(void)
+{
+ static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
+ struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
+ unsigned long long facility_list_extended;
+ unsigned int facility_list;
+ int i;
+
+ facility_list = stfl();
+ /*
+ * The store facility list bits numbers as found in the principles
+ * of operation are numbered with bit 1UL<<31 as number 0 to
+ * bit 1UL<<0 as number 31.
+ * Bit 0: instructions named N3, "backported" to esa-mode
+ * Bit 2: z/Architecture mode is active
+ * Bit 7: the store-facility-list-extended facility is installed
+ * Bit 17: the message-security assist is installed
+ * Bit 19: the long-displacement facility is installed
+ * Bit 21: the extended-immediate facility is installed
+ * These get translated to:
+ * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
+ * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
+ * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+ */
+ for (i = 0; i < 6; i++)
+ if (facility_list & (1UL << (31 - stfl_bits[i])))
+ elf_hwcap |= 1UL << i;
+
+ /*
+ * Check for additional facilities with store-facility-list-extended.
+ * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
+ * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
+ * as stored by stfl, bits 32-xxx contain additional facilities.
+ * How many facility words are stored depends on the number of
+ * doublewords passed to the instruction. The additional facilites
+ * are:
+ * Bit 43: decimal floating point facility is installed
+ * translated to:
+ * HWCAP_S390_DFP bit 6.
+ */
+ if ((elf_hwcap & (1UL << 2)) &&
+ stfle(&facility_list_extended, 1) > 0) {
+ if (facility_list_extended & (1ULL << (64 - 43)))
+ elf_hwcap |= 1UL << 6;
+ }
+
+ switch (cpuinfo->cpu_id.machine) {
+ case 0x9672:
+#if !defined(CONFIG_64BIT)
+ default: /* Use "g5" as default for 31 bit kernels. */
+#endif
+ strcpy(elf_platform, "g5");
+ break;
+ case 0x2064:
+ case 0x2066:
+#if defined(CONFIG_64BIT)
+ default: /* Use "z900" as default for 64 bit kernels. */
+#endif
+ strcpy(elf_platform, "z900");
+ break;
+ case 0x2084:
+ case 0x2086:
+ strcpy(elf_platform, "z990");
+ break;
+ case 0x2094:
+ strcpy(elf_platform, "z9-109");
+ break;
+ }
+}
+
/*
* Setup function called from init/main.c just after the banner
* was printed.
@@ -805,6 +899,11 @@ setup_arch(char **cmdline_p)
smp_setup_cpu_possible_map();
/*
+ * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+ */
+ setup_hwcaps();
+
+ /*
* Create kernel page tables and switch to virtual addressing.
*/
paging_init();
@@ -839,8 +938,12 @@ void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
static int show_cpuinfo(struct seq_file *m, void *v)
{
+ static const char *hwcap_str[7] = {
+ "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
+ };
struct cpuinfo_S390 *cpuinfo;
unsigned long n = (unsigned long) v - 1;
+ int i;
s390_adjust_jiffies();
preempt_disable();
@@ -850,7 +953,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"bogomips per cpu: %lu.%02lu\n",
num_online_cpus(), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100);
+ seq_puts(m, "features\t: ");
+ for (i = 0; i < 7; i++)
+ if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+ seq_printf(m, "%s ", hwcap_str[i]);
+ seq_puts(m, "\n");
}
+
if (cpu_online(n)) {
#ifdef CONFIG_SMP
if (smp_processor_id() == n)
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2b76a87..91f705a 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -52,38 +52,24 @@ extern int sysctl_userprocess_debug;
extern void die(const char *,struct pt_regs *,long);
#ifdef CONFIG_KPROBES
-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-int register_page_fault_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(¬ify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb);
-}
-
-static int __kprobes __notify_page_fault(struct pt_regs *regs, long err)
-{
- struct die_args args = { .str = "page fault",
- .trapnr = 14,
- .signr = SIGSEGV };
- args.regs = regs;
- args.err = err;
- return atomic_notifier_call_chain(¬ify_page_fault_chain,
- DIE_PAGE_FAULT, &args);
-}
-
static inline int notify_page_fault(struct pt_regs *regs, long err)
{
- if (unlikely(kprobe_running()))
- return __notify_page_fault(regs, err);
- return NOTIFY_DONE;
+ int ret = 0;
+
+ /* kprobe_running() needs smp_processor_id() */
+ if (!user_mode(regs)) {
+ preempt_disable();
+ if (kprobe_running() && kprobe_fault_handler(regs, 14))
+ ret = 1;
+ preempt_enable();
+ }
+
+ return ret;
}
#else
static inline int notify_page_fault(struct pt_regs *regs, long err)
{
- return NOTIFY_DONE;
+ return 0;
}
#endif
@@ -319,7 +305,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
int space;
int si_code;
- if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ if (notify_page_fault(regs, error_code))
return;
tsk = current;
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index e71929d..9775210 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2174,6 +2174,51 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
return ret;
}
+struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device,
+ void *rdc_buffer,
+ int rdc_buffer_size, char *magic)
+{
+ struct dasd_ccw_req *cqr;
+ struct ccw1 *ccw;
+
+ cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
+
+ if (IS_ERR(cqr)) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s",
+ "Could not allocate RDC request");
+ return cqr;
+ }
+
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = CCW_CMD_RDC;
+ ccw->cda = (__u32)(addr_t)rdc_buffer;
+ ccw->count = rdc_buffer_size;
+
+ cqr->device = device;
+ cqr->expires = 10*HZ;
+ clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ cqr->retries = 2;
+ cqr->buildclk = get_clock();
+ cqr->status = DASD_CQR_FILLED;
+ return cqr;
+}
+
+
+int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
+ void **rdc_buffer, int rdc_buffer_size)
+{
+ int ret;
+ struct dasd_ccw_req *cqr;
+
+ cqr = dasd_generic_build_rdc(device, *rdc_buffer, rdc_buffer_size,
+ magic);
+ if (IS_ERR(cqr))
+ return PTR_ERR(cqr);
+
+ ret = dasd_sleep_on(cqr);
+ dasd_sfree_request(cqr, cqr->device);
+ return ret;
+}
static int __init
dasd_init(void)
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index cecab22..c9583fb 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -450,6 +450,81 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
return 0;
}
+struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device,
+ void *rcd_buffer,
+ struct ciw *ciw, __u8 lpm)
+{
+ struct dasd_ccw_req *cqr;
+ struct ccw1 *ccw;
+
+ cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
+
+ if (IS_ERR(cqr)) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s",
+ "Could not allocate RCD request");
+ return cqr;
+ }
+
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = ciw->cmd;
+ ccw->cda = (__u32)(addr_t)rcd_buffer;
+ ccw->count = ciw->count;
+
+ cqr->device = device;
+ cqr->expires = 10*HZ;
+ cqr->lpm = lpm;
+ clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ cqr->retries = 2;
+ cqr->buildclk = get_clock();
+ cqr->status = DASD_CQR_FILLED;
+ return cqr;
+}
+
+static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
+ void **rcd_buffer,
+ int *rcd_buffer_size, __u8 lpm)
+{
+ struct ciw *ciw;
+ char *rcd_buf = NULL;
+ int ret;
+ struct dasd_ccw_req *cqr;
+
+ /*
+ * scan for RCD command in extended SenseID data
+ */
+ ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
+ if (!ciw || ciw->cmd == 0) {
+ ret = -EOPNOTSUPP;
+ goto out_error;
+ }
+ rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+ if (!rcd_buf) {
+ ret = -ENOMEM;
+ goto out_error;
+ }
+ cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
+ if (IS_ERR(cqr)) {
+ ret = PTR_ERR(cqr);
+ goto out_error;
+ }
+ ret = dasd_sleep_on(cqr);
+ /*
+ * on success we update the user input parms
+ */
+ dasd_sfree_request(cqr, cqr->device);
+ if (ret)
+ goto out_error;
+
+ *rcd_buffer_size = ciw->count;
+ *rcd_buffer = rcd_buf;
+ return 0;
+out_error:
+ kfree(rcd_buf);
+ *rcd_buffer = NULL;
+ *rcd_buffer_size = 0;
+ return ret;
+}
+
static int
dasd_eckd_read_conf(struct dasd_device *device)
{
@@ -469,8 +544,8 @@ dasd_eckd_read_conf(struct dasd_device *device)
/* get configuration data per operational path */
for (lpm = 0x80; lpm; lpm>>= 1) {
if (lpm & path_data->opm){
- rc = read_conf_data_lpm(device->cdev, &conf_data,
- &conf_len, lpm);
+ rc = dasd_eckd_read_conf_lpm(device, &conf_data,
+ &conf_len, lpm);
if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */
MESSAGE(KERN_WARNING,
"Read configuration data returned "
@@ -639,7 +714,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
memset(rdc_data, 0, sizeof(rdc_data));
- rc = read_dev_chars(device->cdev, &rdc_data, 64);
+ rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
if (rc)
DEV_MESSAGE(KERN_WARNING, device,
"Read device characteristics returned "
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index be0909e..da16ead 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -135,7 +135,7 @@ dasd_fba_check_characteristics(struct dasd_device *device)
}
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
- rc = read_dev_chars(device->cdev, &rdc_data, 32);
+ rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32);
if (rc) {
DEV_MESSAGE(KERN_WARNING, device,
"Read device characteristics returned error %d",
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index a2cc69e..241294c 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -509,6 +509,8 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
int dasd_generic_set_offline (struct ccw_device *cdev);
int dasd_generic_notify(struct ccw_device *, int);
+int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int);
+
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
extern int dasd_probeonly;
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index bb4ff53..3b52f5c 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -103,6 +103,7 @@ enum tape_op {
TO_CRYPT_OFF, /* Disable encrpytion */
TO_KEKL_SET, /* Set KEK label */
TO_KEKL_QUERY, /* Query KEK label */
+ TO_RDC, /* Read device characteristics */
TO_SIZE, /* #entries in tape_op_t */
};
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 50f5eda..7e2b2ab 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -788,6 +788,7 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
case TO_SIZE:
case TO_KEKL_SET:
case TO_KEKL_QUERY:
+ case TO_RDC:
break;
}
return TAPE_IO_SUCCESS;
@@ -1549,6 +1550,26 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
return TAPE_IO_STOP;
}
+
+static int tape_3590_read_dev_chars(struct tape_device *device,
+ struct tape_3590_rdc_data *rdc_data)
+{
+ int rc;
+ struct tape_request *request;
+
+ request = tape_alloc_request(1, sizeof(*rdc_data));
+ if (IS_ERR(request))
+ return PTR_ERR(request);
+ request->op = TO_RDC;
+ tape_ccw_end(request->cpaddr, CCW_CMD_RDC, sizeof(*rdc_data),
+ request->cpdata);
+ rc = tape_do_io(device, request);
+ if (rc == 0)
+ memcpy(rdc_data, request->cpdata, sizeof(*rdc_data));
+ tape_free_request(request);
+ return rc;
+}
+
/*
* Setup device function
*/
@@ -1557,7 +1578,7 @@ tape_3590_setup_device(struct tape_device *device)
{
int rc;
struct tape_3590_disc_data *data;
- char *rdc_data;
+ struct tape_3590_rdc_data *rdc_data;
DBF_EVENT(6, "3590 device setup\n");
data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);
@@ -1566,12 +1587,12 @@ tape_3590_setup_device(struct tape_device *device)
data->read_back_op = READ_PREVIOUS;
device->discdata = data;
- rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA);
+ rdc_data = kmalloc(sizeof(*rdc_data), GFP_KERNEL | GFP_DMA);
if (!rdc_data) {
rc = -ENOMEM;
goto fail_kmalloc;
}
- rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64);
+ rc = tape_3590_read_dev_chars(device, rdc_data);
if (rc) {
DBF_LH(3, "Read device characteristics failed!\n");
goto fail_kmalloc;
@@ -1579,7 +1600,7 @@ tape_3590_setup_device(struct tape_device *device)
rc = tape_std_assign(device);
if (rc)
goto fail_rdc_data;
- if (rdc_data[31] == 0x13) {
+ if (rdc_data->data[31] == 0x13) {
PRINT_INFO("Device has crypto support\n");
data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
tape_3592_disable_crypt(device);
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h
index aa51388..4534055 100644
--- a/drivers/s390/char/tape_3590.h
+++ b/drivers/s390/char/tape_3590.h
@@ -129,6 +129,10 @@ struct tape_3590_med_sense {
char pad2[116];
} __attribute__ ((packed));
+struct tape_3590_rdc_data {
+ char data[64];
+} __attribute__ ((packed));
+
/* Datastructures for 3592 encryption support */
struct tape3592_kekl {
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index e2a8a1a..2fae633 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -73,7 +73,7 @@ const char *tape_op_verbose[TO_SIZE] =
[TO_DIS] = "DIS", [TO_ASSIGN] = "ASS",
[TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON",
[TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS",
- [TO_KEKL_QUERY] = "KLQ",
+ [TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC",
};
static int
@@ -911,6 +911,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request)
case TO_ASSIGN:
case TO_UNASSIGN:
case TO_READ_ATTMSG:
+ case TO_RDC:
if (device->tape_state == TS_INIT)
break;
if (device->tape_state == TS_UNUSED)
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 05fac07..cba64e4 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -69,7 +69,6 @@ static const char version[] = "QDIO base support version 2";
static int qdio_performance_stats = 0;
static int proc_perf_file_registration;
-static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc;
static struct qdio_perf_stats perf_stats;
static int hydra_thinints;
@@ -111,6 +110,31 @@ qdio_min(int a,int b)
}
/***************** SCRUBBER HELPER ROUTINES **********************/
+#ifdef CONFIG_64BIT
+static inline void qdio_perf_stat_inc(atomic64_t *count)
+{
+ if (qdio_performance_stats)
+ atomic64_inc(count);
+}
+
+static inline void qdio_perf_stat_dec(atomic64_t *count)
+{
+ if (qdio_performance_stats)
+ atomic64_dec(count);
+}
+#else /* CONFIG_64BIT */
+static inline void qdio_perf_stat_inc(atomic_t *count)
+{
+ if (qdio_performance_stats)
+ atomic_inc(count);
+}
+
+static inline void qdio_perf_stat_dec(atomic_t *count)
+{
+ if (qdio_performance_stats)
+ atomic_dec(count);
+}
+#endif /* CONFIG_64BIT */
static inline __u64
qdio_get_micros(void)
@@ -277,8 +301,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
QDIO_DBF_TEXT4(0,trace,"sigasync");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- if (qdio_performance_stats)
- perf_stats.siga_syncs++;
+ qdio_perf_stat_inc(&perf_stats.siga_syncs);
cc = do_siga_sync(q->schid, gpr2, gpr3);
if (cc)
@@ -323,8 +346,7 @@ qdio_siga_output(struct qdio_q *q)
__u32 busy_bit;
__u64 start_time=0;
- if (qdio_performance_stats)
- perf_stats.siga_outs++;
+ qdio_perf_stat_inc(&perf_stats.siga_outs);
QDIO_DBF_TEXT4(0,trace,"sigaout");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -358,8 +380,7 @@ qdio_siga_input(struct qdio_q *q)
QDIO_DBF_TEXT4(0,trace,"sigain");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
- if (qdio_performance_stats)
- perf_stats.siga_ins++;
+ qdio_perf_stat_inc(&perf_stats.siga_ins);
cc = do_siga_input(q->schid, q->mask);
@@ -953,8 +974,7 @@ __qdio_outbound_processing(struct qdio_q *q)
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
- if (qdio_performance_stats)
- o_p_c++;
+ qdio_perf_stat_inc(&perf_stats.outbound_tl_runs_resched);
/* as we're sissies, we'll check next time */
if (likely(!atomic_read(&q->is_in_shutdown))) {
qdio_mark_q(q);
@@ -962,10 +982,8 @@ __qdio_outbound_processing(struct qdio_q *q)
}
return;
}
- if (qdio_performance_stats) {
- o_p_nc++;
- perf_stats.tl_runs++;
- }
+ qdio_perf_stat_inc(&perf_stats.outbound_tl_runs);
+ qdio_perf_stat_inc(&perf_stats.tl_runs);
/* see comment in qdio_kick_outbound_q */
siga_attempts=atomic_read(&q->busy_siga_counter);
@@ -1139,17 +1157,6 @@ qdio_has_inbound_q_moved(struct qdio_q *q)
{
int i;
- static int old_pcis=0;
- static int old_thinints=0;
-
- if (qdio_performance_stats) {
- if ((old_pcis==perf_stats.pcis)&&
- (old_thinints==perf_stats.thinints))
- perf_stats.start_time_inbound=NOW;
- else
- old_pcis=perf_stats.pcis;
- }
-
i=qdio_get_inbound_buffer_frontier(q);
if ( (i!=GET_SAVED_FRONTIER(q)) ||
(q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
@@ -1337,10 +1344,7 @@ qdio_kick_inbound_handler(struct qdio_q *q)
q->siga_error=0;
q->error_status_flags=0;
- if (qdio_performance_stats) {
- perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
- perf_stats.inbound_cnt++;
- }
+ qdio_perf_stat_inc(&perf_stats.inbound_cnt);
}
static void
@@ -1360,8 +1364,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
*/
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
- if (qdio_performance_stats)
- ii_p_c++;
+ qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched);
/*
* as we might just be about to stop polling, we make
* sure that we check again at least once more
@@ -1369,8 +1372,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
tiqdio_sched_tl();
return;
}
- if (qdio_performance_stats)
- ii_p_nc++;
+ qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs);
if (unlikely(atomic_read(&q->is_in_shutdown))) {
qdio_unmark_q(q);
goto out;
@@ -1412,8 +1414,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
for (i=0;i<irq_ptr->no_output_qs;i++) {
oq = irq_ptr->output_qs[i];
if (!qdio_is_outbound_q_done(oq)) {
- if (qdio_performance_stats)
- perf_stats.tl_runs--;
+ qdio_perf_stat_dec(&perf_stats.tl_runs);
__qdio_outbound_processing(oq);
}
}
@@ -1452,8 +1453,7 @@ __qdio_inbound_processing(struct qdio_q *q)
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
- if (qdio_performance_stats)
- i_p_c++;
+ qdio_perf_stat_inc(&perf_stats.inbound_tl_runs_resched);
/* as we're sissies, we'll check next time */
if (likely(!atomic_read(&q->is_in_shutdown))) {
qdio_mark_q(q);
@@ -1461,10 +1461,8 @@ __qdio_inbound_processing(struct qdio_q *q)
}
return;
}
- if (qdio_performance_stats) {
- i_p_nc++;
- perf_stats.tl_runs++;
- }
+ qdio_perf_stat_inc(&perf_stats.inbound_tl_runs);
+ qdio_perf_stat_inc(&perf_stats.tl_runs);
again:
if (qdio_has_inbound_q_moved(q)) {
@@ -1510,8 +1508,7 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
- if (qdio_performance_stats)
- ii_p_c++;
+ qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched);
/*
* as we might just be about to stop polling, we make
* sure that we check again at least once more
@@ -1602,8 +1599,7 @@ tiqdio_tl(unsigned long data)
{
QDIO_DBF_TEXT4(0,trace,"iqdio_tl");
- if (qdio_performance_stats)
- perf_stats.tl_runs++;
+ qdio_perf_stat_inc(&perf_stats.tl_runs);
tiqdio_inbound_checks();
}
@@ -1914,10 +1910,7 @@ tiqdio_thinint_handler(void)
{
QDIO_DBF_TEXT4(0,trace,"thin_int");
- if (qdio_performance_stats) {
- perf_stats.thinints++;
- perf_stats.start_time_inbound=NOW;
- }
+ qdio_perf_stat_inc(&perf_stats.thinints);
/* SVS only when needed:
* issue SVS to benefit from iqdio interrupt avoidance
@@ -1972,17 +1965,12 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
int i;
struct qdio_q *q;
- if (qdio_performance_stats) {
- perf_stats.pcis++;
- perf_stats.start_time_inbound=NOW;
- }
+ qdio_perf_stat_inc(&perf_stats.pcis);
for (i=0;i<irq_ptr->no_input_qs;i++) {
q=irq_ptr->input_qs[i];
if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
qdio_mark_q(q);
else {
- if (qdio_performance_stats)
- perf_stats.tl_runs--;
__qdio_inbound_processing(q);
}
}
@@ -1992,8 +1980,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
q=irq_ptr->output_qs[i];
if (qdio_is_outbound_q_done(q))
continue;
- if (qdio_performance_stats)
- perf_stats.tl_runs--;
+ qdio_perf_stat_dec(&perf_stats.tl_runs);
if (!irq_ptr->sync_done_on_outb_pcis)
SYNC_MEMORY;
__qdio_outbound_processing(q);
@@ -3463,18 +3450,12 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
/* This is the outbound handling of queues */
- if (qdio_performance_stats)
- perf_stats.start_time_outbound=NOW;
-
qdio_do_qdio_fill_output(q,qidx,count,buffers);
used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count;
if (callflags&QDIO_FLAG_DONT_SIGA) {
- if (qdio_performance_stats) {
- perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
- perf_stats.outbound_cnt++;
- }
+ qdio_perf_stat_inc(&perf_stats.outbound_cnt);
return;
}
if (q->is_iqdio_q) {
@@ -3504,8 +3485,7 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
qdio_kick_outbound_q(q);
} else {
QDIO_DBF_TEXT3(0,trace, "fast-req");
- if (qdio_performance_stats)
- perf_stats.fast_reqs++;
+ qdio_perf_stat_inc(&perf_stats.fast_reqs);
}
}
/*
@@ -3516,10 +3496,7 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
__qdio_outbound_processing(q);
}
- if (qdio_performance_stats) {
- perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
- perf_stats.outbound_cnt++;
- }
+ qdio_perf_stat_inc(&perf_stats.outbound_cnt);
}
/* count must be 1 in iqdio */
@@ -3589,33 +3566,67 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
return 0;
#define _OUTP_IT(x...) c+=sprintf(buffer+c,x)
- _OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c);
- _OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c);
- _OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c);
- _OUTP_IT("Number of tasklet runs (total) : %lu\n",
- perf_stats.tl_runs);
+#ifdef CONFIG_64BIT
+ _OUTP_IT("Number of tasklet runs (total) : %li\n",
+ (long)atomic64_read(&perf_stats.tl_runs));
+ _OUTP_IT("Inbound tasklet runs tried/retried : %li/%li\n",
+ (long)atomic64_read(&perf_stats.inbound_tl_runs),
+ (long)atomic64_read(&perf_stats.inbound_tl_runs_resched));
+ _OUTP_IT("Inbound-thin tasklet runs tried/retried : %li/%li\n",
+ (long)atomic64_read(&perf_stats.inbound_thin_tl_runs),
+ (long)atomic64_read(&perf_stats.inbound_thin_tl_runs_resched));
+ _OUTP_IT("Outbound tasklet runs tried/retried : %li/%li\n",
+ (long)atomic64_read(&perf_stats.outbound_tl_runs),
+ (long)atomic64_read(&perf_stats.outbound_tl_runs_resched));
_OUTP_IT("\n");
- _OUTP_IT("Number of SIGA sync's issued : %lu\n",
- perf_stats.siga_syncs);
- _OUTP_IT("Number of SIGA in's issued : %lu\n",
- perf_stats.siga_ins);
- _OUTP_IT("Number of SIGA out's issued : %lu\n",
- perf_stats.siga_outs);
- _OUTP_IT("Number of PCIs caught : %lu\n",
- perf_stats.pcis);
- _OUTP_IT("Number of adapter interrupts caught : %lu\n",
- perf_stats.thinints);
- _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %lu\n",
- perf_stats.fast_reqs);
+ _OUTP_IT("Number of SIGA sync's issued : %li\n",
+ (long)atomic64_read(&perf_stats.siga_syncs));
+ _OUTP_IT("Number of SIGA in's issued : %li\n",
+ (long)atomic64_read(&perf_stats.siga_ins));
+ _OUTP_IT("Number of SIGA out's issued : %li\n",
+ (long)atomic64_read(&perf_stats.siga_outs));
+ _OUTP_IT("Number of PCIs caught : %li\n",
+ (long)atomic64_read(&perf_stats.pcis));
+ _OUTP_IT("Number of adapter interrupts caught : %li\n",
+ (long)atomic64_read(&perf_stats.thinints));
+ _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %li\n",
+ (long)atomic64_read(&perf_stats.fast_reqs));
_OUTP_IT("\n");
- _OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n",
- perf_stats.inbound_time);
- _OUTP_IT("Number of inbound transfers : %lu\n",
- perf_stats.inbound_cnt);
- _OUTP_IT("Total time of all outbound do_QDIOs (us) : %lu\n",
- perf_stats.outbound_time);
- _OUTP_IT("Number of do_QDIOs outbound : %lu\n",
- perf_stats.outbound_cnt);
+ _OUTP_IT("Number of inbound transfers : %li\n",
+ (long)atomic64_read(&perf_stats.inbound_cnt));
+ _OUTP_IT("Number of do_QDIOs outbound : %li\n",
+ (long)atomic64_read(&perf_stats.outbound_cnt));
+#else /* CONFIG_64BIT */
+ _OUTP_IT("Number of tasklet runs (total) : %i\n",
+ atomic_read(&perf_stats.tl_runs));
+ _OUTP_IT("Inbound tasklet runs tried/retried : %i/%i\n",
+ atomic_read(&perf_stats.inbound_tl_runs),
+ atomic_read(&perf_stats.inbound_tl_runs_resched));
+ _OUTP_IT("Inbound-thin tasklet runs tried/retried : %i/%i\n",
+ atomic_read(&perf_stats.inbound_thin_tl_runs),
+ atomic_read(&perf_stats.inbound_thin_tl_runs_resched));
+ _OUTP_IT("Outbound tasklet runs tried/retried : %i/%i\n",
+ atomic_read(&perf_stats.outbound_tl_runs),
+ atomic_read(&perf_stats.outbound_tl_runs_resched));
+ _OUTP_IT("\n");
+ _OUTP_IT("Number of SIGA sync's issued : %i\n",
+ atomic_read(&perf_stats.siga_syncs));
+ _OUTP_IT("Number of SIGA in's issued : %i\n",
+ atomic_read(&perf_stats.siga_ins));
+ _OUTP_IT("Number of SIGA out's issued : %i\n",
+ atomic_read(&perf_stats.siga_outs));
+ _OUTP_IT("Number of PCIs caught : %i\n",
+ atomic_read(&perf_stats.pcis));
+ _OUTP_IT("Number of adapter interrupts caught : %i\n",
+ atomic_read(&perf_stats.thinints));
+ _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %i\n",
+ atomic_read(&perf_stats.fast_reqs));
+ _OUTP_IT("\n");
+ _OUTP_IT("Number of inbound transfers : %i\n",
+ atomic_read(&perf_stats.inbound_cnt));
+ _OUTP_IT("Number of do_QDIOs outbound : %i\n",
+ atomic_read(&perf_stats.outbound_cnt));
+#endif /* CONFIG_64BIT */
_OUTP_IT("\n");
return c;
@@ -3642,8 +3653,6 @@ qdio_add_procfs_entry(void)
static void
qdio_remove_procfs_entry(void)
{
- perf_stats.tl_runs=0;
-
if (!proc_perf_file_registration) /* means if it went ok earlier */
remove_proc_entry(QDIO_PERF,&proc_root);
}
@@ -3671,13 +3680,38 @@ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count
qdio_performance_stats = i;
if (i==0) {
/* reset perf. stat. info */
- i_p_nc = 0;
- i_p_c = 0;
- ii_p_nc = 0;
- ii_p_c = 0;
- o_p_nc = 0;
- o_p_c = 0;
- memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
+#ifdef CONFIG_64BIT
+ atomic64_set(&perf_stats.tl_runs, 0);
+ atomic64_set(&perf_stats.outbound_tl_runs, 0);
+ atomic64_set(&perf_stats.inbound_tl_runs, 0);
+ atomic64_set(&perf_stats.inbound_tl_runs_resched, 0);
+ atomic64_set(&perf_stats.inbound_thin_tl_runs, 0);
+ atomic64_set(&perf_stats.inbound_thin_tl_runs_resched,
+ 0);
+ atomic64_set(&perf_stats.siga_outs, 0);
+ atomic64_set(&perf_stats.siga_ins, 0);
+ atomic64_set(&perf_stats.siga_syncs, 0);
+ atomic64_set(&perf_stats.pcis, 0);
+ atomic64_set(&perf_stats.thinints, 0);
+ atomic64_set(&perf_stats.fast_reqs, 0);
+ atomic64_set(&perf_stats.outbound_cnt, 0);
+ atomic64_set(&perf_stats.inbound_cnt, 0);
+#else /* CONFIG_64BIT */
+ atomic_set(&perf_stats.tl_runs, 0);
+ atomic_set(&perf_stats.outbound_tl_runs, 0);
+ atomic_set(&perf_stats.inbound_tl_runs, 0);
+ atomic_set(&perf_stats.inbound_tl_runs_resched, 0);
+ atomic_set(&perf_stats.inbound_thin_tl_runs, 0);
+ atomic_set(&perf_stats.inbound_thin_tl_runs_resched, 0);
+ atomic_set(&perf_stats.siga_outs, 0);
+ atomic_set(&perf_stats.siga_ins, 0);
+ atomic_set(&perf_stats.siga_syncs, 0);
+ atomic_set(&perf_stats.pcis, 0);
+ atomic_set(&perf_stats.thinints, 0);
+ atomic_set(&perf_stats.fast_reqs, 0);
+ atomic_set(&perf_stats.outbound_cnt, 0);
+ atomic_set(&perf_stats.inbound_cnt, 0);
+#endif /* CONFIG_64BIT */
}
} else {
QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n");
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index ec9af72..2895392 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -406,21 +406,43 @@ do_clear_global_summary(void)
#define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
struct qdio_perf_stats {
- unsigned long tl_runs;
-
- unsigned long siga_outs;
- unsigned long siga_ins;
- unsigned long siga_syncs;
- unsigned long pcis;
- unsigned long thinints;
- unsigned long fast_reqs;
-
- __u64 start_time_outbound;
- unsigned long outbound_cnt;
- unsigned long outbound_time;
- __u64 start_time_inbound;
- unsigned long inbound_cnt;
- unsigned long inbound_time;
+#ifdef CONFIG_64BIT
+ atomic64_t tl_runs;
+ atomic64_t outbound_tl_runs;
+ atomic64_t outbound_tl_runs_resched;
+ atomic64_t inbound_tl_runs;
+ atomic64_t inbound_tl_runs_resched;
+ atomic64_t inbound_thin_tl_runs;
+ atomic64_t inbound_thin_tl_runs_resched;
+
+ atomic64_t siga_outs;
+ atomic64_t siga_ins;
+ atomic64_t siga_syncs;
+ atomic64_t pcis;
+ atomic64_t thinints;
+ atomic64_t fast_reqs;
+
+ atomic64_t outbound_cnt;
+ atomic64_t inbound_cnt;
+#else /* CONFIG_64BIT */
+ atomic_t tl_runs;
+ atomic_t outbound_tl_runs;
+ atomic_t outbound_tl_runs_resched;
+ atomic_t inbound_tl_runs;
+ atomic_t inbound_tl_runs_resched;
+ atomic_t inbound_thin_tl_runs;
+ atomic_t inbound_thin_tl_runs_resched;
+
+ atomic_t siga_outs;
+ atomic_t siga_ins;
+ atomic_t siga_syncs;
+ atomic_t pcis;
+ atomic_t thinints;
+ atomic_t fast_reqs;
+
+ atomic_t outbound_cnt;
+ atomic_t inbound_cnt;
+#endif /* CONFIG_64BIT */
};
/* unlikely as the later the better */
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 84b108d..b34eb82 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -288,6 +288,7 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
*/
#define IF_NAME_LEN 16
#define QETH_TX_TIMEOUT 100 * HZ
+#define QETH_RCD_TIMEOUT 60 * HZ
#define QETH_HEADER_SIZE 32
#define MAX_PORTNO 15
#define QETH_FAKE_LL_LEN_ETH ETH_HLEN
@@ -582,6 +583,8 @@ enum qeth_channel_states {
CH_STATE_ACTIVATING,
CH_STATE_HALTED,
CH_STATE_STOPPED,
+ CH_STATE_RCD,
+ CH_STATE_RCD_DONE,
};
/**
* card state machine
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index ad7792d..6fd8870 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -315,7 +315,8 @@ qeth_alloc_card(void)
}
static long
-__qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
+ struct irb *irb)
{
if (!IS_ERR(irb))
return 0;
@@ -330,6 +331,14 @@ __qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
QETH_DBF_TEXT(trace, 2, "ckirberr");
QETH_DBF_TEXT_(trace, 2, " rc%d", -ETIMEDOUT);
+ if (intparm == QETH_RCD_PARM) {
+ struct qeth_card *card = CARD_FROM_CDEV(cdev);
+
+ if (card && (card->data.ccwdev == cdev)) {
+ card->data.state = CH_STATE_DOWN;
+ wake_up(&card->wait_q);
+ }
+ }
break;
default:
PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
@@ -401,7 +410,7 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
QETH_DBF_TEXT(trace,5,"irq");
- if (__qeth_check_irb_error(cdev, irb))
+ if (__qeth_check_irb_error(cdev, intparm, irb))
return;
cstat = irb->scsw.cstat;
dstat = irb->scsw.dstat;
@@ -429,7 +438,8 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
channel->state = CH_STATE_HALTED;
/*let's wake up immediately on data channel*/
- if ((channel == &card->data) && (intparm != 0))
+ if ((channel == &card->data) && (intparm != 0) &&
+ (intparm != QETH_RCD_PARM))
goto out;
if (intparm == QETH_CLEAR_CHANNEL_PARM) {
@@ -453,6 +463,10 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
HEXDUMP16(WARN,"irb: ",irb);
HEXDUMP16(WARN,"sense data: ",irb->ecw);
}
+ if (intparm == QETH_RCD_PARM) {
+ channel->state = CH_STATE_DOWN;
+ goto out;
+ }
rc = qeth_get_problem(cdev,irb);
if (rc) {
qeth_schedule_recovery(card);
@@ -460,6 +474,10 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
}
+ if (intparm == QETH_RCD_PARM) {
+ channel->state = CH_STATE_RCD_DONE;
+ goto out;
+ }
if (intparm) {
buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
buffer->state = BUF_STATE_PROCESSED;
@@ -1204,6 +1222,54 @@ qeth_probe_device(struct ccwgroup_device *gdev)
}
+static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+ int *length)
+{
+ struct ciw *ciw;
+ char *rcd_buf;
+ int ret;
+ struct qeth_channel *channel = &card->data;
+ unsigned long flags;
+
+ /*
+ * scan for RCD command in extended SenseID data
+ */
+ ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+ if (!ciw || ciw->cmd == 0)
+ return -EOPNOTSUPP;
+ rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+ if (!rcd_buf)
+ return -ENOMEM;
+
+ channel->ccw.cmd_code = ciw->cmd;
+ channel->ccw.cda = (__u32) __pa (rcd_buf);
+ channel->ccw.count = ciw->count;
+ channel->ccw.flags = CCW_FLAG_SLI;
+ channel->state = CH_STATE_RCD;
+ spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+ ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+ QETH_RCD_PARM, LPM_ANYPATH, 0,
+ QETH_RCD_TIMEOUT);
+ spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+ if (!ret)
+ wait_event(card->wait_q,
+ (channel->state == CH_STATE_RCD_DONE ||
+ channel->state == CH_STATE_DOWN));
+ if (channel->state == CH_STATE_DOWN)
+ ret = -EIO;
+ else
+ channel->state = CH_STATE_DOWN;
+ if (ret) {
+ kfree(rcd_buf);
+ *buffer = NULL;
+ *length = 0;
+ } else {
+ *length = ciw->count;
+ *buffer = rcd_buf;
+ }
+ return ret;
+}
+
static int
qeth_get_unitaddr(struct qeth_card *card)
{
@@ -1212,9 +1278,9 @@ qeth_get_unitaddr(struct qeth_card *card)
int rc;
QETH_DBF_TEXT(setup, 2, "getunit");
- rc = read_conf_data(CARD_DDEV(card), (void **) &prcd, &length);
+ rc = qeth_read_conf_data(card, (void **) &prcd, &length);
if (rc) {
- PRINT_ERR("read_conf_data for device %s returned %i\n",
+ PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
CARD_DDEV_ID(card), rc);
return rc;
}
@@ -1223,6 +1289,7 @@ qeth_get_unitaddr(struct qeth_card *card)
card->info.cula = prcd[63];
card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
(prcd[0x11] == _ascebc['M']));
+ kfree(prcd);
return 0;
}
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 0477c47..d74bc43 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -37,6 +37,7 @@ extern unsigned char IPA_PDU_HEADER[];
#define QETH_CLEAR_CHANNEL_PARM -10
#define QETH_HALT_CHANNEL_PARM -11
+#define QETH_RCD_PARM -12
/*****************************************************************************/
/* IP Assist related definitions */
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index cfc8153..6795ece 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -164,9 +164,9 @@ extern int ccw_device_resume(struct ccw_device *);
extern int ccw_device_halt(struct ccw_device *, unsigned long);
extern int ccw_device_clear(struct ccw_device *, unsigned long);
-extern int read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
-extern int read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
-extern int read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
+extern int __deprecated read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
+extern int __deprecated read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
+extern int __deprecated read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
int *length, __u8 lpm);
extern int ccw_device_set_online(struct ccw_device *cdev);
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index c0d629d..91d0632 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -188,7 +188,8 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
/* This yields a mask that user programs can use to figure out what
instruction set this CPU supports. */
-#define ELF_HWCAP (0)
+extern unsigned long elf_hwcap;
+#define ELF_HWCAP (elf_hwcap)
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
@@ -197,7 +198,9 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
For the moment, we have only optimizations for the Intel generations,
but that could change... */
-#define ELF_PLATFORM (NULL)
+#define ELF_PLATFORM_SIZE 8
+extern char elf_platform[];
+#define ELF_PLATFORM (elf_platform)
#ifndef __s390x__
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
diff --git a/include/asm-s390/kdebug.h b/include/asm-s390/kdebug.h
index 1b50f89..d2d7ad2 100644
--- a/include/asm-s390/kdebug.h
+++ b/include/asm-s390/kdebug.h
@@ -22,8 +22,21 @@ struct die_args {
*/
extern int register_die_notifier(struct notifier_block *);
extern int unregister_die_notifier(struct notifier_block *);
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
+
+/*
+ * These are only here because kprobes.c wants them to implement a
+ * blatant layering violation. Will hopefully go away soon once all
+ * architectures are updated.
+ */
+static inline int register_page_fault_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
extern struct atomic_notifier_head s390die_chain;
enum die_val {
@@ -39,7 +52,6 @@ enum die_val {
DIE_GPF,
DIE_CALL,
DIE_NMI_IPI,
- DIE_PAGE_FAULT,
};
static inline int notify_die(enum die_val val, const char *str,
diff --git a/include/asm-s390/kprobes.h b/include/asm-s390/kprobes.h
index b847ff0..830fe4c 100644
--- a/include/asm-s390/kprobes.h
+++ b/include/asm-s390/kprobes.h
@@ -97,18 +97,10 @@ void kretprobe_trampoline(void);
int is_prohibited_opcode(kprobe_opcode_t *instruction);
void get_instruction_type(struct arch_specific_insn *ainsn);
+int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+
#define flush_insn_slot(p) do { } while (0)
#endif /* _ASM_S390_KPROBES_H */
-
-#ifdef CONFIG_KPROBES
-
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
-#else /* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return 0;
-}
-#endif
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index ffc9788..801a6fd 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -229,17 +229,19 @@ struct _lowcore
__u16 subchannel_nr; /* 0x0ba */
__u32 io_int_parm; /* 0x0bc */
__u32 io_int_word; /* 0x0c0 */
- __u8 pad3[0xD4-0xC4]; /* 0x0c4 */
+ __u8 pad3[0xc8-0xc4]; /* 0x0c4 */
+ __u32 stfl_fac_list; /* 0x0c8 */
+ __u8 pad4[0xd4-0xcc]; /* 0x0cc */
__u32 extended_save_area_addr; /* 0x0d4 */
__u32 cpu_timer_save_area[2]; /* 0x0d8 */
__u32 clock_comp_save_area[2]; /* 0x0e0 */
__u32 mcck_interruption_code[2]; /* 0x0e8 */
- __u8 pad4[0xf4-0xf0]; /* 0x0f0 */
+ __u8 pad5[0xf4-0xf0]; /* 0x0f0 */
__u32 external_damage_code; /* 0x0f4 */
__u32 failing_storage_address; /* 0x0f8 */
- __u8 pad5[0x100-0xfc]; /* 0x0fc */
+ __u8 pad6[0x100-0xfc]; /* 0x0fc */
__u32 st_status_fixed_logout[4];/* 0x100 */
- __u8 pad6[0x120-0x110]; /* 0x110 */
+ __u8 pad7[0x120-0x110]; /* 0x110 */
__u32 access_regs_save_area[16];/* 0x120 */
__u32 floating_pt_save_area[8]; /* 0x160 */
__u32 gpregs_save_area[16]; /* 0x180 */
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-05-31 15:40 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-05-31 15:40 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/hypfs/hypfs_diag.c | 17 +++++++++++--
arch/s390/kernel/debug.c | 22 +++++++++---------
arch/s390/kernel/setup.c | 4 +-
arch/s390/kernel/smp.c | 6 ++--
drivers/s390/block/dasd_eer.c | 16 ++++++------
drivers/s390/char/raw3270.c | 10 ++++----
drivers/s390/cio/device.c | 49 +++++++++++++++++++++++++++++++---------
drivers/s390/cio/device_fsm.c | 6 +++++
8 files changed, 87 insertions(+), 43 deletions(-)
Christoph Hellwig (3):
[S390] dasd_eer: use mutex instead of semaphore
[S390] arch/s390/kernel/debug.c: use mutex instead of semaphore
[S390] raw3270: use mutex instead of semaphore
Cornelia Huck (1):
[S390] cio: Use device_schedule_callback() for removing disconnected devices.
Heiko Carstens (1):
[S390] Fix section annotations.
Michael Holzheu (1):
[S390] Add exception handler for diagnose 224
Peter Oberparleiter (1):
[S390] cio: deregister ccw device when pgid disband failed
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 2782cf9..b9a1ce1 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -481,9 +481,17 @@ out:
/* Diagnose 224 functions */
-static void diag224(void *ptr)
+static int diag224(void *ptr)
{
- asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
+ int rc = -ENOTSUPP;
+
+ asm volatile(
+ " diag %1,%2,0x224\n"
+ "0: lhi %0,0x0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "+d" (rc) :"d" (0), "d" (ptr) : "memory");
+ return rc;
}
static int diag224_get_name_table(void)
@@ -492,7 +500,10 @@ static int diag224_get_name_table(void)
diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
if (!diag224_cpu_names)
return -ENOMEM;
- diag224(diag224_cpu_names);
+ if (diag224(diag224_cpu_names)) {
+ kfree(diag224_cpu_names);
+ return -ENOTSUPP;
+ }
EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
return 0;
}
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index dca6eaf..1b2f5ce 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -163,7 +163,7 @@ unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
static debug_info_t *debug_area_first = NULL;
static debug_info_t *debug_area_last = NULL;
-static DECLARE_MUTEX(debug_lock);
+static DEFINE_MUTEX(debug_mutex);
static int initialized;
@@ -576,7 +576,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
int rc = 0;
file_private_info_t *p_info;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
p_info = ((file_private_info_t *) file->private_data);
if (p_info->view->input_proc)
rc = p_info->view->input_proc(p_info->debug_info_org,
@@ -584,7 +584,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
length, offset);
else
rc = -EPERM;
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc; /* number of input characters */
}
@@ -602,7 +602,7 @@ debug_open(struct inode *inode, struct file *file)
file_private_info_t *p_info;
debug_info_t *debug_info, *debug_info_snapshot;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_info = file->f_path.dentry->d_inode->i_private;
/* find debug view */
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
@@ -653,7 +653,7 @@ found:
file->private_data = p_info;
debug_info_get(debug_info);
out:
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
@@ -688,7 +688,7 @@ debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
if (!initialized)
BUG();
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
/* create new debug_info */
@@ -702,7 +702,7 @@ out:
if (!rc){
printk(KERN_ERR "debug: debug_register failed for %s\n",name);
}
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
@@ -716,9 +716,9 @@ debug_unregister(debug_info_t * id)
{
if (!id)
goto out;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_info_put(id);
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
out:
return;
@@ -1054,11 +1054,11 @@ __init debug_init(void)
int rc = 0;
s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
printk(KERN_INFO "debug: Initialization complete\n");
initialized = 1;
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 6bfb088..51d6309 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -102,7 +102,7 @@ static struct resource data_resource = {
/*
* cpu_init() initializes state that is per-CPU.
*/
-void __devinit cpu_init (void)
+void __cpuinit cpu_init(void)
{
int addr = hard_smp_processor_id();
@@ -915,7 +915,7 @@ setup_arch(char **cmdline_p)
setup_zfcpdump(console_devno);
}
-void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
{
printk("cpu %d "
#ifdef CONFIG_SMP
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 09f028a..8ff2fea 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -492,7 +492,7 @@ static unsigned int __init smp_count_cpus(void)
/*
* Activate a secondary processor.
*/
-int __devinit start_secondary(void *cpuvoid)
+int __cpuinit start_secondary(void *cpuvoid)
{
/* Setup the cpu */
cpu_init();
@@ -741,7 +741,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_create_idle(cpu);
}
-void __devinit smp_prepare_boot_cpu(void)
+void __init smp_prepare_boot_cpu(void)
{
BUG_ON(smp_processor_id() != 0);
@@ -750,7 +750,7 @@ void __devinit smp_prepare_boot_cpu(void)
current_set[0] = current;
}
-void smp_cpus_done(unsigned int max_cpus)
+void __init smp_cpus_done(unsigned int max_cpus)
{
cpu_present_map = cpu_possible_map;
}
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index a1dc8c4..0c081a6 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -14,9 +14,9 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/poll.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <asm/atomic.h>
#include <asm/ebcdic.h>
@@ -514,7 +514,7 @@ void dasd_eer_disable(struct dasd_device *device)
* to transfer in a readbuffer, which is protected by the readbuffer_mutex.
*/
static char readbuffer[PAGE_SIZE];
-static DECLARE_MUTEX(readbuffer_mutex);
+static DEFINE_MUTEX(readbuffer_mutex);
static int dasd_eer_open(struct inode *inp, struct file *filp)
{
@@ -579,7 +579,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
struct eerbuffer *eerb;
eerb = (struct eerbuffer *) filp->private_data;
- if (down_interruptible(&readbuffer_mutex))
+ if (mutex_lock_interruptible(&readbuffer_mutex))
return -ERESTARTSYS;
spin_lock_irqsave(&bufferlock, flags);
@@ -588,7 +588,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
/* has been deleted */
eerb->residual = 0;
spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
return -EIO;
} else if (eerb->residual > 0) {
/* OK we still have a second half of a record to deliver */
@@ -602,7 +602,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
if (!tc) {
/* no data available */
spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
rc = wait_event_interruptible(
@@ -610,7 +610,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
eerb->head != eerb->tail);
if (rc)
return rc;
- if (down_interruptible(&readbuffer_mutex))
+ if (mutex_lock_interruptible(&readbuffer_mutex))
return -ERESTARTSYS;
spin_lock_irqsave(&bufferlock, flags);
}
@@ -626,11 +626,11 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
spin_unlock_irqrestore(&bufferlock, flags);
if (copy_to_user(buf, readbuffer, effective_count)) {
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
return -EFAULT;
}
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
return effective_count;
}
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index f6ef90e..743944a 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -487,7 +487,7 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */
} __attribute__ ((packed));
static struct diag210 raw3270_init_diag210;
-static DECLARE_MUTEX(raw3270_init_sem);
+static DEFINE_MUTEX(raw3270_init_mutex);
static int
raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
@@ -713,7 +713,7 @@ raw3270_size_device(struct raw3270 *rp)
{
int rc;
- down(&raw3270_init_sem);
+ mutex_lock(&raw3270_init_mutex);
rp->view = &raw3270_init_view;
raw3270_init_view.dev = rp;
if (MACHINE_IS_VM)
@@ -722,7 +722,7 @@ raw3270_size_device(struct raw3270 *rp)
rc = __raw3270_size_device(rp);
raw3270_init_view.dev = NULL;
rp->view = NULL;
- up(&raw3270_init_sem);
+ mutex_unlock(&raw3270_init_mutex);
if (rc == 0) { /* Found something. */
/* Try to find a model. */
rp->model = 0;
@@ -749,7 +749,7 @@ raw3270_reset_device(struct raw3270 *rp)
{
int rc;
- down(&raw3270_init_sem);
+ mutex_lock(&raw3270_init_mutex);
memset(&rp->init_request, 0, sizeof(rp->init_request));
memset(&rp->init_data, 0, sizeof(rp->init_data));
/* Store reset data stream to init_data/init_request */
@@ -764,7 +764,7 @@ raw3270_reset_device(struct raw3270 *rp)
rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
raw3270_init_view.dev = NULL;
rp->view = NULL;
- up(&raw3270_init_sem);
+ mutex_unlock(&raw3270_init_mutex);
return rc;
}
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a8b373f..6b264bd 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -296,30 +296,57 @@ static void ccw_device_unregister(struct ccw_device *cdev)
device_del(&cdev->dev);
}
+static void ccw_device_remove_orphan_cb(struct device *dev)
+{
+ struct ccw_device *cdev = to_ccwdev(dev);
+
+ ccw_device_unregister(cdev);
+ put_device(&cdev->dev);
+}
+
+static void ccw_device_remove_sch_cb(struct device *dev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ css_sch_device_unregister(sch);
+ /* Reset intparm to zeroes. */
+ sch->schib.pmcw.intparm = 0;
+ cio_modify(sch);
+ put_device(&sch->dev);
+}
+
static void
ccw_device_remove_disconnected(struct ccw_device *cdev)
{
- struct subchannel *sch;
unsigned long flags;
+ int rc;
+
/*
* Forced offline in disconnected state means
* 'throw away device'.
*/
if (ccw_device_is_orphan(cdev)) {
- /* Deregister ccw device. */
+ /*
+ * Deregister ccw device.
+ * Unfortunately, we cannot do this directly from the
+ * attribute method.
+ */
spin_lock_irqsave(cdev->ccwlock, flags);
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
- ccw_device_unregister(cdev);
- put_device(&cdev->dev);
- return ;
+ rc = device_schedule_callback(&cdev->dev,
+ ccw_device_remove_orphan_cb);
+ if (rc)
+ dev_info(&cdev->dev, "Couldn't unregister orphan\n");
+ return;
}
- sch = to_subchannel(cdev->dev.parent);
- css_sch_device_unregister(sch);
- /* Reset intparm to zeroes. */
- sch->schib.pmcw.intparm = 0;
- cio_modify(sch);
- put_device(&sch->dev);
+ /* Deregister subchannel, which will kill the ccw device. */
+ rc = device_schedule_callback(cdev->dev.parent,
+ ccw_device_remove_sch_cb);
+ if (rc)
+ dev_info(&cdev->dev,
+ "Couldn't unregister disconnected device\n");
}
int
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 898ec3b..6bba809 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -688,6 +688,12 @@ ccw_device_disband_done(struct ccw_device *cdev, int err)
ccw_device_done(cdev, DEV_STATE_BOXED);
break;
default:
+ cdev->private->flags.donotify = 0;
+ if (get_device(&cdev->dev)) {
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_call_sch_unregister);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ }
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
break;
}
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-06-19 8:50 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-06-19 8:50 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/appldata/appldata_base.c | 5 ++---
arch/s390/kernel/entry.S | 8 +++++++-
arch/s390/kernel/entry64.S | 8 +++++++-
arch/s390/kernel/setup.c | 1 +
arch/s390/kernel/traps.c | 9 ++++++---
drivers/s390/char/zcore.c | 3 +++
include/asm-s390/processor.h | 5 +++++
include/asm-s390/ptrace.h | 9 +--------
8 files changed, 32 insertions(+), 16 deletions(-)
Heiko Carstens (4):
[S390] Fix yet another two section mismatches.
[S390] Print list of modules on die().
[S390] Move psw_set_key.
[S390] Add oops_enter()/oops_exit() calls to die().
Michael Holzheu (2):
[S390] Missing blank when appending cio_ignore kernel parameter
[S390] Fix zfcpdump header
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 81a2b92..6ffbab7 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -535,8 +535,7 @@ void appldata_unregister_ops(struct appldata_ops *ops)
/******************************* init / exit *********************************/
-static void
-appldata_online_cpu(int cpu)
+static void __cpuinit appldata_online_cpu(int cpu)
{
init_virt_timer(&per_cpu(appldata_timer, cpu));
per_cpu(appldata_timer, cpu).function = appldata_timer_function;
@@ -580,7 +579,7 @@ appldata_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block appldata_nb = {
+static struct notifier_block __cpuinitdata appldata_nb = {
.notifier_call = appldata_cpu_notify,
};
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c8a2212..6234c69 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -769,10 +769,13 @@ mcck_return:
RESTORE_ALL __LC_RETURN_MCCK_PSW,0
-#ifdef CONFIG_SMP
/*
* Restart interruption handler, kick starter for additional CPUs
*/
+#ifdef CONFIG_SMP
+#ifndef CONFIG_HOTPLUG_CPU
+ .section .init.text,"ax"
+#endif
.globl restart_int_handler
restart_int_handler:
l %r15,__LC_SAVE_AREA+60 # load ksp
@@ -785,6 +788,9 @@ restart_int_handler:
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
+#ifndef CONFIG_HOTPLUG_CPU
+ .previous
+#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 93745fd..685f11f 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -745,10 +745,13 @@ mcck_return:
#endif
lpswe __LC_RETURN_MCCK_PSW # back to caller
-#ifdef CONFIG_SMP
/*
* Restart interruption handler, kick starter for additional CPUs
*/
+#ifdef CONFIG_SMP
+#ifndef CONFIG_HOTPLUG_CPU
+ .section .init.text,"ax"
+#endif
.globl restart_int_handler
restart_int_handler:
lg %r15,__LC_SAVE_AREA+120 # load ksp
@@ -759,6 +762,9 @@ restart_int_handler:
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
+#ifndef CONFIG_HOTPLUG_CPU
+ .previous
+#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 51d6309..7e1bfb9 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -300,6 +300,7 @@ static void __init setup_zfcpdump(unsigned int console_devno)
else
sprintf(str, "cio_ignore=all,!0.0.%04x",
ipl_info.data.fcp.dev_id.devno);
+ strcat(COMMAND_LINE, " ");
strcat(COMMAND_LINE, str);
console_loglevel = 2;
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index cbfe730..ee9186f 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -253,19 +253,22 @@ void die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
+ oops_enter();
debug_stop_all();
console_verbose();
spin_lock_irq(&die_lock);
bust_spinlocks(1);
printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
- show_regs(regs);
+ print_modules();
+ show_regs(regs);
bust_spinlocks(0);
- spin_unlock_irq(&die_lock);
+ spin_unlock_irq(&die_lock);
if (in_interrupt())
panic("Fatal exception in interrupt");
if (panic_on_oops)
panic("Fatal exception: panic_on_oops");
- do_exit(SIGSEGV);
+ oops_exit();
+ do_exit(SIGSEGV);
}
static void inline
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 66eb068..4e711a9 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -267,7 +267,9 @@ struct zcore_header {
u64 tod;
cpuid_t cpu_id;
u32 arch_id;
+ u32 volnr;
u32 build_arch;
+ u64 rmem_size;
char pad2[4016];
} __attribute__((packed,__aligned__(16)));
@@ -559,6 +561,7 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr)
else
hdr->arch_id = DUMP_ARCH_S390;
hdr->mem_size = sys_info.mem_size;
+ hdr->rmem_size = sys_info.mem_size;
hdr->mem_end = sys_info.mem_size;
hdr->num_pages = sys_info.mem_size / PAGE_SIZE;
hdr->tod = get_clock();
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index e0fcea8..5cb480a 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -216,6 +216,11 @@ static inline void cpu_relax(void)
barrier();
}
+static inline void psw_set_key(unsigned int key)
+{
+ asm volatile("spka 0(%0)" : : "d" (key));
+}
+
/*
* Set PSW to specified value.
*/
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index fa6ca87..332ee73 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -470,14 +470,7 @@ struct user_regs_struct
#define regs_return_value(regs)((regs)->gprs[2])
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs * regs);
-#endif
-
-static inline void
-psw_set_key(unsigned int key)
-{
- asm volatile("spka 0(%0)" : : "d" (key));
-}
-
+#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#endif /* _S390_PTRACE_H */
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-07-27 11:40 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-07-27 11:40 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
Documentation/feature-removal-schedule.txt | 16 --
arch/s390/appldata/appldata_base.c | 12 +-
arch/s390/kernel/compat_wrapper.S | 10 +
arch/s390/kernel/entry.S | 6 +-
arch/s390/kernel/entry64.S | 6 +-
arch/s390/kernel/head.S | 1 +
arch/s390/kernel/smp.c | 30 ++--
arch/s390/kernel/sys_s390.c | 20 +++
arch/s390/kernel/syscalls.S | 2 +-
arch/s390/kernel/vmlinux.lds.S | 1 +
arch/s390/kernel/vtime.c | 2 +-
arch/s390/mm/vmem.c | 6 +-
drivers/s390/char/Kconfig | 12 +-
drivers/s390/char/raw3270.c | 6 +-
drivers/s390/char/sclp_vt220.c | 62 +++++---
drivers/s390/char/vmur.c | 2 +-
drivers/s390/cio/blacklist.c | 19 +--
drivers/s390/cio/ccwgroup.c | 3 -
drivers/s390/cio/chp.c | 19 +--
drivers/s390/cio/chsc.c | 26 ++--
drivers/s390/cio/chsc.h | 2 +
drivers/s390/cio/cio.c | 13 +-
drivers/s390/cio/cio_debug.h | 2 +
drivers/s390/cio/cmf.c | 16 +-
drivers/s390/cio/css.c | 32 +++-
drivers/s390/cio/css.h | 1 -
drivers/s390/cio/device.c | 60 ++++---
drivers/s390/cio/device_fsm.c | 20 ++-
drivers/s390/cio/device_ops.c | 257 ----------------------------
include/asm-s390/ccwdev.h | 5 -
include/asm-s390/s390_ext.h | 2 +
include/asm-s390/smp.h | 11 +-
include/asm-s390/unistd.h | 2 +-
net/iucv/iucv.c | 15 +-
34 files changed, 236 insertions(+), 463 deletions(-)
Christian Borntraeger (1):
[S390] add types.h include to s390_ext.h
Cornelia Huck (6):
[S390] cio: css_sch_device_register() can be made static.
[S390] cio: Remove remains of _ccw_device_get_device_number().
[S390] cio: Remove deprecated rdc/rcd.
[S390] cio: Clean up messages.
[S390] cio: Make CIO_* macros safe if dbfs are not available.
[S390] cio: Reorganize initialization.
Frank Munzert (1):
[S390] vmur: fix diag14_read.
Heiko Carstens (6):
[S390] Convert to smp_call_function_single.
[S390] Improve __smp_call_function_map.
[S390] sclp: kill unused SCLP config option.
[S390] Get rid of new section mismatch warnings.
[S390] Fix IRQ tracing.
[S390] Fix sclp_vt220 error handling.
Martin Schwidefsky (1):
[S390] Wire up sys_fallocate.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index c175eed..a43d287 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -211,22 +211,6 @@ Who: Richard Purdie <rpurdie@rpsys.net>
---------------------------
-What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
-When: December 2007
-Why: These functions are a leftover from 2.4 times. They have several
- problems:
- - Duplication of checks that are done in the device driver's
- interrupt handler
- - common I/O layer can't do device specific error recovery
- - device driver can't be notified for conditions happening during
- execution of the function
- Device drivers should issue the read device characteristics and read
- configuration data ccws and do the appropriate error handling
- themselves.
-Who: Cornelia Huck <cornelia.huck@de.ibm.com>
-
----------------------------
-
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
When: September 2007
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 6ffbab7..62391fb 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -173,7 +173,7 @@ int appldata_diag(char record_nr, u16 function, unsigned long buffer,
/*
* appldata_mod_vtimer_wrap()
*
- * wrapper function for mod_virt_timer(), because smp_call_function_on()
+ * wrapper function for mod_virt_timer(), because smp_call_function_single()
* accepts only one parameter.
*/
static void __appldata_mod_vtimer_wrap(void *p) {
@@ -208,9 +208,9 @@ __appldata_vtimer_setup(int cmd)
num_online_cpus()) * TOD_MICRO;
for_each_online_cpu(i) {
per_cpu(appldata_timer, i).expires = per_cpu_interval;
- smp_call_function_on(add_virt_timer_periodic,
- &per_cpu(appldata_timer, i),
- 0, 1, i);
+ smp_call_function_single(i, add_virt_timer_periodic,
+ &per_cpu(appldata_timer, i),
+ 0, 1);
}
appldata_timer_active = 1;
P_INFO("Monitoring timer started.\n");
@@ -236,8 +236,8 @@ __appldata_vtimer_setup(int cmd)
} args;
args.timer = &per_cpu(appldata_timer, i);
args.expires = per_cpu_interval;
- smp_call_function_on(__appldata_mod_vtimer_wrap,
- &args, 0, 1, i);
+ smp_call_function_single(i, __appldata_mod_vtimer_wrap,
+ &args, 0, 1);
}
}
}
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index acc4154..6ee1bed 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1710,3 +1710,13 @@ compat_sys_timerfd_wrapper:
sys_eventfd_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_eventfd
+
+ .globl sys_fallocate_wrapper
+sys_fallocate_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ sllg %r4,%r4,32 # get high word of 64bit loff_t
+ lr %r4,%r5 # get low word of 64bit loff_t
+ sllg %r5,%r6,32 # get high word of 64bit loff_t
+ l %r5,164(%r15) # get low word of 64bit loff_t
+ jg sys_fallocate
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index bc7ff36..f3bceb1 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -624,9 +624,11 @@ io_work_loop:
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
+ TRACE_IRQS_OFF
l %r1,BASED(.Ls390_handle_mcck)
- la %r14,BASED(io_work_loop)
- br %r1 # TIF bit will be cleared by handler
+ basr %r14,%r1 # TIF bit will be cleared by handler
+ TRACE_IRQS_ON
+ b BASED(io_work_loop)
#
# _TIF_NEED_RESCHED is set, call schedule
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 2a7b130..9c0d5cc 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -611,8 +611,10 @@ io_work_loop:
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
- larl %r14,io_work_loop
- jg s390_handle_mcck # TIF bit will be cleared by handler
+ TRACE_IRQS_OFF
+ brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler
+ TRACE_IRQS_ON
+ j io_work_loop
#
# _TIF_NEED_RESCHED is set, call schedule
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 8f8c802..83477c7 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -35,6 +35,7 @@
#define ARCH_OFFSET 0
#endif
+.section ".text.head","ax"
#ifndef CONFIG_IPL
.org 0
.long 0x00080000,0x80000000+startup # Just a restart PSW
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 182c085..03674fb 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -120,7 +120,7 @@ static void __smp_call_function_map(void (*func) (void *info), void *info,
if (wait)
data.finished = CPU_MASK_NONE;
- spin_lock_bh(&call_lock);
+ spin_lock(&call_lock);
call_data = &data;
for_each_cpu_mask(cpu, map)
@@ -129,18 +129,16 @@ static void __smp_call_function_map(void (*func) (void *info), void *info,
/* Wait for response */
while (!cpus_equal(map, data.started))
cpu_relax();
-
if (wait)
while (!cpus_equal(map, data.finished))
cpu_relax();
-
- spin_unlock_bh(&call_lock);
-
+ spin_unlock(&call_lock);
out:
- local_irq_disable();
- if (local)
+ if (local) {
+ local_irq_disable();
func(info);
- local_irq_enable();
+ local_irq_enable();
+ }
}
/*
@@ -170,30 +168,28 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
EXPORT_SYMBOL(smp_call_function);
/*
- * smp_call_function_on:
+ * smp_call_function_single:
+ * @cpu: the CPU where func should run
* @func: the function to run; this must be fast and non-blocking
* @info: an arbitrary pointer to pass to the function
* @nonatomic: unused
* @wait: if true, wait (atomically) until function has completed on other CPUs
- * @cpu: the CPU where func should run
*
* Run a function on one processor.
*
* You must not call this function with disabled interrupts, from a
* hardware interrupt handler or from a bottom half.
*/
-int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic,
- int wait, int cpu)
+int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+ int nonatomic, int wait)
{
- cpumask_t map = CPU_MASK_NONE;
-
preempt_disable();
- cpu_set(cpu, map);
- __smp_call_function_map(func, info, nonatomic, wait, map);
+ __smp_call_function_map(func, info, nonatomic, wait,
+ cpumask_of_cpu(cpu));
preempt_enable();
return 0;
}
-EXPORT_SYMBOL(smp_call_function_on);
+EXPORT_SYMBOL(smp_call_function_single);
static void do_send_stop(void)
{
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 1c90c7e..13e27bd 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -265,3 +265,23 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args)
return -EFAULT;
return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
}
+
+#ifndef CONFIG_64BIT
+/*
+ * This is a wrapper to call sys_fallocate(). For 31 bit s390 the last
+ * 64 bit argument "len" is split into the upper and lower 32 bits. The
+ * system call wrapper in the user space loads the value to %r6/%r7.
+ * The code in entry.S keeps the values in %r2 - %r6 where they are and
+ * stores %r7 to 96(%r15). But the standard C linkage requires that
+ * the whole 64 bit value for len is stored on the stack and doesn't
+ * use %r6 at all. So s390_fallocate has to convert the arguments from
+ * %r2: fd, %r3: mode, %r4/%r5: offset, %r6/96(%r15)-99(%r15): len
+ * to
+ * %r2: fd, %r3: mode, %r4/%r5: offset, 96(%r15)-103(%r15): len
+ */
+asmlinkage long s390_fallocate(int fd, int mode, loff_t offset,
+ u32 len_high, u32 len_low)
+{
+ return sys_fallocate(fd, mode, offset, ((u64)len_high << 32) | len_low);
+}
+#endif
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 738feb4..9e26ed9 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -322,7 +322,7 @@ NI_SYSCALL /* 310 sys_move_pages */
SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
-NI_SYSCALL /* 314 sys_fallocate */
+SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 6ab7d4e..b4622a3 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -21,6 +21,7 @@ SECTIONS
. = 0x00000000;
_text = .; /* Text and read-only data */
.text : {
+ *(.text.head)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index b6ed143..84ff78d 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -415,7 +415,7 @@ EXPORT_SYMBOL(add_virt_timer_periodic);
/*
* If we change a pending timer the function must be called on the CPU
- * where the timer is running on, e.g. by smp_call_function_on()
+ * where the timer is running on, e.g. by smp_call_function_single()
*
* The original mod_timer adds the timer if it is not pending. For compatibility
* we do the same. The timer will be added on the current CPU as a oneshot timer.
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 92a5651..fd594d5 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -29,8 +29,8 @@ struct memory_segment {
static LIST_HEAD(mem_segs);
-void memmap_init(unsigned long size, int nid, unsigned long zone,
- unsigned long start_pfn)
+void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
+ unsigned long start_pfn)
{
struct page *start, *end;
struct page *map_start, *map_end;
@@ -66,7 +66,7 @@ void memmap_init(unsigned long size, int nid, unsigned long zone,
}
}
-static inline void *vmem_alloc_pages(unsigned int order)
+static void __init_refok *vmem_alloc_pages(unsigned int order)
{
if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order);
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 3f36cb3..6430338 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -44,15 +44,9 @@ config CCW_CONSOLE
depends on TN3215_CONSOLE || TN3270_CONSOLE
default y
-config SCLP
- bool "Support for SCLP"
- depends on S390
- help
- Include support for the SCLP interface to the service element.
-
config SCLP_TTY
bool "Support for SCLP line mode terminal"
- depends on SCLP
+ depends on S390
help
Include support for IBM SCLP line-mode terminals.
@@ -65,7 +59,7 @@ config SCLP_CONSOLE
config SCLP_VT220_TTY
bool "Support for SCLP VT220-compatible terminal"
- depends on SCLP
+ depends on S390
help
Include support for an IBM SCLP VT220-compatible terminal.
@@ -78,7 +72,7 @@ config SCLP_VT220_CONSOLE
config SCLP_CPI
tristate "Control-Program Identification"
- depends on SCLP
+ depends on S390
help
This option enables the hardware console interface for system
identification. This is commonly used for workload management and
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 743944a..4f2f81b 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -147,8 +147,7 @@ raw3270_request_alloc(size_t size)
* Allocate a new 3270 ccw request from bootmem. Only works very
* early in the boot process. Only con3270.c should be using this.
*/
-struct raw3270_request *
-raw3270_request_alloc_bootmem(size_t size)
+struct raw3270_request __init *raw3270_request_alloc_bootmem(size_t size)
{
struct raw3270_request *rq;
@@ -848,8 +847,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
/*
* Setup 3270 device configured as console.
*/
-struct raw3270 *
-raw3270_setup_console(struct ccw_device *cdev)
+struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
{
struct raw3270 *rp;
char *ascebc;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 7263347..40cd21b 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -621,11 +621,24 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
/*
* Initialize all relevant components and register driver with system.
*/
-static int
-__sclp_vt220_init(int early)
+static void __init __sclp_vt220_cleanup(void)
+{
+ struct list_head *page, *p;
+
+ list_for_each_safe(page, p, &sclp_vt220_empty) {
+ list_del(page);
+ if (slab_is_available())
+ free_page((unsigned long) page);
+ else
+ free_bootmem((unsigned long) page, PAGE_SIZE);
+ }
+}
+
+static int __init __sclp_vt220_init(void)
{
void *page;
int i;
+ int num_pages;
if (sclp_vt220_initialized)
return 0;
@@ -642,13 +655,16 @@ __sclp_vt220_init(int early)
sclp_vt220_flush_later = 0;
/* Allocate pages for output buffering */
- for (i = 0; i < (early ? MAX_CONSOLE_PAGES : MAX_KMEM_PAGES); i++) {
- if (early)
- page = alloc_bootmem_low_pages(PAGE_SIZE);
- else
+ num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
+ for (i = 0; i < num_pages; i++) {
+ if (slab_is_available())
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!page)
+ else
+ page = alloc_bootmem_low_pages(PAGE_SIZE);
+ if (!page) {
+ __sclp_vt220_cleanup();
return -ENOMEM;
+ }
list_add_tail((struct list_head *) page, &sclp_vt220_empty);
}
return 0;
@@ -662,14 +678,13 @@ static const struct tty_operations sclp_vt220_ops = {
.flush_chars = sclp_vt220_flush_chars,
.write_room = sclp_vt220_write_room,
.chars_in_buffer = sclp_vt220_chars_in_buffer,
- .flush_buffer = sclp_vt220_flush_buffer
+ .flush_buffer = sclp_vt220_flush_buffer,
};
/*
* Register driver with SCLP and Linux and initialize internal tty structures.
*/
-static int __init
-sclp_vt220_tty_init(void)
+static int __init sclp_vt220_tty_init(void)
{
struct tty_driver *driver;
int rc;
@@ -679,18 +694,15 @@ sclp_vt220_tty_init(void)
driver = alloc_tty_driver(1);
if (!driver)
return -ENOMEM;
- rc = __sclp_vt220_init(0);
- if (rc) {
- put_tty_driver(driver);
- return rc;
- }
+ rc = __sclp_vt220_init();
+ if (rc)
+ goto out_driver;
rc = sclp_register(&sclp_vt220_register);
if (rc) {
printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - "
"sclp_register returned %d\n", rc);
- put_tty_driver(driver);
- return rc;
+ goto out_init;
}
driver->owner = THIS_MODULE;
@@ -709,14 +721,20 @@ sclp_vt220_tty_init(void)
printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - "
"tty_register_driver returned %d\n", rc);
- put_tty_driver(driver);
- return rc;
+ goto out_sclp;
}
sclp_vt220_driver = driver;
return 0;
-}
-module_init(sclp_vt220_tty_init);
+out_sclp:
+ sclp_unregister(&sclp_vt220_register);
+out_init:
+ __sclp_vt220_cleanup();
+out_driver:
+ put_tty_driver(driver);
+ return rc;
+}
+__initcall(sclp_vt220_tty_init);
#ifdef CONFIG_SCLP_VT220_CONSOLE
@@ -762,7 +780,7 @@ sclp_vt220_con_init(void)
if (!CONSOLE_IS_SCLP)
return 0;
- rc = __sclp_vt220_init(1);
+ rc = __sclp_vt220_init();
if (rc)
return rc;
/* Attach linux console */
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index e90b0f8..161867c 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -486,7 +486,7 @@ static ssize_t diag14_read(struct file *file, char __user *ubuf, size_t count,
}
if (rc)
goto fail;
- if (reclen)
+ if (reclen && (copied == 0) && (*offs < PAGE_SIZE))
*((u16 *) &buf[FILE_RECLEN_OFFSET]) = reclen;
len = min(count - copied, PAGE_SIZE - res);
if (copy_to_user(ubuf + copied, buf + res, len)) {
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index ec04048..bd5f16f 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -51,7 +51,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to,
to = from;
if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
- printk (KERN_WARNING "Invalid blacklist range "
+ printk (KERN_WARNING "cio: Invalid blacklist range "
"0.%x.%04x to 0.%x.%04x, skipping\n",
ssid, from, ssid, to);
return;
@@ -119,7 +119,7 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno)
return 0;
confused:
strsep(str, ",\n");
- printk(KERN_WARNING "Invalid cio_ignore parameter '%s'\n", sav);
+ printk(KERN_WARNING "cio: Invalid cio_ignore parameter '%s'\n", sav);
return 1;
}
@@ -166,22 +166,19 @@ blacklist_parse_parameters (char *str, range_action action)
continue;
}
if (*str == '-') {
- printk(KERN_WARNING "invalid cio_ignore "
+ printk(KERN_WARNING "cio: invalid cio_ignore "
"parameter '%s'\n",
strsep(&str, ",\n"));
continue;
}
if ((from_id0 != to_id0) ||
(from_ssid != to_ssid)) {
- printk(KERN_WARNING "invalid cio_ignore range "
- "%x.%x.%04x-%x.%x.%04x\n",
- from_id0, from_ssid, from,
- to_id0, to_ssid, to);
+ printk(KERN_WARNING "cio: invalid cio_ignore "
+ "range %x.%x.%04x-%x.%x.%04x\n",
+ from_id0, from_ssid, from,
+ to_id0, to_ssid, to);
continue;
}
- pr_debug("blacklist_setup: adding range "
- "from %x.%x.%04x to %x.%x.%04x\n",
- from_id0, from_ssid, from, to_id0, to_ssid, to);
blacklist_range (ra, from, to, to_ssid);
}
}
@@ -239,7 +236,7 @@ blacklist_parse_proc_parameters (char *buf)
*/
blacklist_parse_parameters (buf + 4, add);
} else {
- printk (KERN_WARNING "cio_ignore: Parse error; \n"
+ printk (KERN_WARNING "cio: cio_ignore: Parse error; \n"
KERN_WARNING "try using 'free all|<devno-range>,"
"<devno-range>,...'\n"
KERN_WARNING "or 'add <devno-range>,"
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e5ccda6..b0a18f5 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -359,7 +359,6 @@ ccwgroup_probe (struct device *dev)
if ((ret = device_create_file(dev, &dev_attr_online)))
return ret;
- pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id);
ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
if (ret)
device_remove_file(dev, &dev_attr_online);
@@ -376,8 +375,6 @@ ccwgroup_remove (struct device *dev)
gdev = to_ccwgroupdev(dev);
gdrv = to_ccwgroupdrv(dev->driver);
- pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id);
-
device_remove_file(dev, &dev_attr_online);
if (gdrv && gdrv->remove)
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index b57d93d..920dd71 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -121,14 +121,8 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
CIO_TRACE_EVENT( 2, dbf_text);
status = chp_get_status(chpid);
- if (status < 0) {
- printk(KERN_ERR "Can't vary unknown chpid %x.%02x\n",
- chpid.cssid, chpid.id);
- return -EINVAL;
- }
-
if (!on && !status) {
- printk(KERN_ERR "chpid %x.%02x is already offline\n",
+ printk(KERN_ERR "cio: chpid %x.%02x is already offline\n",
chpid.cssid, chpid.id);
return -EINVAL;
}
@@ -421,21 +415,14 @@ int chp_new(struct chp_id chpid)
if (ret)
goto out_free;
} else {
- static int msg_done;
-
- if (!msg_done) {
- printk(KERN_WARNING "cio: Channel measurements not "
- "available, continuing.\n");
- msg_done = 1;
- }
chp->cmg = -1;
}
/* make it known to the system */
ret = device_register(&chp->dev);
if (ret) {
- printk(KERN_WARNING "%s: could not register %x.%02x\n",
- __func__, chpid.cssid, chpid.id);
+ CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n",
+ chpid.cssid, chpid.id, ret);
goto out_free;
}
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index ea92ac4..597c0c7 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -990,16 +990,20 @@ out:
return ret;
}
-static int __init
-chsc_alloc_sei_area(void)
+int __init chsc_alloc_sei_area(void)
{
sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!sei_page)
- printk(KERN_WARNING"Can't allocate page for processing of " \
- "chsc machine checks!\n");
+ CIO_MSG_EVENT(0, "Can't allocate page for processing of "
+ "chsc machine checks!\n");
return (sei_page ? 0 : -ENOMEM);
}
+void __init chsc_free_sei_area(void)
+{
+ kfree(sei_page);
+}
+
int __init
chsc_enable_facility(int operation_code)
{
@@ -1051,8 +1055,6 @@ chsc_enable_facility(int operation_code)
return ret;
}
-subsys_initcall(chsc_alloc_sei_area);
-
struct css_general_char css_general_characteristics;
struct css_chsc_char css_chsc_characteristics;
@@ -1073,8 +1075,8 @@ chsc_determine_css_characteristics(void)
scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!scsc_area) {
- printk(KERN_WARNING"cio: Was not able to determine available" \
- "CHSCs due to no memory.\n");
+ CIO_MSG_EVENT(0, "Was not able to determine available"
+ "CHSCs due to no memory.\n");
return -ENOMEM;
}
@@ -1083,15 +1085,15 @@ chsc_determine_css_characteristics(void)
result = chsc(scsc_area);
if (result) {
- printk(KERN_WARNING"cio: Was not able to determine " \
- "available CHSCs, cc=%i.\n", result);
+ CIO_MSG_EVENT(0, "Was not able to determine available CHSCs, "
+ "cc=%i.\n", result);
result = -EIO;
goto exit;
}
if (scsc_area->response.code != 1) {
- printk(KERN_WARNING"cio: Was not able to determine " \
- "available CHSCs.\n");
+ CIO_MSG_EVENT(0, "Was not able to determine "
+ "available CHSCs.\n");
result = -EIO;
goto exit;
}
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 2ad81d1..d1f5db1 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -79,6 +79,8 @@ extern int chsc_get_ssd_info(struct subchannel_id schid,
struct chsc_ssd_info *ssd);
extern int chsc_determine_css_characteristics(void);
extern int css_characteristics_avail;
+extern int chsc_alloc_sei_area(void);
+extern void chsc_free_sei_area(void);
extern int chsc_enable_facility(int);
struct channel_subsystem;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index ea1defb..f2708d6 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -47,8 +47,8 @@ cio_setup (char *parm)
else if (!strcmp (parm, "no"))
cio_show_msg = 0;
else
- printk (KERN_ERR "cio_setup : invalid cio_msg parameter '%s'",
- parm);
+ printk(KERN_ERR "cio: cio_setup: "
+ "invalid cio_msg parameter '%s'", parm);
return 1;
}
@@ -80,7 +80,6 @@ cio_debug_init (void)
goto out_unregister;
debug_register_view (cio_debug_crw_id, &debug_sprintf_view);
debug_set_level (cio_debug_crw_id, 2);
- pr_debug("debugging initialized\n");
return 0;
out_unregister:
@@ -90,7 +89,7 @@ out_unregister:
debug_unregister (cio_debug_trace_id);
if (cio_debug_crw_id)
debug_unregister (cio_debug_crw_id);
- pr_debug("could not initialize debugging\n");
+ printk(KERN_WARNING"cio: could not initialize debugging\n");
return -1;
}
@@ -568,7 +567,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
*/
if (sch->st != 0) {
CIO_DEBUG(KERN_INFO, 0,
- "Subchannel 0.%x.%04x reports "
+ "cio: Subchannel 0.%x.%04x reports "
"non-I/O subchannel type %04X\n",
sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */
@@ -601,7 +600,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
sch->lpm = sch->schib.pmcw.pam & sch->opm;
CIO_DEBUG(KERN_INFO, 0,
- "Detected device %04x on subchannel 0.%x.%04X"
+ "cio: Detected device %04x on subchannel 0.%x.%04X"
" - PIM = %02X, PAM = %02X, POM = %02X\n",
sch->schib.pmcw.dev, sch->schid.ssid,
sch->schid.sch_no, sch->schib.pmcw.pim,
@@ -766,7 +765,7 @@ cio_get_console_sch_no(void)
/* unlike in 2.4, we cannot autoprobe here, since
* the channel subsystem is not fully initialized.
* With some luck, the HWC console can take over */
- printk(KERN_WARNING "No ccw console found!\n");
+ printk(KERN_WARNING "cio: No ccw console found!\n");
return -1;
}
return console_irq;
diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h
index f88844a..c9bf898 100644
--- a/drivers/s390/cio/cio_debug.h
+++ b/drivers/s390/cio/cio_debug.h
@@ -23,6 +23,8 @@ extern debug_info_t *cio_debug_crw_id;
static inline void
CIO_HEX_EVENT(int level, void *data, int length)
{
+ if (unlikely(!cio_debug_trace_id))
+ return;
while (length > 0) {
debug_event(cio_debug_trace_id, level, data, length);
length -= cio_debug_trace_id->buf_size;
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 28abd69..02fd00b 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1185,12 +1185,12 @@ static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *att
case '0':
ret = disable_cmf(cdev);
if (ret)
- printk(KERN_INFO "disable_cmf failed (%d)\n", ret);
+ dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
break;
case '1':
ret = enable_cmf(cdev);
if (ret && ret != -EBUSY)
- printk(KERN_INFO "enable_cmf failed (%d)\n", ret);
+ dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret);
break;
}
@@ -1280,10 +1280,10 @@ init_cmf(void)
format_string = "basic";
cmbops = &cmbops_basic;
if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) {
- printk(KERN_ERR "Basic channel measurement facility"
- " can only use 1 to 4096 devices\n"
+ printk(KERN_ERR "cio: Basic channel measurement "
+ "facility can only use 1 to 4096 devices\n"
KERN_ERR "when the cmf driver is built"
- " as a loadable module\n");
+ " as a loadable module\n");
return 1;
}
break;
@@ -1292,13 +1292,13 @@ init_cmf(void)
cmbops = &cmbops_extended;
break;
default:
- printk(KERN_ERR "Invalid format %d for channel "
+ printk(KERN_ERR "cio: Invalid format %d for channel "
"measurement facility\n", format);
return 1;
}
- printk(KERN_INFO "Channel measurement facility using %s format (%s)\n",
- format_string, detect_string);
+ printk(KERN_INFO "cio: Channel measurement facility using %s "
+ "format (%s)\n", format_string, detect_string);
return 0;
}
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index dfca0ef..1c27a5a 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -109,7 +109,7 @@ css_subchannel_release(struct device *dev)
}
}
-int css_sch_device_register(struct subchannel *sch)
+static int css_sch_device_register(struct subchannel *sch)
{
int ret;
@@ -184,8 +184,8 @@ static int css_register_subchannel(struct subchannel *sch)
/* make it known to the system */
ret = css_sch_device_register(sch);
if (ret) {
- printk (KERN_WARNING "%s: could not register %s\n",
- __func__, sch->dev.bus_id);
+ CIO_MSG_EVENT(0, "Could not register sch 0.%x.%04x: %d\n",
+ sch->schid.ssid, sch->schid.sch_no, ret);
return ret;
}
return ret;
@@ -371,15 +371,12 @@ static int __init slow_subchannel_init(void)
spin_lock_init(&slow_subchannel_lock);
slow_subchannel_set = idset_sch_new();
if (!slow_subchannel_set) {
- printk(KERN_WARNING "cio: could not allocate slow subchannel "
- "set\n");
+ CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n");
return -ENOMEM;
}
return 0;
}
-subsys_initcall(slow_subchannel_init);
-
static void css_slow_path_func(struct work_struct *unused)
{
struct subchannel_id schid;
@@ -425,8 +422,8 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data)
struct subchannel *sch;
int ret;
- CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n",
- schid.ssid, schid.sch_no);
+ CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n",
+ schid.ssid, schid.sch_no);
if (need_reprobe)
return -EAGAIN;
@@ -642,9 +639,20 @@ init_channel_subsystem (void)
{
int ret, i;
- if (chsc_determine_css_characteristics() == 0)
+ ret = chsc_determine_css_characteristics();
+ if (ret == -ENOMEM)
+ goto out; /* No need to continue. */
+ if (ret == 0)
css_characteristics_avail = 1;
+ ret = chsc_alloc_sei_area();
+ if (ret)
+ goto out;
+
+ ret = slow_subchannel_init();
+ if (ret)
+ goto out;
+
if ((ret = bus_register(&css_bus_type)))
goto out;
@@ -710,6 +718,10 @@ out_unregister:
out_bus:
bus_unregister(&css_bus_type);
out:
+ chsc_free_sei_area();
+ kfree(slow_subchannel_set);
+ printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n",
+ ret);
return ret;
}
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index ed79775..5d65e83 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -139,7 +139,6 @@ struct css_driver {
*/
extern struct bus_type css_bus_type;
-extern int css_sch_device_register(struct subchannel *);
extern void css_sch_device_unregister(struct subchannel *);
extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 001682e..297659f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -338,15 +338,20 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
rc = device_schedule_callback(&cdev->dev,
ccw_device_remove_orphan_cb);
if (rc)
- dev_info(&cdev->dev, "Couldn't unregister orphan\n");
+ CIO_MSG_EVENT(2, "Couldn't unregister orphan "
+ "0.%x.%04x\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
return;
}
/* Deregister subchannel, which will kill the ccw device. */
rc = device_schedule_callback(cdev->dev.parent,
ccw_device_remove_sch_cb);
if (rc)
- dev_info(&cdev->dev,
- "Couldn't unregister disconnected device\n");
+ CIO_MSG_EVENT(2, "Couldn't unregister disconnected device "
+ "0.%x.%04x\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
}
int
@@ -379,8 +384,10 @@ ccw_device_set_offline(struct ccw_device *cdev)
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else {
- pr_debug("ccw_device_offline returned %d, device %s\n",
- ret, cdev->dev.bus_id);
+ CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+ "device 0.%x.%04x\n",
+ ret, cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
cdev->online = 1;
}
return ret;
@@ -402,8 +409,10 @@ ccw_device_set_online(struct ccw_device *cdev)
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else {
- pr_debug("ccw_device_online returned %d, device %s\n",
- ret, cdev->dev.bus_id);
+ CIO_MSG_EVENT(2, "ccw_device_online returned %d, "
+ "device 0.%x.%04x\n",
+ ret, cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
return ret;
}
if (cdev->private->state != DEV_STATE_ONLINE)
@@ -417,9 +426,11 @@ ccw_device_set_online(struct ccw_device *cdev)
spin_unlock_irq(cdev->ccwlock);
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
- else
- pr_debug("ccw_device_offline returned %d, device %s\n",
- ret, cdev->dev.bus_id);
+ else
+ CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+ "device 0.%x.%04x\n",
+ ret, cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
return (ret == 0) ? -ENODEV : ret;
}
@@ -439,9 +450,10 @@ static int online_store_recog_and_online(struct ccw_device *cdev)
if (cdev->id.cu_type == 0) {
ret = ccw_device_recognition(cdev);
if (ret) {
- printk(KERN_WARNING"Couldn't start recognition "
- "for device %s (ret=%d)\n",
- cdev->dev.bus_id, ret);
+ CIO_MSG_EVENT(0, "Couldn't start recognition "
+ "for device 0.%x.%04x (ret=%d)\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
return ret;
}
wait_event(cdev->private->wait_q,
@@ -461,8 +473,8 @@ static void online_store_handle_online(struct ccw_device *cdev, int force)
if (force && cdev->private->state == DEV_STATE_BOXED) {
ret = ccw_device_stlck(cdev);
if (ret) {
- printk(KERN_WARNING"ccw_device_stlck for device %s "
- "returned %d!\n", cdev->dev.bus_id, ret);
+ dev_warn(&cdev->dev,
+ "ccw_device_stlck returned %d!\n", ret);
return;
}
if (cdev->id.cu_type == 0)
@@ -893,8 +905,10 @@ io_subchannel_register(struct work_struct *work)
ret = device_reprobe(&cdev->dev);
if (ret)
/* We can't do much here. */
- dev_info(&cdev->dev, "device_reprobe() returned"
- " %d\n", ret);
+ CIO_MSG_EVENT(2, "device_reprobe() returned"
+ " %d for 0.%x.%04x\n", ret,
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
}
goto out;
}
@@ -907,8 +921,9 @@ io_subchannel_register(struct work_struct *work)
/* make it known to the system */
ret = ccw_device_register(cdev);
if (ret) {
- printk (KERN_WARNING "%s: could not register %s\n",
- __func__, cdev->dev.bus_id);
+ CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
put_device(&cdev->dev);
spin_lock_irqsave(sch->lock, flags);
sch->dev.driver_data = NULL;
@@ -1361,7 +1376,6 @@ ccw_device_remove (struct device *dev)
struct ccw_driver *cdrv = cdev->drv;
int ret;
- pr_debug("removing device %s\n", cdev->dev.bus_id);
if (cdrv->remove)
cdrv->remove(cdev);
if (cdev->online) {
@@ -1374,8 +1388,10 @@ ccw_device_remove (struct device *dev)
dev_fsm_final_state(cdev));
else
//FIXME: we can't fail!
- pr_debug("ccw_device_offline returned %d, device %s\n",
- ret, cdev->dev.bus_id);
+ CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+ "device 0.%x.%04x\n",
+ ret, cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
}
ccw_device_set_timeout(cdev, 0);
cdev->drv = NULL;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 6bba809..8633dc5 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -268,7 +268,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
switch (state) {
case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : unknown device %04x on subchannel "
+ "cio: SenseID : unknown device %04x on subchannel "
"0.%x.%04x\n", cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no);
break;
@@ -293,7 +293,8 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
return;
}
/* Issue device info message. */
- CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
+ CIO_DEBUG(KERN_INFO, 2,
+ "cio: SenseID : device 0.%x.%04x reports: "
"CU Type/Mod = %04X/%02X, Dev Type/Mod = "
"%04X/%02X\n",
cdev->private->dev_id.ssid,
@@ -303,7 +304,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
break;
case DEV_STATE_BOXED:
CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : boxed device %04x on subchannel "
+ "cio: SenseID : boxed device %04x on subchannel "
"0.%x.%04x\n", cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no);
break;
@@ -388,7 +389,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED)
CIO_DEBUG(KERN_WARNING, 2,
- "Boxed device %04x on subchannel %04x\n",
+ "cio: Boxed device %04x on subchannel %04x\n",
cdev->private->dev_id.devno, sch->schid.sch_no);
if (cdev->private->flags.donotify) {
@@ -946,9 +947,10 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
/* Basic sense hasn't started. Try again. */
ccw_device_do_sense(cdev, irb);
else {
- printk(KERN_INFO "Huh? %s(%s): unsolicited "
- "interrupt...\n",
- __FUNCTION__, cdev->dev.bus_id);
+ CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited "
+ "interrupt during w4sense...\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
if (cdev->handler)
cdev->handler (cdev, 0, irb);
}
@@ -1215,8 +1217,8 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event)
static void
ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
{
- printk(KERN_EMERG "dev_jumptable[%i][%i] == NULL\n",
- cdev->private->state, dev_event);
+ CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n",
+ cdev->private->state, dev_event);
BUG();
}
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index a5d263f..14eba85 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -288,253 +288,6 @@ ccw_device_get_path_mask(struct ccw_device *cdev)
return sch->lpm;
}
-static void
-ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
-{
- if (!ip)
- /* unsolicited interrupt */
- return;
-
- /* Abuse intparm for error reporting. */
- if (IS_ERR(irb))
- cdev->private->intparm = -EIO;
- else if (irb->scsw.cc == 1)
- /* Retry for deferred condition code. */
- cdev->private->intparm = -EAGAIN;
- else if ((irb->scsw.dstat !=
- (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
- (irb->scsw.cstat != 0)) {
- /*
- * We didn't get channel end / device end. Check if path
- * verification has been started; we can retry after it has
- * finished. We also retry unit checks except for command reject
- * or intervention required. Also check for long busy
- * conditions.
- */
- if (cdev->private->flags.doverify ||
- cdev->private->state == DEV_STATE_VERIFY)
- cdev->private->intparm = -EAGAIN;
- else if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
- !(irb->ecw[0] &
- (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ)))
- cdev->private->intparm = -EAGAIN;
- else if ((irb->scsw.dstat & DEV_STAT_ATTENTION) &&
- (irb->scsw.dstat & DEV_STAT_DEV_END) &&
- (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP))
- cdev->private->intparm = -EAGAIN;
- else
- cdev->private->intparm = -EIO;
-
- } else
- cdev->private->intparm = 0;
- wake_up(&cdev->private->wait_q);
-}
-
-static int
-__ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm)
-{
- int ret;
- struct subchannel *sch;
-
- sch = to_subchannel(cdev->dev.parent);
- do {
- ccw_device_set_timeout(cdev, 60 * HZ);
- ret = cio_start (sch, ccw, lpm);
- if (ret != 0)
- ccw_device_set_timeout(cdev, 0);
- if (ret == -EBUSY) {
- /* Try again later. */
- spin_unlock_irq(sch->lock);
- msleep(10);
- spin_lock_irq(sch->lock);
- continue;
- }
- if (ret != 0)
- /* Non-retryable error. */
- break;
- /* Wait for end of request. */
- cdev->private->intparm = magic;
- spin_unlock_irq(sch->lock);
- wait_event(cdev->private->wait_q,
- (cdev->private->intparm == -EIO) ||
- (cdev->private->intparm == -EAGAIN) ||
- (cdev->private->intparm == 0));
- spin_lock_irq(sch->lock);
- /* Check at least for channel end / device end */
- if (cdev->private->intparm == -EIO) {
- /* Non-retryable error. */
- ret = -EIO;
- break;
- }
- if (cdev->private->intparm == 0)
- /* Success. */
- break;
- /* Try again later. */
- spin_unlock_irq(sch->lock);
- msleep(10);
- spin_lock_irq(sch->lock);
- } while (1);
-
- return ret;
-}
-
-/**
- * read_dev_chars() - read device characteristics
- * @param cdev target ccw device
- * @param buffer pointer to buffer for rdc data
- * @param length size of rdc data
- * @returns 0 for success, negative error value on failure
- *
- * Context:
- * called for online device, lock not held
- **/
-int
-read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
-{
- void (*handler)(struct ccw_device *, unsigned long, struct irb *);
- struct subchannel *sch;
- int ret;
- struct ccw1 *rdc_ccw;
-
- if (!cdev)
- return -ENODEV;
- if (!buffer || !length)
- return -EINVAL;
- sch = to_subchannel(cdev->dev.parent);
-
- CIO_TRACE_EVENT (4, "rddevch");
- CIO_TRACE_EVENT (4, sch->dev.bus_id);
-
- rdc_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
- if (!rdc_ccw)
- return -ENOMEM;
- rdc_ccw->cmd_code = CCW_CMD_RDC;
- rdc_ccw->count = length;
- rdc_ccw->flags = CCW_FLAG_SLI;
- ret = set_normalized_cda (rdc_ccw, (*buffer));
- if (ret != 0) {
- kfree(rdc_ccw);
- return ret;
- }
-
- spin_lock_irq(sch->lock);
- /* Save interrupt handler. */
- handler = cdev->handler;
- /* Temporarily install own handler. */
- cdev->handler = ccw_device_wake_up;
- if (cdev->private->state != DEV_STATE_ONLINE)
- ret = -ENODEV;
- else if (((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
- !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
- cdev->private->flags.doverify)
- ret = -EBUSY;
- else
- /* 0x00D9C4C3 == ebcdic "RDC" */
- ret = __ccw_device_retry_loop(cdev, rdc_ccw, 0x00D9C4C3, 0);
-
- /* Restore interrupt handler. */
- cdev->handler = handler;
- spin_unlock_irq(sch->lock);
-
- clear_normalized_cda (rdc_ccw);
- kfree(rdc_ccw);
-
- return ret;
-}
-
-/*
- * Read Configuration data using path mask
- */
-int
-read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lpm)
-{
- void (*handler)(struct ccw_device *, unsigned long, struct irb *);
- struct subchannel *sch;
- struct ciw *ciw;
- char *rcd_buf;
- int ret;
- struct ccw1 *rcd_ccw;
-
- if (!cdev)
- return -ENODEV;
- if (!buffer || !length)
- return -EINVAL;
- sch = to_subchannel(cdev->dev.parent);
-
- CIO_TRACE_EVENT (4, "rdconf");
- CIO_TRACE_EVENT (4, sch->dev.bus_id);
-
- /*
- * scan for RCD command in extended SenseID data
- */
- ciw = ccw_device_get_ciw(cdev, CIW_TYPE_RCD);
- if (!ciw || ciw->cmd == 0)
- return -EOPNOTSUPP;
-
- /* Adjust requested path mask to excluded varied off paths. */
- if (lpm) {
- lpm &= sch->opm;
- if (lpm == 0)
- return -EACCES;
- }
-
- rcd_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
- if (!rcd_ccw)
- return -ENOMEM;
- rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
- if (!rcd_buf) {
- kfree(rcd_ccw);
- return -ENOMEM;
- }
- rcd_ccw->cmd_code = ciw->cmd;
- rcd_ccw->cda = (__u32) __pa (rcd_buf);
- rcd_ccw->count = ciw->count;
- rcd_ccw->flags = CCW_FLAG_SLI;
-
- spin_lock_irq(sch->lock);
- /* Save interrupt handler. */
- handler = cdev->handler;
- /* Temporarily install own handler. */
- cdev->handler = ccw_device_wake_up;
- if (cdev->private->state != DEV_STATE_ONLINE)
- ret = -ENODEV;
- else if (((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
- !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
- cdev->private->flags.doverify)
- ret = -EBUSY;
- else
- /* 0x00D9C3C4 == ebcdic "RCD" */
- ret = __ccw_device_retry_loop(cdev, rcd_ccw, 0x00D9C3C4, lpm);
-
- /* Restore interrupt handler. */
- cdev->handler = handler;
- spin_unlock_irq(sch->lock);
-
- /*
- * on success we update the user input parms
- */
- if (ret) {
- kfree (rcd_buf);
- *buffer = NULL;
- *length = 0;
- } else {
- *length = ciw->count;
- *buffer = rcd_buf;
- }
- kfree(rcd_ccw);
-
- return ret;
-}
-
-/*
- * Read Configuration data
- */
-int
-read_conf_data (struct ccw_device *cdev, void **buffer, int *length)
-{
- return read_conf_data_lpm (cdev, buffer, length, 0);
-}
-
/*
* Try to break the lock on a boxed device.
*/
@@ -635,12 +388,6 @@ _ccw_device_get_subchannel_number(struct ccw_device *cdev)
return cdev->private->schid.sch_no;
}
-int
-_ccw_device_get_device_number(struct ccw_device *cdev)
-{
- return cdev->private->dev_id.devno;
-}
-
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccw_device_set_options_mask);
@@ -655,9 +402,5 @@ EXPORT_SYMBOL(ccw_device_start_timeout_key);
EXPORT_SYMBOL(ccw_device_start_key);
EXPORT_SYMBOL(ccw_device_get_ciw);
EXPORT_SYMBOL(ccw_device_get_path_mask);
-EXPORT_SYMBOL(read_conf_data);
-EXPORT_SYMBOL(read_dev_chars);
EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
-EXPORT_SYMBOL(_ccw_device_get_device_number);
EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
-EXPORT_SYMBOL_GPL(read_conf_data_lpm);
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index 4c2e171..1aeda27 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -165,11 +165,6 @@ extern int ccw_device_resume(struct ccw_device *);
extern int ccw_device_halt(struct ccw_device *, unsigned long);
extern int ccw_device_clear(struct ccw_device *, unsigned long);
-extern int __deprecated read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
-extern int __deprecated read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
-extern int __deprecated read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
- int *length, __u8 lpm);
-
extern int ccw_device_set_online(struct ccw_device *cdev);
extern int ccw_device_set_offline(struct ccw_device *cdev);
diff --git a/include/asm-s390/s390_ext.h b/include/asm-s390/s390_ext.h
index df9b101..1e72362 100644
--- a/include/asm-s390/s390_ext.h
+++ b/include/asm-s390/s390_ext.h
@@ -10,6 +10,8 @@
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
+#include <linux/types.h>
+
typedef void (*ext_int_handler_t)(__u16 code);
/*
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 76e424f..07708c0 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -36,8 +36,7 @@ extern void machine_halt_smp(void);
extern void machine_power_off_smp(void);
extern void smp_setup_cpu_possible_map(void);
-extern int smp_call_function_on(void (*func) (void *info), void *info,
- int nonatomic, int wait, int cpu);
+
#define NO_PROC_ID 0xFF /* No processor magic marker */
/*
@@ -96,14 +95,6 @@ extern int __cpu_up (unsigned int cpu);
#endif
#ifndef CONFIG_SMP
-static inline int
-smp_call_function_on(void (*func) (void *info), void *info,
- int nonatomic, int wait, int cpu)
-{
- func(info);
- return 0;
-}
-
static inline void smp_send_stop(void)
{
/* Disable all interrupts/machine checks */
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 790c1c5..f04acb2 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -251,7 +251,7 @@
#define __NR_getcpu 311
#define __NR_epoll_pwait 312
#define __NR_utimes 313
-/* Number 314 is reserved for new sys_fallocate */
+#define __NR_fallocate 314
#define __NR_utimensat 315
#define __NR_signalfd 316
#define __NR_timerfd 317
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index ad5150b..983058d 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -479,7 +479,8 @@ static void iucv_setmask_mp(void)
/* Enable all cpus with a declared buffer. */
if (cpu_isset(cpu, iucv_buffer_cpumask) &&
!cpu_isset(cpu, iucv_irq_cpumask))
- smp_call_function_on(iucv_allow_cpu, NULL, 0, 1, cpu);
+ smp_call_function_single(cpu, iucv_allow_cpu,
+ NULL, 0, 1);
preempt_enable();
}
@@ -497,7 +498,7 @@ static void iucv_setmask_up(void)
cpumask = iucv_irq_cpumask;
cpu_clear(first_cpu(iucv_irq_cpumask), cpumask);
for_each_cpu_mask(cpu, cpumask)
- smp_call_function_on(iucv_block_cpu, NULL, 0, 1, cpu);
+ smp_call_function_single(cpu, iucv_block_cpu, NULL, 0, 1);
}
/**
@@ -522,7 +523,7 @@ static int iucv_enable(void)
rc = -EIO;
preempt_disable();
for_each_online_cpu(cpu)
- smp_call_function_on(iucv_declare_cpu, NULL, 0, 1, cpu);
+ smp_call_function_single(cpu, iucv_declare_cpu, NULL, 0, 1);
preempt_enable();
if (cpus_empty(iucv_buffer_cpumask))
/* No cpu could declare an iucv buffer. */
@@ -578,7 +579,7 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
case CPU_ONLINE_FROZEN:
case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN:
- smp_call_function_on(iucv_declare_cpu, NULL, 0, 1, cpu);
+ smp_call_function_single(cpu, iucv_declare_cpu, NULL, 0, 1);
break;
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
@@ -587,10 +588,10 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
if (cpus_empty(cpumask))
/* Can't offline last IUCV enabled cpu. */
return NOTIFY_BAD;
- smp_call_function_on(iucv_retrieve_cpu, NULL, 0, 1, cpu);
+ smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 0, 1);
if (cpus_empty(iucv_irq_cpumask))
- smp_call_function_on(iucv_allow_cpu, NULL, 0, 1,
- first_cpu(iucv_buffer_cpumask));
+ smp_call_function_single(first_cpu(iucv_buffer_cpumask),
+ iucv_allow_cpu, NULL, 0, 1);
break;
}
return NOTIFY_OK;
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-08-22 12:44 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-08-22 12:44 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/hypfs/inode.c | 33 ++++--
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/diag.c | 102 ++++++++++++++++
arch/s390/kernel/dis.c | 2 +-
arch/s390/kernel/kprobes.c | 2 +-
arch/s390/kernel/s390_ksyms.c | 1 -
arch/s390/mm/cmm.c | 1 +
arch/s390/mm/init.c | 17 ---
drivers/s390/block/dasd_diag.c | 1 +
drivers/s390/char/raw3270.c | 1 +
drivers/s390/char/vmur.c | 250 ++++++++++++++++++++++++++--------------
drivers/s390/char/vmur.h | 1 +
drivers/s390/cio/cmf.c | 10 +-
drivers/s390/cio/device.c | 5 +-
drivers/s390/cio/device_id.c | 48 +--------
drivers/s390/cio/qdio.c | 5 +-
include/asm-s390/atomic.h | 26 ++++-
include/asm-s390/cio.h | 15 ---
include/asm-s390/diag.h | 39 ++++++
include/asm-s390/pgalloc.h | 2 -
20 files changed, 371 insertions(+), 192 deletions(-)
create mode 100644 arch/s390/kernel/diag.c
create mode 100644 include/asm-s390/diag.h
Christian Borntraeger (1):
[S390] disassembler: fix b2 opcodes like srst, bsg, and others
Cornelia Huck (2):
[S390] cio: dont forget to set last slot to NULL in ccw_uevent().
[S390] cio: change confusing message in cmf.
David Wilder (1):
[S390] kprobes: fix instruction length calculation
Heiko Carstens (1):
[S390] Change atomic_read/set to inline functions with barrier semantics.
Klaus D. Wacker (2):
[S390] qdio: fix EQBS handling on CCQ96
[S390] qdio: Refresh buffer states for IQDIO Asynchronous output queue
Michael Holzheu (3):
[S390] vmur: fix diag14 exceptions with addresses > 2GB.
[S390] vmur: fix reference counting for vmur device structure
[S390] hypfs: inode corruption due to missing locking
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index ad4ca75..5245717 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -60,17 +60,28 @@ static void hypfs_add_dentry(struct dentry *dentry)
hypfs_last_dentry = dentry;
}
+static inline int hypfs_positive(struct dentry *dentry)
+{
+ return dentry->d_inode && !d_unhashed(dentry);
+}
+
static void hypfs_remove(struct dentry *dentry)
{
struct dentry *parent;
parent = dentry->d_parent;
- if (S_ISDIR(dentry->d_inode->i_mode))
- simple_rmdir(parent->d_inode, dentry);
- else
- simple_unlink(parent->d_inode, dentry);
+ if (!parent || !parent->d_inode)
+ return;
+ mutex_lock(&parent->d_inode->i_mutex);
+ if (hypfs_positive(dentry)) {
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ simple_rmdir(parent->d_inode, dentry);
+ else
+ simple_unlink(parent->d_inode, dentry);
+ }
d_delete(dentry);
dput(dentry);
+ mutex_unlock(&parent->d_inode->i_mutex);
}
static void hypfs_delete_tree(struct dentry *root)
@@ -315,6 +326,7 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
}
hypfs_update_update(sb);
sb->s_root = root_dentry;
+ printk(KERN_INFO "hypfs: Hypervisor filesystem mounted\n");
return 0;
err_tree:
@@ -356,13 +368,17 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
qname.name = name;
qname.len = strlen(name);
qname.hash = full_name_hash(name, qname.len);
+ mutex_lock(&parent->d_inode->i_mutex);
dentry = lookup_one_len(name, parent, strlen(name));
- if (IS_ERR(dentry))
- return ERR_PTR(-ENOMEM);
+ if (IS_ERR(dentry)) {
+ dentry = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
inode = hypfs_make_inode(sb, mode);
if (!inode) {
dput(dentry);
- return ERR_PTR(-ENOMEM);
+ dentry = ERR_PTR(-ENOMEM);
+ goto fail;
}
if (mode & S_IFREG) {
inode->i_fop = &hypfs_file_ops;
@@ -379,6 +395,8 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
inode->i_private = data;
d_instantiate(dentry, inode);
dget(dentry);
+fail:
+ mutex_unlock(&parent->d_inode->i_mutex);
return dentry;
}
@@ -391,7 +409,6 @@ struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
if (IS_ERR(dentry))
return dentry;
hypfs_add_dentry(dentry);
- parent->d_inode->i_nlink++;
return dentry;
}
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 3195d37..56cb710 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o base.o early.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o
+ semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c
new file mode 100644
index 0000000..c032d11
--- /dev/null
+++ b/arch/s390/kernel/diag.c
@@ -0,0 +1,102 @@
+/*
+ * Implementation of s390 diagnose codes
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <asm/diag.h>
+
+/*
+ * Diagnose 10: Release pages
+ */
+void diag10(unsigned long addr)
+{
+ if (addr >= 0x7ff00000)
+ return;
+ asm volatile(
+#ifdef CONFIG_64BIT
+ " sam31\n"
+ " diag %0,%0,0x10\n"
+ "0: sam64\n"
+#else
+ " diag %0,%0,0x10\n"
+ "0:\n"
+#endif
+ EX_TABLE(0b, 0b)
+ : : "a" (addr));
+}
+EXPORT_SYMBOL(diag10);
+
+/*
+ * Diagnose 14: Input spool file manipulation
+ */
+int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
+{
+ register unsigned long _ry1 asm("2") = ry1;
+ register unsigned long _ry2 asm("3") = subcode;
+ int rc = 0;
+
+ asm volatile(
+#ifdef CONFIG_64BIT
+ " sam31\n"
+ " diag %2,2,0x14\n"
+ " sam64\n"
+#else
+ " diag %2,2,0x14\n"
+#endif
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (rc), "+d" (_ry2)
+ : "d" (rx), "d" (_ry1)
+ : "cc");
+
+ return rc;
+}
+EXPORT_SYMBOL(diag14);
+
+/*
+ * Diagnose 210: Get information about a virtual device
+ */
+int diag210(struct diag210 *addr)
+{
+ /*
+ * diag 210 needs its data below the 2GB border, so we
+ * use a static data area to be sure
+ */
+ static struct diag210 diag210_tmp;
+ static DEFINE_SPINLOCK(diag210_lock);
+ unsigned long flags;
+ int ccode;
+
+ spin_lock_irqsave(&diag210_lock, flags);
+ diag210_tmp = *addr;
+
+#ifdef CONFIG_64BIT
+ asm volatile(
+ " lhi %0,-1\n"
+ " sam31\n"
+ " diag %1,0,0x210\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1: sam64\n"
+ EX_TABLE(0b, 1b)
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#else
+ asm volatile(
+ " lhi %0,-1\n"
+ " diag %1,0,0x210\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ EX_TABLE(0b, 1b)
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+ *addr = diag210_tmp;
+ spin_unlock_irqrestore(&diag210_lock, flags);
+
+ return ccode;
+}
+EXPORT_SYMBOL(diag210);
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index d305731..50d2235 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -577,7 +577,7 @@ static struct insn opcode_b2[] = {
{ "esta", 0x4a, INSTR_RRE_RR },
{ "lura", 0x4b, INSTR_RRE_RR },
{ "tar", 0x4c, INSTR_RRE_AR },
- { "cpya", INSTR_RRE_AA },
+ { "cpya", 0x4d, INSTR_RRE_AA },
{ "sar", 0x4e, INSTR_RRE_AR },
{ "ear", 0x4f, INSTR_RRE_RA },
{ "csp", 0x50, INSTR_RRE_RR },
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 358d2bb..e40373d 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -85,7 +85,7 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
ainsn->reg = (*ainsn->insn & 0xf0) >> 4;
/* save the instruction length (pop 5-5) in bytes */
- switch (*(__u8 *) (ainsn->insn) >> 4) {
+ switch (*(__u8 *) (ainsn->insn) >> 6) {
case 0:
ainsn->ilen = 2;
break;
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 90b5ef5..7234c73 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -25,7 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap);
EXPORT_SYMBOL(_ni_bitmap);
EXPORT_SYMBOL(_zb_findmap);
EXPORT_SYMBOL(_sb_findmap);
-EXPORT_SYMBOL(diag10);
/*
* semaphore ops
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index c5b2f4f..fabc50a 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -20,6 +20,7 @@
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
+#include <asm/diag.h>
static char *sender = "VMRMSVM";
module_param(sender, charp, 0400);
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 9098531..3a25bbf 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -42,23 +42,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-void diag10(unsigned long addr)
-{
- if (addr >= 0x7ff00000)
- return;
- asm volatile(
-#ifdef CONFIG_64BIT
- " sam31\n"
- " diag %0,%0,0x10\n"
- "0: sam64\n"
-#else
- " diag %0,%0,0x10\n"
- "0:\n"
-#endif
- EX_TABLE(0b,0b)
- : : "a" (addr));
-}
-
void show_mem(void)
{
int i, total = 0, reserved = 0;
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index eccac1c..d32c60d 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -24,6 +24,7 @@
#include <asm/s390_ext.h>
#include <asm/todclk.h>
#include <asm/vtoc.h>
+#include <asm/diag.h>
#include "dasd_int.h"
#include "dasd_diag.h"
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 4f2f81b..2edd5fb 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -21,6 +21,7 @@
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include <asm/ebcdic.h>
+#include <asm/diag.h>
#include "raw3270.h"
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 04b19bd..d70a6e6 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -14,6 +14,7 @@
#include <asm/cio.h>
#include <asm/ccwdev.h>
#include <asm/debug.h>
+#include <asm/diag.h>
#include "vmur.h"
@@ -68,8 +69,26 @@ static struct ccw_driver ur_driver = {
.set_offline = ur_set_offline,
};
+static DEFINE_MUTEX(vmur_mutex);
+
/*
* Allocation, freeing, getting and putting of urdev structures
+ *
+ * Each ur device (urd) contains a reference to its corresponding ccw device
+ * (cdev) using the urd->cdev pointer. Each ccw device has a reference to the
+ * ur device using the cdev->dev.driver_data pointer.
+ *
+ * urd references:
+ * - ur_probe gets a urd reference, ur_remove drops the reference
+ * (cdev->dev.driver_data)
+ * - ur_open gets a urd reference, ur_relase drops the reference
+ * (urf->urd)
+ *
+ * cdev references:
+ * - urdev_alloc get a cdev reference (urd->cdev)
+ * - urdev_free drops the cdev reference (urd->cdev)
+ *
+ * Setting and clearing of cdev->dev.driver_data is protected by the ccwdev lock
*/
static struct urdev *urdev_alloc(struct ccw_device *cdev)
{
@@ -78,42 +97,61 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
urd = kzalloc(sizeof(struct urdev), GFP_KERNEL);
if (!urd)
return NULL;
- urd->cdev = cdev;
urd->reclen = cdev->id.driver_info;
ccw_device_get_id(cdev, &urd->dev_id);
mutex_init(&urd->io_mutex);
mutex_init(&urd->open_mutex);
+ atomic_set(&urd->ref_count, 1);
+ urd->cdev = cdev;
+ get_device(&cdev->dev);
return urd;
}
static void urdev_free(struct urdev *urd)
{
+ TRACE("urdev_free: %p\n", urd);
+ if (urd->cdev)
+ put_device(&urd->cdev->dev);
kfree(urd);
}
-/*
- * This is how the character device driver gets a reference to a
- * ur device. When this call returns successfully, a reference has
- * been taken (by get_device) on the underlying kobject. The recipient
- * of this urdev pointer must eventually drop it with urdev_put(urd)
- * which does the corresponding put_device().
- */
+static void urdev_get(struct urdev *urd)
+{
+ atomic_inc(&urd->ref_count);
+}
+
+static struct urdev *urdev_get_from_cdev(struct ccw_device *cdev)
+{
+ struct urdev *urd;
+ unsigned long flags;
+
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ urd = cdev->dev.driver_data;
+ if (urd)
+ urdev_get(urd);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+ return urd;
+}
+
static struct urdev *urdev_get_from_devno(u16 devno)
{
char bus_id[16];
struct ccw_device *cdev;
+ struct urdev *urd;
sprintf(bus_id, "0.0.%04x", devno);
cdev = get_ccwdev_by_busid(&ur_driver, bus_id);
if (!cdev)
return NULL;
-
- return cdev->dev.driver_data;
+ urd = urdev_get_from_cdev(cdev);
+ put_device(&cdev->dev);
+ return urd;
}
static void urdev_put(struct urdev *urd)
{
- put_device(&urd->cdev->dev);
+ if (atomic_dec_and_test(&urd->ref_count))
+ urdev_free(urd);
}
/*
@@ -245,6 +283,7 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
return;
}
urd = cdev->dev.driver_data;
+ BUG_ON(!urd);
/* On special conditions irb is an error pointer */
if (IS_ERR(irb))
urd->io_request_rc = PTR_ERR(irb);
@@ -262,9 +301,15 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
static ssize_t ur_attr_reclen_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct urdev *urd = dev->driver_data;
+ struct urdev *urd;
+ int rc;
- return sprintf(buf, "%zu\n", urd->reclen);
+ urd = urdev_get_from_cdev(to_ccwdev(dev));
+ if (!urd)
+ return -ENODEV;
+ rc = sprintf(buf, "%zu\n", urd->reclen);
+ urdev_put(urd);
+ return rc;
}
static DEVICE_ATTR(reclen, 0444, ur_attr_reclen_show, NULL);
@@ -379,31 +424,6 @@ static ssize_t ur_write(struct file *file, const char __user *udata,
return do_write(urf->urd, udata, count, urf->dev_reclen, ppos);
}
-static int do_diag_14(unsigned long rx, unsigned long ry1,
- unsigned long subcode)
-{
- register unsigned long _ry1 asm("2") = ry1;
- register unsigned long _ry2 asm("3") = subcode;
- int rc = 0;
-
- asm volatile(
-#ifdef CONFIG_64BIT
- " sam31\n"
- " diag %2,2,0x14\n"
- " sam64\n"
-#else
- " diag %2,2,0x14\n"
-#endif
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (rc), "+d" (_ry2)
- : "d" (rx), "d" (_ry1)
- : "cc");
-
- TRACE("diag 14: subcode=0x%lx, cc=%i\n", subcode, rc);
- return rc;
-}
-
/*
* diagnose code 0x14 subcode 0x0028 - position spool file to designated
* record
@@ -415,7 +435,7 @@ static int diag_position_to_record(int devno, int record)
{
int cc;
- cc = do_diag_14(record, devno, 0x28);
+ cc = diag14(record, devno, 0x28);
switch (cc) {
case 0:
return 0;
@@ -440,7 +460,7 @@ static int diag_read_file(int devno, char *buf)
{
int cc;
- cc = do_diag_14((unsigned long) buf, devno, 0x00);
+ cc = diag14((unsigned long) buf, devno, 0x00);
switch (cc) {
case 0:
return 0;
@@ -533,7 +553,7 @@ static int diag_read_next_file_info(struct file_control_block *buf, int spid)
{
int cc;
- cc = do_diag_14((unsigned long) buf, spid, 0xfff);
+ cc = diag14((unsigned long) buf, spid, 0xfff);
switch (cc) {
case 0:
return 0;
@@ -750,64 +770,63 @@ static struct file_operations ur_fops = {
/*
* ccw_device infrastructure:
- * ur_probe gets its own ref to the device (i.e. get_device),
- * creates the struct urdev, the device attributes, sets up
- * the interrupt handler and validates the virtual unit record device.
- * ur_remove removes the device attributes, frees the struct urdev
- * and drops (put_device) the ref to the device we got in ur_probe.
+ * ur_probe creates the struct urdev (with refcount = 1), the device
+ * attributes, sets up the interrupt handler and validates the virtual
+ * unit record device.
+ * ur_remove removes the device attributes and drops the reference to
+ * struct urdev.
+ *
+ * ur_probe, ur_remove, ur_set_online and ur_set_offline are serialized
+ * by the vmur_mutex lock.
+ *
+ * urd->char_device is used as indication that the online function has
+ * been completed successfully.
*/
static int ur_probe(struct ccw_device *cdev)
{
struct urdev *urd;
int rc;
- TRACE("ur_probe: cdev=%p state=%d\n", cdev, *(int *) cdev->private);
-
- if (!get_device(&cdev->dev))
- return -ENODEV;
+ TRACE("ur_probe: cdev=%p\n", cdev);
+ mutex_lock(&vmur_mutex);
urd = urdev_alloc(cdev);
if (!urd) {
rc = -ENOMEM;
- goto fail;
+ goto fail_unlock;
}
+
rc = ur_create_attributes(&cdev->dev);
if (rc) {
rc = -ENOMEM;
- goto fail;
+ goto fail_urdev_put;
}
- cdev->dev.driver_data = urd;
cdev->handler = ur_int_handler;
/* validate virtual unit record device */
urd->class = get_urd_class(urd);
if (urd->class < 0) {
rc = urd->class;
- goto fail;
+ goto fail_remove_attr;
}
if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) {
rc = -ENOTSUPP;
- goto fail;
+ goto fail_remove_attr;
}
+ spin_lock_irq(get_ccwdev_lock(cdev));
+ cdev->dev.driver_data = urd;
+ spin_unlock_irq(get_ccwdev_lock(cdev));
+ mutex_unlock(&vmur_mutex);
return 0;
-fail:
- urdev_free(urd);
- put_device(&cdev->dev);
- return rc;
-}
-
-static void ur_remove(struct ccw_device *cdev)
-{
- struct urdev *urd = cdev->dev.driver_data;
-
- TRACE("ur_remove\n");
- if (cdev->online)
- ur_set_offline(cdev);
+fail_remove_attr:
ur_remove_attributes(&cdev->dev);
- urdev_free(urd);
- put_device(&cdev->dev);
+fail_urdev_put:
+ urdev_put(urd);
+fail_unlock:
+ mutex_unlock(&vmur_mutex);
+ return rc;
}
static int ur_set_online(struct ccw_device *cdev)
@@ -816,20 +835,29 @@ static int ur_set_online(struct ccw_device *cdev)
int minor, major, rc;
char node_id[16];
- TRACE("ur_set_online: cdev=%p state=%d\n", cdev,
- *(int *) cdev->private);
+ TRACE("ur_set_online: cdev=%p\n", cdev);
- if (!try_module_get(ur_driver.owner))
- return -EINVAL;
+ mutex_lock(&vmur_mutex);
+ urd = urdev_get_from_cdev(cdev);
+ if (!urd) {
+ /* ur_remove already deleted our urd */
+ rc = -ENODEV;
+ goto fail_unlock;
+ }
+
+ if (urd->char_device) {
+ /* Another ur_set_online was faster */
+ rc = -EBUSY;
+ goto fail_urdev_put;
+ }
- urd = (struct urdev *) cdev->dev.driver_data;
minor = urd->dev_id.devno;
major = MAJOR(ur_first_dev_maj_min);
urd->char_device = cdev_alloc();
if (!urd->char_device) {
rc = -ENOMEM;
- goto fail_module_put;
+ goto fail_urdev_put;
}
cdev_init(urd->char_device, &ur_fops);
@@ -858,29 +886,79 @@ static int ur_set_online(struct ccw_device *cdev)
TRACE("ur_set_online: device_create rc=%d\n", rc);
goto fail_free_cdev;
}
-
+ urdev_put(urd);
+ mutex_unlock(&vmur_mutex);
return 0;
fail_free_cdev:
cdev_del(urd->char_device);
-fail_module_put:
- module_put(ur_driver.owner);
-
+ urd->char_device = NULL;
+fail_urdev_put:
+ urdev_put(urd);
+fail_unlock:
+ mutex_unlock(&vmur_mutex);
return rc;
}
-static int ur_set_offline(struct ccw_device *cdev)
+static int ur_set_offline_force(struct ccw_device *cdev, int force)
{
struct urdev *urd;
+ int rc;
- TRACE("ur_set_offline: cdev=%p cdev->private=%p state=%d\n",
- cdev, cdev->private, *(int *) cdev->private);
- urd = (struct urdev *) cdev->dev.driver_data;
+ TRACE("ur_set_offline: cdev=%p\n", cdev);
+ urd = urdev_get_from_cdev(cdev);
+ if (!urd)
+ /* ur_remove already deleted our urd */
+ return -ENODEV;
+ if (!urd->char_device) {
+ /* Another ur_set_offline was faster */
+ rc = -EBUSY;
+ goto fail_urdev_put;
+ }
+ if (!force && (atomic_read(&urd->ref_count) > 2)) {
+ /* There is still a user of urd (e.g. ur_open) */
+ TRACE("ur_set_offline: BUSY\n");
+ rc = -EBUSY;
+ goto fail_urdev_put;
+ }
device_destroy(vmur_class, urd->char_device->dev);
cdev_del(urd->char_device);
- module_put(ur_driver.owner);
+ urd->char_device = NULL;
+ rc = 0;
- return 0;
+fail_urdev_put:
+ urdev_put(urd);
+ return rc;
+}
+
+static int ur_set_offline(struct ccw_device *cdev)
+{
+ int rc;
+
+ mutex_lock(&vmur_mutex);
+ rc = ur_set_offline_force(cdev, 0);
+ mutex_unlock(&vmur_mutex);
+ return rc;
+}
+
+static void ur_remove(struct ccw_device *cdev)
+{
+ unsigned long flags;
+
+ TRACE("ur_remove\n");
+
+ mutex_lock(&vmur_mutex);
+
+ if (cdev->online)
+ ur_set_offline_force(cdev, 1);
+ ur_remove_attributes(&cdev->dev);
+
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ urdev_put(cdev->dev.driver_data);
+ cdev->dev.driver_data = NULL;
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+
+ mutex_unlock(&vmur_mutex);
}
/*
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
index 2b3c564..fa95964 100644
--- a/drivers/s390/char/vmur.h
+++ b/drivers/s390/char/vmur.h
@@ -70,6 +70,7 @@ struct urdev {
size_t reclen; /* Record length for *write* CCWs */
int class; /* VM device class */
int io_request_rc; /* return code from I/O request */
+ atomic_t ref_count; /* reference counter */
};
/*
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 02fd00b..34a7969 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -594,6 +594,9 @@ alloc_cmb (struct ccw_device *cdev)
free_pages((unsigned long)mem, get_order(size));
} else if (!mem) {
/* no luck */
+ printk(KERN_WARNING "cio: failed to allocate area "
+ "for measuring %d subchannels\n",
+ cmb_area.num_channels);
ret = -ENOMEM;
goto out;
} else {
@@ -1279,13 +1282,6 @@ init_cmf(void)
case CMF_BASIC:
format_string = "basic";
cmbops = &cmbops_basic;
- if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) {
- printk(KERN_ERR "cio: Basic channel measurement "
- "facility can only use 1 to 4096 devices\n"
- KERN_ERR "when the cmf driver is built"
- " as a loadable module\n");
- return 1;
- }
break;
case CMF_EXTENDED:
format_string = "extended";
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 297659f..e44d92e 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -117,7 +117,10 @@ static int ccw_uevent(struct device *dev, char **envp, int num_envp,
snprint_alias(modalias_buf, sizeof(modalias_buf), id, "");
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
"MODALIAS=%s", modalias_buf);
- return ret;
+ if (ret)
+ return ret;
+ envp[i] = NULL;
+ return 0;
}
struct bus_type ccw_bus_type;
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 60b9347..f232832 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -17,6 +17,7 @@
#include <asm/delay.h>
#include <asm/cio.h>
#include <asm/lowcore.h>
+#include <asm/diag.h>
#include "cio.h"
#include "cio_debug.h"
@@ -25,51 +26,6 @@
#include "ioasm.h"
/*
- * diag210 is used under VM to get information about a virtual device
- */
-int
-diag210(struct diag210 * addr)
-{
- /*
- * diag 210 needs its data below the 2GB border, so we
- * use a static data area to be sure
- */
- static struct diag210 diag210_tmp;
- static DEFINE_SPINLOCK(diag210_lock);
- unsigned long flags;
- int ccode;
-
- spin_lock_irqsave(&diag210_lock, flags);
- diag210_tmp = *addr;
-
-#ifdef CONFIG_64BIT
- asm volatile(
- " lhi %0,-1\n"
- " sam31\n"
- " diag %1,0,0x210\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- "1: sam64\n"
- EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
-#else
- asm volatile(
- " lhi %0,-1\n"
- " diag %1,0,0x210\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- "1:\n"
- EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
-#endif
-
- *addr = diag210_tmp;
- spin_unlock_irqrestore(&diag210_lock, flags);
-
- return ccode;
-}
-
-/*
* Input :
* devno - device number
* ps - pointer to sense ID data area
@@ -349,5 +305,3 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
break;
}
}
-
-EXPORT_SYMBOL(diag210);
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 03347ae..d8d4798 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -195,6 +195,8 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
again:
ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if ((ccq == 96) && (tmp_cnt != *cnt))
+ rc = 0;
if (rc == 1) {
QDIO_DBF_TEXT5(1,trace,"eqAGAIN");
goto again;
@@ -740,7 +742,8 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q)
first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
(QDIO_MAX_BUFFERS_PER_Q-1));
- if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis))
+ if (((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis)) ||
+ (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH))
SYNC_MEMORY;
check_next:
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index ea48695..2d18465 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -67,8 +67,17 @@ typedef struct {
#endif /* __GNUC__ */
-#define atomic_read(v) ((v)->counter)
-#define atomic_set(v,i) (((v)->counter) = (i))
+static inline int atomic_read(const atomic_t *v)
+{
+ barrier();
+ return v->counter;
+}
+
+static inline void atomic_set(atomic_t *v, int i)
+{
+ v->counter = i;
+ barrier();
+}
static __inline__ int atomic_add_return(int i, atomic_t * v)
{
@@ -182,8 +191,17 @@ typedef struct {
#endif /* __GNUC__ */
-#define atomic64_read(v) ((v)->counter)
-#define atomic64_set(v,i) (((v)->counter) = (i))
+static inline long long atomic64_read(const atomic64_t *v)
+{
+ barrier();
+ return v->counter;
+}
+
+static inline void atomic64_set(atomic64_t *v, long long i)
+{
+ v->counter = i;
+ barrier();
+}
static __inline__ long long atomic64_add_return(long long i, atomic64_t * v)
{
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
index f738d28..1982fb3 100644
--- a/include/asm-s390/cio.h
+++ b/include/asm-s390/cio.h
@@ -258,19 +258,6 @@ struct ciw {
/* Sick revalidation of device. */
#define CIO_REVALIDATE 0x0008
-struct diag210 {
- __u16 vrdcdvno : 16; /* device number (input) */
- __u16 vrdclen : 16; /* data block length (input) */
- __u32 vrdcvcla : 8; /* virtual device class (output) */
- __u32 vrdcvtyp : 8; /* virtual device type (output) */
- __u32 vrdcvsta : 8; /* virtual device status (output) */
- __u32 vrdcvfla : 8; /* virtual device flags (output) */
- __u32 vrdcrccl : 8; /* real device class (output) */
- __u32 vrdccrty : 8; /* real device type (output) */
- __u32 vrdccrmd : 8; /* real device model (output) */
- __u32 vrdccrft : 8; /* real device feature (output) */
-} __attribute__ ((packed,aligned(4)));
-
struct ccw_dev_id {
u8 ssid;
u16 devno;
@@ -285,8 +272,6 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1,
return 0;
}
-extern int diag210(struct diag210 *addr);
-
extern void wait_cons_dev(void);
extern void css_schedule_reprobe(void);
diff --git a/include/asm-s390/diag.h b/include/asm-s390/diag.h
new file mode 100644
index 0000000..72b2e2f
--- /dev/null
+++ b/include/asm-s390/diag.h
@@ -0,0 +1,39 @@
+/*
+ * s390 diagnose functions
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_DIAG_H
+#define _ASM_S390_DIAG_H
+
+/*
+ * Diagnose 10: Release pages
+ */
+extern void diag10(unsigned long addr);
+
+/*
+ * Diagnose 14: Input spool file manipulation
+ */
+extern int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode);
+
+/*
+ * Diagnose 210: Get information about a virtual device
+ */
+struct diag210 {
+ u16 vrdcdvno; /* device number (input) */
+ u16 vrdclen; /* data block length (input) */
+ u8 vrdcvcla; /* virtual device class (output) */
+ u8 vrdcvtyp; /* virtual device type (output) */
+ u8 vrdcvsta; /* virtual device status (output) */
+ u8 vrdcvfla; /* virtual device flags (output) */
+ u8 vrdcrccl; /* real device class (output) */
+ u8 vrdccrty; /* real device type (output) */
+ u8 vrdccrmd; /* real device model (output) */
+ u8 vrdccrft; /* real device feature (output) */
+} __attribute__((packed, aligned(4)));
+
+extern int diag210(struct diag210 *addr);
+
+#endif /* _ASM_S390_DIAG_H */
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 56c8a6c..e45d3c9 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -19,8 +19,6 @@
#define check_pgt_cache() do {} while (0)
-extern void diag10(unsigned long addr);
-
/*
* Page allocation orders.
*/
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-10-12 14:22 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-10-12 14:22 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
Documentation/DocBook/Makefile | 2 +-
Documentation/DocBook/s390-drivers.tmpl | 149 ++++++++++++++++
Documentation/s390/00-INDEX | 26 +++
Documentation/s390/CommonIO | 51 +++---
Documentation/s390/cds.txt | 8 +-
arch/s390/appldata/appldata_base.c | 59 +------
arch/s390/kernel/audit.c | 7 +-
arch/s390/kernel/audit.h | 15 ++
arch/s390/kernel/compat_audit.c | 1 +
arch/s390/kernel/cpcmd.c | 100 ++++++-----
arch/s390/kernel/dis.c | 5 +-
arch/s390/kernel/ipl.c | 4 +-
arch/s390/kernel/vmlinux.lds.S | 234 ++++++++++++++-----------
arch/s390/mm/fault.c | 2 +-
drivers/block/Kconfig | 3 +-
drivers/s390/block/dasd_int.h | 3 +-
drivers/s390/block/xpram.c | 2 +-
drivers/s390/char/con3215.c | 3 +
drivers/s390/char/con3270.c | 3 +-
drivers/s390/char/sclp.c | 5 +-
drivers/s390/char/tape_3590.c | 26 ++-
drivers/s390/char/tty3270.c | 9 +-
drivers/s390/char/tty3270.h | 16 ++
drivers/s390/char/vmwatchdog.c | 4 +-
drivers/s390/char/zcore.c | 7 +-
drivers/s390/cio/ccwgroup.c | 67 ++++++--
drivers/s390/cio/chp.c | 30 ++--
drivers/s390/cio/cio.c | 5 +
drivers/s390/cio/cmf.c | 232 ++++++++++++++++---------
drivers/s390/cio/css.c | 98 ++++++++----
drivers/s390/cio/css.h | 3 +-
drivers/s390/cio/device.c | 80 ++++++++--
drivers/s390/cio/device.h | 1 -
drivers/s390/cio/device_fsm.c | 147 +++-------------
drivers/s390/cio/device_ops.c | 241 ++++++++++++++++++++++----
drivers/s390/cio/qdio.c | 39 ++--
drivers/s390/crypto/ap_bus.c | 5 +-
drivers/s390/crypto/zcrypt_mono.c | 4 +-
drivers/s390/crypto/zcrypt_pcixcc.c | 9 +-
drivers/s390/crypto/zcrypt_pcixcc.h | 45 -----
drivers/s390/scsi/zfcp_ccw.c | 10 +-
drivers/s390/scsi/zfcp_dbf.c | 10 +-
drivers/s390/scsi/zfcp_erp.c | 18 +-
include/asm-s390/cache.h | 2 -
include/asm-s390/ccwdev.h | 77 ++++-----
include/asm-s390/ccwgroup.h | 32 +++-
include/asm-s390/cio.h | 288 +++++++++++++++++++++----------
include/asm-s390/cmb.h | 73 ++------
include/asm-s390/page.h | 3 +-
include/asm-s390/pgtable.h | 13 +-
include/asm-s390/s390_ext.h | 8 +-
include/asm-s390/system.h | 24 ++--
include/asm-s390/zcrypt.h | 4 +-
53 files changed, 1427 insertions(+), 885 deletions(-)
create mode 100644 Documentation/DocBook/s390-drivers.tmpl
create mode 100644 Documentation/s390/00-INDEX
create mode 100644 arch/s390/kernel/audit.h
create mode 100644 drivers/s390/char/tty3270.h
Christian Borntraeger (2):
[S390] disassembler: Remove redundant variable assignment
[S390] remove packed attribute from ext_int_info_t.
Cornelia Huck (15):
[S390] cio: rename css to channel_subsystems
[S390] cio: remove subchannel_add_files()
[S390] cio: Fix some coding style issues in cmf.
[S390] cio: Kerneldoc comments for cmf.
[S390] cio: Add docbook comments.
[S390] cio: Add s390-drivers book.
[S390] cio: Minor style fixes.
[S390] cio: Disable channel path measurements on shutdown/reboot.
[S390] cio: Introduce ccw_bus_type.shutdown.
[S390] cio: Disable channel measurements (cmf) on shutdown/reboot.
[S390] cio: Fix device attributes for early devices.
[S390] Add Documentation/s390/00-INDEX.
[S390] cio: Documentation update.
[S390] cio: Avoid machine check vs. not operational races.
[S390] 3215: Handle special console device.
Heiko Carstens (9):
[S390] zcrypt: make init/exit functions static.
[S390] Get rid of a bunch of sparse warnings again.
[S390] Get rid of ARCH_KMALLOC_MINALIGN.
[S390] qdio: dont cast function pointers and use them to call functions.
[S390] Force link error if xchg/cmpxchg gets called with unsupported size.
[S390] Make vmalloc area start at address > 4GB.
[S390] cpcmd: fix inline assembly usage.
[S390] vmwatchdog: fix broken inline assembly.
[S390] pfault: Fix alignment of parameter list.
Martin Schwidefsky (2):
[S390] disassembler: fix output for insns with 6 operands.
[S390] xpram: fix bio_end{_,}io typo
Michael Holzheu (3):
[S390] Use IPL CLEAR for reipl under z/VM
[S390] zcore: fix inline assembly in memcpy_real()
[S390] tape: Fix medium state handling
Ralph Wuerthner (3):
[S390] zcrypt: remove duplicated struct CPRBX definition
[S390] zcrypt: fix ap_reset_domain()
[S390] zcrypt: fix PCIXCC/CEX2C error recovery
Robert P. J. Day (1):
[S390] Remove obsolete recommendation for 8M ramdisk size.
Sam Ravnborg (2):
[S390] s390: beautify vmlinux.lds
[S390] s390: use PAGE_SIZE in vmlinux.lds
Satyam Sharma (2):
[S390] appldata_base: Misc cpuinit annotations and bugfix
[S390] appldata_base: Remove module_exit function and modular stuff
Ursula Braun (1):
[S390] qdio: change QDIO performance_stats error message priority
vignesh babu (1):
[S390] is_power_of_2 in drivers/s390/block/dasd_int.h
Diff too long ..
^ permalink raw reply [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-10-22 10:54 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-10-22 10:54 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/defconfig | 131 ++++++++-----
arch/s390/kernel/ipl.c | 2 +
arch/s390/kernel/process.c | 18 ++-
arch/s390/kernel/smp.c | 65 ++++++-
arch/s390/lib/uaccess_pt.c | 90 +++------
arch/s390/mm/Makefile | 2 +-
arch/s390/mm/init.c | 32 ++--
arch/s390/mm/pgtable.c | 94 +++++++++
arch/s390/mm/vmem.c | 53 ++++--
drivers/s390/char/raw3270.c | 26 +--
drivers/s390/char/tape_class.c | 19 +--
drivers/s390/char/tape_class.h | 4 +-
drivers/s390/char/vmlogrdr.c | 15 +-
drivers/s390/cio/chp.c | 12 +-
drivers/s390/cio/css.c | 9 +
include/asm-s390/cpu.h | 25 +++
include/asm-s390/mmu_context.h | 50 +++---
include/asm-s390/page.h | 4 +
include/asm-s390/pgalloc.h | 250 ++++++++---------------
include/asm-s390/pgtable.h | 429 +++++++++++++++++++++-------------------
include/asm-s390/processor.h | 20 +--
include/asm-s390/tlb.h | 129 +++++++++++-
include/asm-s390/tlbflush.h | 152 ++++++---------
23 files changed, 918 insertions(+), 713 deletions(-)
create mode 100644 arch/s390/mm/pgtable.c
create mode 100644 include/asm-s390/cpu.h
Cornelia Huck (3):
[S390] cio: Use to_channelpath() for device to channel path conversion.
[S390] cio: Fix incomplete commit for uevent suppression.
[S390] struct class_device -> struct device conversion.
Heiko Carstens (1):
[S390] Add per-cpu idle time / idle count sysfs attributes.
Martin Schwidefsky (6):
[S390] Update default configuration.
[S390] tlb flush fix.
[S390] Remove unused user_seg from thread structure.
[S390] Introduce follow_table in uaccess_pt.c
[S390] Cleanup page table definitions.
[S390] 4level-fixup cleanup
Michael Holzheu (1):
[S390] kernel: Fix dump on panic for DASDs under LPAR.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-11-20 11:38 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-11-20 11:38 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/appldata/appldata.h | 1 -
arch/s390/appldata/appldata_base.c | 74 ++++----------------
arch/s390/appldata/appldata_mem.c | 1 -
arch/s390/appldata/appldata_net_sum.c | 1 -
arch/s390/appldata/appldata_os.c | 1 -
arch/s390/kernel/early.c | 2 +-
arch/s390/kernel/entry.S | 120 +++++++++++++++++++++-----------
arch/s390/kernel/entry64.S | 114 ++++++++++++++++++++-----------
arch/s390/kernel/setup.c | 6 ++-
arch/s390/kernel/smp.c | 56 ++-------------
arch/s390/kernel/traps.c | 1 +
arch/s390/mm/cmm.c | 3 -
drivers/s390/cio/css.c | 2 +-
drivers/s390/cio/device_fsm.c | 2 +-
drivers/s390/cio/device_id.c | 45 +++----------
include/asm-s390/system.h | 5 ++
include/linux/sysctl.h | 6 --
kernel/sysctl_check.c | 14 ----
mm/rmap.c | 9 ++-
net/iucv/iucv.c | 107 +++++++++++++++++-------------
20 files changed, 263 insertions(+), 307 deletions(-)
Christian Borntraeger (2):
[S390] magic sysrq: check for in_atomic before doing an console_unblank
[S390] Optimize storage key handling for anonymous pages
Christoph Lameter (1):
[S390] Explicitly code allocpercpu calls in iucv
Cornelia Huck (1):
[S390] cio: Register/unregister subchannels only from kslowcrw.
Heiko Carstens (7):
[S390] Fix irq tracing and lockdep_sys_exit calls.
[S390] cmm: remove unused binary sysctls.
[S390] appldata: remove unused binary sysctls.
[S390] Fix kernel preemption.
[S390] Dont overwrite lowcores on smp_send_stop().
[S390] Fix memory detection.
[S390] Add missing die_notifier() call to die().
Peter Oberparleiter (1):
[S390] cio: change device sense procedure to work with pav aliases
diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h
index 4069b81..db3ae85 100644
--- a/arch/s390/appldata/appldata.h
+++ b/arch/s390/appldata/appldata.h
@@ -45,7 +45,6 @@ struct appldata_ops {
int active; /* monitoring status */
/* fill in from here */
- unsigned int ctl_nr; /* sysctl ID */
char name[APPLDATA_PROC_NAME_LENGTH]; /* name of /proc fs node */
unsigned char record_nr; /* Record Nr. for Product ID */
void (*callback)(void *data); /* callback function */
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index ac61cf4..655d525 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -53,29 +53,26 @@ static int appldata_interval_handler(ctl_table *ctl, int write,
static struct ctl_table_header *appldata_sysctl_header;
static struct ctl_table appldata_table[] = {
{
- .ctl_name = CTL_APPLDATA_TIMER,
.procname = "timer",
.mode = S_IRUGO | S_IWUSR,
.proc_handler = &appldata_timer_handler,
},
{
- .ctl_name = CTL_APPLDATA_INTERVAL,
.procname = "interval",
.mode = S_IRUGO | S_IWUSR,
.proc_handler = &appldata_interval_handler,
},
- { .ctl_name = 0 }
+ { },
};
static struct ctl_table appldata_dir_table[] = {
{
- .ctl_name = CTL_APPLDATA,
.procname = appldata_proc_name,
.maxlen = 0,
.mode = S_IRUGO | S_IXUGO,
.child = appldata_table,
},
- { .ctl_name = 0 }
+ { },
};
/*
@@ -441,75 +438,38 @@ out:
*/
int appldata_register_ops(struct appldata_ops *ops)
{
- struct list_head *lh;
- struct appldata_ops *tmp_ops;
- int i;
-
- i = 0;
+ if ((ops->size > APPLDATA_MAX_REC_SIZE) || (ops->size < 0))
+ return -EINVAL;
- if ((ops->size > APPLDATA_MAX_REC_SIZE) ||
- (ops->size < 0)){
- P_ERROR("Invalid size of %s record = %i, maximum = %i!\n",
- ops->name, ops->size, APPLDATA_MAX_REC_SIZE);
- return -ENOMEM;
- }
- if ((ops->ctl_nr == CTL_APPLDATA) ||
- (ops->ctl_nr == CTL_APPLDATA_TIMER) ||
- (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) {
- P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr);
- return -EBUSY;
- }
- ops->ctl_table = kzalloc(4*sizeof(struct ctl_table), GFP_KERNEL);
- if (ops->ctl_table == NULL) {
- P_ERROR("Not enough memory for %s ctl_table!\n", ops->name);
+ ops->ctl_table = kzalloc(4 * sizeof(struct ctl_table), GFP_KERNEL);
+ if (!ops->ctl_table)
return -ENOMEM;
- }
spin_lock(&appldata_ops_lock);
- list_for_each(lh, &appldata_ops_list) {
- tmp_ops = list_entry(lh, struct appldata_ops, list);
- P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n",
- ++i, tmp_ops->name, tmp_ops->ctl_nr);
- P_DEBUG("Comparing %s (ctl %i) with %s (ctl %i)\n",
- tmp_ops->name, tmp_ops->ctl_nr, ops->name,
- ops->ctl_nr);
- if (strncmp(tmp_ops->name, ops->name,
- APPLDATA_PROC_NAME_LENGTH) == 0) {
- P_ERROR("Name \"%s\" already registered!\n", ops->name);
- kfree(ops->ctl_table);
- spin_unlock(&appldata_ops_lock);
- return -EBUSY;
- }
- if (tmp_ops->ctl_nr == ops->ctl_nr) {
- P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
- kfree(ops->ctl_table);
- spin_unlock(&appldata_ops_lock);
- return -EBUSY;
- }
- }
list_add(&ops->list, &appldata_ops_list);
spin_unlock(&appldata_ops_lock);
- ops->ctl_table[0].ctl_name = CTL_APPLDATA;
ops->ctl_table[0].procname = appldata_proc_name;
ops->ctl_table[0].maxlen = 0;
ops->ctl_table[0].mode = S_IRUGO | S_IXUGO;
ops->ctl_table[0].child = &ops->ctl_table[2];
- ops->ctl_table[1].ctl_name = 0;
-
- ops->ctl_table[2].ctl_name = ops->ctl_nr;
ops->ctl_table[2].procname = ops->name;
ops->ctl_table[2].mode = S_IRUGO | S_IWUSR;
ops->ctl_table[2].proc_handler = appldata_generic_handler;
ops->ctl_table[2].data = ops;
- ops->ctl_table[3].ctl_name = 0;
-
ops->sysctl_header = register_sysctl_table(ops->ctl_table);
-
+ if (!ops->sysctl_header)
+ goto out;
P_INFO("%s-ops registered!\n", ops->name);
return 0;
+out:
+ spin_lock(&appldata_ops_lock);
+ list_del(&ops->list);
+ spin_unlock(&appldata_ops_lock);
+ kfree(ops->ctl_table);
+ return -ENOMEM;
}
/*
@@ -519,15 +479,11 @@ int appldata_register_ops(struct appldata_ops *ops)
*/
void appldata_unregister_ops(struct appldata_ops *ops)
{
- void *table;
spin_lock(&appldata_ops_lock);
list_del(&ops->list);
- /* at that point any incoming access will fail */
- table = ops->ctl_table;
- ops->ctl_table = NULL;
spin_unlock(&appldata_ops_lock);
unregister_sysctl_table(ops->sysctl_header);
- kfree(table);
+ kfree(ops->ctl_table);
P_INFO("%s-ops unregistered!\n", ops->name);
}
/********************** module-ops management <END> **************************/
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index 697eb30..51181cc 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -147,7 +147,6 @@ static void appldata_get_mem_data(void *data)
static struct appldata_ops ops = {
- .ctl_nr = CTL_APPLDATA_MEM,
.name = "mem",
.record_nr = APPLDATA_RECORD_MEM_ID,
.size = sizeof(struct appldata_mem_data),
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
index 6c1815a..4d83443 100644
--- a/arch/s390/appldata/appldata_net_sum.c
+++ b/arch/s390/appldata/appldata_net_sum.c
@@ -142,7 +142,6 @@ static void appldata_get_net_sum_data(void *data)
static struct appldata_ops ops = {
- .ctl_nr = CTL_APPLDATA_NET_SUM,
.name = "net_sum",
.record_nr = APPLDATA_RECORD_NET_SUM_ID,
.size = sizeof(struct appldata_net_sum_data),
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
index 76a1552..6b3eafe 100644
--- a/arch/s390/appldata/appldata_os.c
+++ b/arch/s390/appldata/appldata_os.c
@@ -82,7 +82,6 @@ struct appldata_os_data {
static struct appldata_os_data *appldata_os_data;
static struct appldata_ops ops = {
- .ctl_nr = CTL_APPLDATA_OS,
.name = "os",
.record_nr = APPLDATA_RECORD_OS_ID,
.owner = THIS_MODULE,
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 8bf4ae1..1b3af7d 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -200,7 +200,7 @@ static noinline __init void find_memory_chunks(unsigned long memsize)
cc = __tprot(addr);
while (cc == old_cc) {
addr += CHUNK_INCR;
- if (addr >= memsize)
+ if (memsize && addr >= memsize)
break;
#ifndef CONFIG_64BIT
if (addr == ADDR2G)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 139ca15..b2b2edc 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -69,13 +69,31 @@ STACK_SIZE = 1 << STACK_SHIFT
basr %r14,%r1
.endm
- .macro LOCKDEP_SYS_EXIT
- l %r1,BASED(.Llockdep_sys_exit)
+ .macro TRACE_IRQS_CHECK
+ tm SP_PSW(%r15),0x03 # irqs enabled?
+ jz 0f
+ l %r1,BASED(.Ltrace_irq_on)
basr %r14,%r1
+ j 1f
+0: l %r1,BASED(.Ltrace_irq_off)
+ basr %r14,%r1
+1:
.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
+#define TRACE_IRQS_CHECK
+#endif
+
+#ifdef CONFIG_LOCKDEP
+ .macro LOCKDEP_SYS_EXIT
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ jz 0f
+ l %r1,BASED(.Llockdep_sys_exit)
+ basr %r14,%r1
+0:
+ .endm
+#else
#define LOCKDEP_SYS_EXIT
#endif
@@ -234,8 +252,6 @@ sysc_saveall:
lh %r7,0x8a # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
sysc_vtime:
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
- bz BASED(sysc_do_svc)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
sysc_stime:
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -263,19 +279,34 @@ sysc_do_restart:
sysc_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
- bno BASED(sysc_leave)
+ bno BASED(sysc_restore)
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
+sysc_restore:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ la %r1,BASED(sysc_restore_trace_psw)
+ lpsw 0(%r1)
+sysc_restore_trace:
+ TRACE_IRQS_CHECK
LOCKDEP_SYS_EXIT
+#endif
sysc_leave:
RESTORE_ALL __LC_RETURN_PSW,1
+sysc_done:
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+ .align 8
+ .globl sysc_restore_trace_psw
+sysc_restore_trace_psw:
+ .long 0, sysc_restore_trace + 0x80000000
+#endif
#
# recheck if there is more work to do
#
sysc_work_loop:
tm __TI_flags+3(%r9),_TIF_WORK_SVC
- bz BASED(sysc_leave) # there is no work to do
+ bz BASED(sysc_restore) # there is no work to do
#
# One of the work bits is on. Find out which one.
#
@@ -290,8 +321,8 @@ sysc_work:
bo BASED(sysc_restart)
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
bo BASED(sysc_singlestep)
- LOCKDEP_SYS_EXIT
- b BASED(sysc_leave)
+ b BASED(sysc_restore)
+sysc_work_done:
#
# _TIF_NEED_RESCHED is set, call schedule
@@ -458,6 +489,7 @@ pgm_check_handler:
pgm_no_vtime:
#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ TRACE_IRQS_OFF
l %r3,__LC_PGM_ILC # load program interruption code
la %r8,0x7f
nr %r8,%r3
@@ -497,6 +529,7 @@ pgm_per_std:
pgm_no_vtime2:
#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ TRACE_IRQS_OFF
l %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
@@ -517,15 +550,13 @@ pgm_svcper:
SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
- bz BASED(pgm_no_vtime3)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
-pgm_no_vtime3:
#endif
lh %r7,0x8a # get svc number from lowcore
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ TRACE_IRQS_OFF
l %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
@@ -542,7 +573,7 @@ kernel_per:
mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
- la %r14,BASED(sysc_leave) # load adr. of system return
+ la %r14,BASED(sysc_restore)# load adr. of system return
br %r1 # branch to do_single_step
/*
@@ -569,26 +600,38 @@ io_no_vtime:
l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
la %r2,SP_PTREGS(%r15) # address of register-save area
basr %r14,%r1 # branch to standard irq handler
- TRACE_IRQS_ON
-
io_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifdef CONFIG_PREEMPT
bno BASED(io_preempt) # no -> check for preemptive scheduling
#else
- bno BASED(io_leave) # no-> skip resched & signal
+ bno BASED(io_restore) # no-> skip resched & signal
#endif
tm __TI_flags+3(%r9),_TIF_WORK_INT
bnz BASED(io_work) # there is work to do (signals etc.)
+io_restore:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ la %r1,BASED(io_restore_trace_psw)
+ lpsw 0(%r1)
+io_restore_trace:
+ TRACE_IRQS_CHECK
LOCKDEP_SYS_EXIT
+#endif
io_leave:
RESTORE_ALL __LC_RETURN_PSW,0
io_done:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ .align 8
+ .globl io_restore_trace_psw
+io_restore_trace_psw:
+ .long 0, io_restore_trace + 0x80000000
+#endif
+
#ifdef CONFIG_PREEMPT
io_preempt:
icm %r0,15,__TI_precount(%r9)
- bnz BASED(io_leave)
+ bnz BASED(io_restore)
l %r1,SP_R15(%r15)
s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
@@ -596,14 +639,10 @@ io_preempt:
lr %r15,%r1
io_resume_loop:
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
- bno BASED(io_leave)
- mvc __TI_precount(4,%r9),BASED(.Lc_pactive)
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- l %r1,BASED(.Lschedule)
- basr %r14,%r1 # call schedule
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
- xc __TI_precount(4,%r9),__TI_precount(%r9)
- b BASED(io_resume_loop)
+ bno BASED(io_restore)
+ l %r1,BASED(.Lpreempt_schedule_irq)
+ la %r14,BASED(io_resume_loop)
+ br %r1 # call schedule
#endif
#
@@ -627,40 +666,42 @@ io_work_loop:
bo BASED(io_reschedule)
tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
bnz BASED(io_sigpending)
- LOCKDEP_SYS_EXIT
- b BASED(io_leave)
+ b BASED(io_restore)
+io_work_done:
#
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
- TRACE_IRQS_OFF
l %r1,BASED(.Ls390_handle_mcck)
basr %r14,%r1 # TIF bit will be cleared by handler
- TRACE_IRQS_ON
b BASED(io_work_loop)
#
# _TIF_NEED_RESCHED is set, call schedule
#
io_reschedule:
+ TRACE_IRQS_ON
l %r1,BASED(.Lschedule)
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
basr %r14,%r1 # call scheduler
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ TRACE_IRQS_OFF
tm __TI_flags+3(%r9),_TIF_WORK_INT
- bz BASED(io_leave) # there is no work to do
+ bz BASED(io_restore) # there is no work to do
b BASED(io_work_loop)
#
# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
io_sigpending:
+ TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ldo_signal)
basr %r14,%r1 # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ TRACE_IRQS_OFF
b BASED(io_work_loop)
/*
@@ -688,7 +729,6 @@ ext_no_vtime:
lh %r3,__LC_EXT_INT_CODE # get interruption code
l %r1,BASED(.Ldo_extint)
basr %r14,%r1
- TRACE_IRQS_ON
b BASED(io_return)
__critical_end:
@@ -853,15 +893,15 @@ cleanup_table_system_call:
cleanup_table_sysc_return:
.long sysc_return + 0x80000000, sysc_leave + 0x80000000
cleanup_table_sysc_leave:
- .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000
+ .long sysc_leave + 0x80000000, sysc_done + 0x80000000
cleanup_table_sysc_work_loop:
- .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000
+ .long sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000
cleanup_table_io_return:
.long io_return + 0x80000000, io_leave + 0x80000000
cleanup_table_io_leave:
.long io_leave + 0x80000000, io_done + 0x80000000
cleanup_table_io_work_loop:
- .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000
+ .long io_work_loop + 0x80000000, io_work_done + 0x80000000
cleanup_critical:
clc 4(4,%r12),BASED(cleanup_table_system_call)
@@ -930,8 +970,6 @@ cleanup_system_call:
cleanup_vtime:
clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
bhe BASED(cleanup_stime)
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
- bz BASED(cleanup_novtime)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
cleanup_stime:
clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16)
@@ -939,7 +977,6 @@ cleanup_stime:
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
cleanup_update:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
-cleanup_novtime:
#endif
mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4)
la %r12,__LC_RETURN_PSW
@@ -978,10 +1015,10 @@ cleanup_sysc_leave:
2: la %r12,__LC_RETURN_PSW
br %r14
cleanup_sysc_leave_insn:
+ .long sysc_done - 4 + 0x80000000
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .long sysc_leave + 14 + 0x80000000
+ .long sysc_done - 8 + 0x80000000
#endif
- .long sysc_leave + 10 + 0x80000000
cleanup_io_return:
mvc __LC_RETURN_PSW(4),0(%r12)
@@ -1008,10 +1045,10 @@ cleanup_io_leave:
2: la %r12,__LC_RETURN_PSW
br %r14
cleanup_io_leave_insn:
+ .long io_done - 4 + 0x80000000
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .long io_leave + 18 + 0x80000000
+ .long io_done - 8 + 0x80000000
#endif
- .long io_leave + 14 + 0x80000000
/*
* Integer constants
@@ -1019,7 +1056,6 @@ cleanup_io_leave_insn:
.align 4
.Lc_spsize: .long SP_SIZE
.Lc_overhead: .long STACK_FRAME_OVERHEAD
-.Lc_pactive: .long PREEMPT_ACTIVE
.Lnr_syscalls: .long NR_syscalls
.L0x018: .short 0x018
.L0x020: .short 0x020
@@ -1043,6 +1079,8 @@ cleanup_io_leave_insn:
.Lexecve_tail: .long execve_tail
.Ljump_table: .long pgm_check_table
.Lschedule: .long schedule
+.Lpreempt_schedule_irq:
+ .long preempt_schedule_irq
.Ltrace: .long syscall_trace
.Lschedtail: .long schedule_tail
.Lsysc_table: .long sys_call_table
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 05e26d1..a3e47b8 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -67,12 +67,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
brasl %r14,trace_hardirqs_off
.endm
- .macro LOCKDEP_SYS_EXIT
- brasl %r14,lockdep_sys_exit
+ .macro TRACE_IRQS_CHECK
+ tm SP_PSW(%r15),0x03 # irqs enabled?
+ jz 0f
+ brasl %r14,trace_hardirqs_on
+ j 1f
+0: brasl %r14,trace_hardirqs_off
+1:
.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
+#define TRACE_IRQS_CHECK
+#endif
+
+#ifdef CONFIG_LOCKDEP
+ .macro LOCKDEP_SYS_EXIT
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ jz 0f
+ brasl %r14,lockdep_sys_exit
+0:
+ .endm
+#else
#define LOCKDEP_SYS_EXIT
#endif
@@ -222,8 +238,6 @@ sysc_saveall:
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
sysc_vtime:
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
- jz sysc_do_svc
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
sysc_stime:
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -257,19 +271,34 @@ sysc_noemu:
sysc_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
- jno sysc_leave
+ jno sysc_restore
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.)
+sysc_restore:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ larl %r1,sysc_restore_trace_psw
+ lpswe 0(%r1)
+sysc_restore_trace:
+ TRACE_IRQS_CHECK
LOCKDEP_SYS_EXIT
+#endif
sysc_leave:
RESTORE_ALL __LC_RETURN_PSW,1
+sysc_done:
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+ .align 8
+ .globl sysc_restore_trace_psw
+sysc_restore_trace_psw:
+ .quad 0, sysc_restore_trace
+#endif
#
# recheck if there is more work to do
#
sysc_work_loop:
tm __TI_flags+7(%r9),_TIF_WORK_SVC
- jz sysc_leave # there is no work to do
+ jz sysc_restore # there is no work to do
#
# One of the work bits is on. Find out which one.
#
@@ -284,8 +313,8 @@ sysc_work:
jo sysc_restart
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
jo sysc_singlestep
- LOCKDEP_SYS_EXIT
- j sysc_leave
+ j sysc_restore
+sysc_work_done:
#
# _TIF_NEED_RESCHED is set, call schedule
@@ -445,6 +474,7 @@ pgm_check_handler:
pgm_no_vtime:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ TRACE_IRQS_OFF
lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
ngr %r8,%r3
@@ -484,6 +514,7 @@ pgm_per_std:
pgm_no_vtime2:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ TRACE_IRQS_OFF
lg %r1,__TI_task(%r9)
tm SP_PSW+1(%r15),0x01 # kernel per event ?
jz kernel_per
@@ -504,12 +535,9 @@ pgm_svcper:
SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
- jz pgm_no_vtime3
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
-pgm_no_vtime3:
#endif
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
@@ -529,7 +557,7 @@ kernel_per:
lhi %r0,__LC_PGM_OLD_PSW
sth %r0,SP_TRAP(%r15) # set trap indication to pgm check
la %r2,SP_PTREGS(%r15) # address of register-save area
- larl %r14,sysc_leave # load adr. of system ret, no work
+ larl %r14,sysc_restore # load adr. of system ret, no work
jg do_single_step # branch to do_single_step
/*
@@ -554,26 +582,38 @@ io_no_vtime:
TRACE_IRQS_OFF
la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_IRQ # call standard irq handler
- TRACE_IRQS_ON
-
io_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifdef CONFIG_PREEMPT
jno io_preempt # no -> check for preemptive scheduling
#else
- jno io_leave # no-> skip resched & signal
+ jno io_restore # no-> skip resched & signal
#endif
tm __TI_flags+7(%r9),_TIF_WORK_INT
jnz io_work # there is work to do (signals etc.)
+io_restore:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ larl %r1,io_restore_trace_psw
+ lpswe 0(%r1)
+io_restore_trace:
+ TRACE_IRQS_CHECK
LOCKDEP_SYS_EXIT
+#endif
io_leave:
RESTORE_ALL __LC_RETURN_PSW,0
io_done:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ .align 8
+ .globl io_restore_trace_psw
+io_restore_trace_psw:
+ .quad 0, io_restore_trace
+#endif
+
#ifdef CONFIG_PREEMPT
io_preempt:
icm %r0,15,__TI_precount(%r9)
- jnz io_leave
+ jnz io_restore
# switch to kernel stack
lg %r1,SP_R15(%r15)
aghi %r1,-SP_SIZE
@@ -582,14 +622,9 @@ io_preempt:
lgr %r15,%r1
io_resume_loop:
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
- jno io_leave
- larl %r1,.Lc_pactive
- mvc __TI_precount(4,%r9),0(%r1)
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- brasl %r14,schedule # call schedule
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
- xc __TI_precount(4,%r9),__TI_precount(%r9)
- j io_resume_loop
+ jno io_restore
+ larl %r14,io_resume_loop
+ jg preempt_schedule_irq
#endif
#
@@ -613,37 +648,39 @@ io_work_loop:
jo io_reschedule
tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
jnz io_sigpending
- LOCKDEP_SYS_EXIT
- j io_leave
+ j io_restore
+io_work_done:
#
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
- TRACE_IRQS_OFF
brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler
- TRACE_IRQS_ON
j io_work_loop
#
# _TIF_NEED_RESCHED is set, call schedule
#
io_reschedule:
+ TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
brasl %r14,schedule # call scheduler
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ TRACE_IRQS_OFF
tm __TI_flags+7(%r9),_TIF_WORK_INT
- jz io_leave # there is no work to do
+ jz io_restore # there is no work to do
j io_work_loop
#
# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
io_sigpending:
+ TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
brasl %r14,do_signal # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ TRACE_IRQS_OFF
j io_work_loop
/*
@@ -669,7 +706,6 @@ ext_no_vtime:
la %r2,SP_PTREGS(%r15) # address of register-save area
llgh %r3,__LC_EXT_INT_CODE # get interruption code
brasl %r14,do_extint
- TRACE_IRQS_ON
j io_return
__critical_end:
@@ -824,15 +860,15 @@ cleanup_table_system_call:
cleanup_table_sysc_return:
.quad sysc_return, sysc_leave
cleanup_table_sysc_leave:
- .quad sysc_leave, sysc_work_loop
+ .quad sysc_leave, sysc_done
cleanup_table_sysc_work_loop:
- .quad sysc_work_loop, sysc_reschedule
+ .quad sysc_work_loop, sysc_work_done
cleanup_table_io_return:
.quad io_return, io_leave
cleanup_table_io_leave:
.quad io_leave, io_done
cleanup_table_io_work_loop:
- .quad io_work_loop, io_mcck_pending
+ .quad io_work_loop, io_work_done
cleanup_critical:
clc 8(8,%r12),BASED(cleanup_table_system_call)
@@ -901,8 +937,6 @@ cleanup_system_call:
cleanup_vtime:
clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
jhe cleanup_stime
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
- jz cleanup_novtime
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
cleanup_stime:
clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32)
@@ -910,7 +944,6 @@ cleanup_stime:
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
cleanup_update:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
-cleanup_novtime:
#endif
mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8)
la %r12,__LC_RETURN_PSW
@@ -949,10 +982,10 @@ cleanup_sysc_leave:
2: la %r12,__LC_RETURN_PSW
br %r14
cleanup_sysc_leave_insn:
+ .quad sysc_done - 4
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .quad sysc_leave + 16
+ .quad sysc_done - 8
#endif
- .quad sysc_leave + 12
cleanup_io_return:
mvc __LC_RETURN_PSW(8),0(%r12)
@@ -979,17 +1012,16 @@ cleanup_io_leave:
2: la %r12,__LC_RETURN_PSW
br %r14
cleanup_io_leave_insn:
+ .quad io_done - 4
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .quad io_leave + 20
+ .quad io_done - 8
#endif
- .quad io_leave + 16
/*
* Integer constants
*/
.align 4
.Lconst:
-.Lc_pactive: .long PREEMPT_ACTIVE
.Lnr_syscalls: .long NR_syscalls
.L0x0130: .short 0x130
.L0x0140: .short 0x140
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 7e1bfb9..50f8f1e 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -347,7 +347,7 @@ void (*_machine_power_off)(void) = do_machine_power_off_nonsmp;
void machine_restart(char *command)
{
- if (!in_interrupt() || oops_in_progress)
+ if ((!in_interrupt() && !in_atomic()) || oops_in_progress)
/*
* Only unblank the console if we are called in enabled
* context or a bust_spinlocks cleared the way for us.
@@ -492,6 +492,10 @@ static void setup_addressing_mode(void)
printk("S390 address spaces switched, ");
set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY);
}
+#ifdef CONFIG_TRACE_IRQFLAGS
+ sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+ io_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+#endif
}
static void __init
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b05ae85..264ea90 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -193,72 +193,30 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
}
EXPORT_SYMBOL(smp_call_function_single);
-static void do_send_stop(void)
+void smp_send_stop(void)
{
int cpu, rc;
- /* stop all processors */
- for_each_online_cpu(cpu) {
- if (cpu == smp_processor_id())
- continue;
- do {
- rc = signal_processor(cpu, sigp_stop);
- } while (rc == sigp_busy);
- }
-}
+ /* Disable all interrupts/machine checks */
+ __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
-static void do_store_status(void)
-{
- int cpu, rc;
+ /* write magic number to zero page (absolute 0) */
+ lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
- /* store status of all processors in their lowcores (real 0) */
+ /* stop all processors */
for_each_online_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
do {
- rc = signal_processor_p(
- (__u32)(unsigned long) lowcore_ptr[cpu], cpu,
- sigp_store_status_at_address);
+ rc = signal_processor(cpu, sigp_stop);
} while (rc == sigp_busy);
- }
-}
-static void do_wait_for_stop(void)
-{
- int cpu;
-
- /* Wait for all other cpus to enter stopped state */
- for_each_online_cpu(cpu) {
- if (cpu == smp_processor_id())
- continue;
while (!smp_cpu_not_running(cpu))
cpu_relax();
}
}
/*
- * this function sends a 'stop' sigp to all other CPUs in the system.
- * it goes straight through.
- */
-void smp_send_stop(void)
-{
- /* Disable all interrupts/machine checks */
- __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
-
- /* write magic number to zero page (absolute 0) */
- lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
-
- /* stop other processors. */
- do_send_stop();
-
- /* wait until other processors are stopped */
- do_wait_for_stop();
-
- /* store status of other processors. */
- do_store_status();
-}
-
-/*
* Reboot, halt and power_off routines for SMP.
*/
void machine_restart_smp(char *__unused)
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 8ec9def..8ed16a8 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -260,6 +260,7 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(1);
printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
print_modules();
+ notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
show_regs(regs);
bust_spinlocks(0);
add_taint(TAINT_DIE);
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index d4ed93d..413c240 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -341,19 +341,16 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
static struct ctl_table cmm_table[] = {
{
- .ctl_name = VM_CMM_PAGES,
.procname = "cmm_pages",
.mode = 0644,
.proc_handler = &cmm_pages_handler,
},
{
- .ctl_name = VM_CMM_TIMED_PAGES,
.procname = "cmm_timed_pages",
.mode = 0644,
.proc_handler = &cmm_pages_handler,
},
{
- .ctl_name = VM_CMM_TIMEOUT,
.procname = "cmm_timeout",
.mode = 0644,
.proc_handler = &cmm_timeout_handler,
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 838f7ac..6db3108 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -483,7 +483,7 @@ static DECLARE_WORK(css_reprobe_work, reprobe_all);
void css_schedule_reprobe(void)
{
need_reprobe = 1;
- queue_work(ccw_device_work, &css_reprobe_work);
+ queue_work(slow_path_wq, &css_reprobe_work);
}
EXPORT_SYMBOL_GPL(css_schedule_reprobe);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 8867443..bfad421 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -1034,7 +1034,7 @@ device_trigger_reprobe(struct subchannel *sch)
if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_move_to_orphanage);
- queue_work(ccw_device_work, &cdev->private->kick_work);
+ queue_work(slow_path_wq, &cdev->private->kick_work);
} else
ccw_device_start_id(cdev, 0);
}
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index f232832..2f6bf46 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -113,19 +113,10 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
{
struct subchannel *sch;
struct ccw1 *ccw;
- int ret;
sch = to_subchannel(cdev->dev.parent);
/* Setup sense channel program. */
ccw = cdev->private->iccws;
- if (sch->schib.pmcw.pim != 0x80) {
- /* more than one path installed. */
- ccw->cmd_code = CCW_CMD_SUSPEND_RECONN;
- ccw->cda = 0;
- ccw->count = 0;
- ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC;
- ccw++;
- }
ccw->cmd_code = CCW_CMD_SENSE_ID;
ccw->cda = (__u32) __pa (&cdev->private->senseid);
ccw->count = sizeof (struct senseid);
@@ -133,25 +124,9 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
/* Reset device status. */
memset(&cdev->private->irb, 0, sizeof(struct irb));
+ cdev->private->flags.intretry = 0;
- /* Try on every path. */
- ret = -ENODEV;
- while (cdev->private->imask != 0) {
- if ((sch->opm & cdev->private->imask) != 0 &&
- cdev->private->iretry > 0) {
- cdev->private->iretry--;
- /* Reset internal retry indication. */
- cdev->private->flags.intretry = 0;
- ret = cio_start (sch, cdev->private->iccws,
- cdev->private->imask);
- /* ret is 0, -EBUSY, -EACCES or -ENODEV */
- if (ret != -EACCES)
- return ret;
- }
- cdev->private->imask >>= 1;
- cdev->private->iretry = 5;
- }
- return ret;
+ return cio_start(sch, ccw, LPM_ANYPATH);
}
void
@@ -161,8 +136,7 @@ ccw_device_sense_id_start(struct ccw_device *cdev)
memset (&cdev->private->senseid, 0, sizeof (struct senseid));
cdev->private->senseid.cu_type = 0xFFFF;
- cdev->private->imask = 0x80;
- cdev->private->iretry = 5;
+ cdev->private->iretry = 3;
ret = __ccw_device_sense_id_start(cdev);
if (ret && ret != -EBUSY)
ccw_device_sense_id_done(cdev, ret);
@@ -278,14 +252,13 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
ccw_device_sense_id_done(cdev, ret);
break;
case -EACCES: /* channel is not operational. */
- sch->lpm &= ~cdev->private->imask;
- cdev->private->imask >>= 1;
- cdev->private->iretry = 5;
- /* fall through. */
case -EAGAIN: /* try again. */
- ret = __ccw_device_sense_id_start(cdev);
- if (ret == 0 || ret == -EBUSY)
- break;
+ cdev->private->iretry--;
+ if (cdev->private->iretry > 0) {
+ ret = __ccw_device_sense_id_start(cdev);
+ if (ret == 0 || ret == -EBUSY)
+ break;
+ }
/* fall through. */
default: /* Sense ID failed. Try asking VM. */
if (MACHINE_IS_VM) {
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index d866d33..44bda78 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -388,6 +388,11 @@ extern void (*_machine_power_off)(void);
#define arch_align_stack(x) (x)
+#ifdef CONFIG_TRACE_IRQFLAGS
+extern psw_t sysc_restore_trace_psw;
+extern psw_t io_restore_trace_psw;
+#endif
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index e99171f..4f5047d 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -70,7 +70,6 @@ enum
CTL_ABI=9, /* Binary emulation */
CTL_CPU=10, /* CPU stuff (speed scaling, etc) */
CTL_ARLAN=254, /* arlan wireless driver */
- CTL_APPLDATA=2120, /* s390 appldata */
CTL_S390DBF=5677, /* s390 debug */
CTL_SUNRPC=7249, /* sunrpc debug */
CTL_PM=9899, /* frv power management */
@@ -207,11 +206,6 @@ enum
VM_PANIC_ON_OOM=33, /* panic at out-of-memory */
VM_VDSO_ENABLED=34, /* map VDSO into new processes? */
VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */
-
- /* s390 vm cmm sysctls */
- VM_CMM_PAGES=1111,
- VM_CMM_TIMED_PAGES=1112,
- VM_CMM_TIMEOUT=1113,
};
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index 4abc6d2..8f5baac 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -140,9 +140,6 @@ static struct trans_ctl_table trans_vm_table[] = {
{ VM_PANIC_ON_OOM, "panic_on_oom" },
{ VM_VDSO_ENABLED, "vdso_enabled" },
{ VM_MIN_SLAB, "min_slab_ratio" },
- { VM_CMM_PAGES, "cmm_pages" },
- { VM_CMM_TIMED_PAGES, "cmm_timed_pages" },
- { VM_CMM_TIMEOUT, "cmm_timeout" },
{}
};
@@ -1219,16 +1216,6 @@ static struct trans_ctl_table trans_arlan_table[] = {
{}
};
-static struct trans_ctl_table trans_appldata_table[] = {
- { CTL_APPLDATA_TIMER, "timer" },
- { CTL_APPLDATA_INTERVAL, "interval" },
- { CTL_APPLDATA_OS, "os" },
- { CTL_APPLDATA_NET_SUM, "net_sum" },
- { CTL_APPLDATA_MEM, "mem" },
- {}
-
-};
-
static struct trans_ctl_table trans_s390dbf_table[] = {
{ 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" },
{ 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" },
@@ -1273,7 +1260,6 @@ static struct trans_ctl_table trans_root_table[] = {
{ CTL_ABI, "abi" },
/* CTL_CPU not used */
{ CTL_ARLAN, "arlan", trans_arlan_table },
- { CTL_APPLDATA, "appldata", trans_appldata_table },
{ CTL_S390DBF, "s390dbf", trans_s390dbf_table },
{ CTL_SUNRPC, "sunrpc", trans_sunrpc_table },
{ CTL_PM, "pm", trans_pm_table },
diff --git a/mm/rmap.c b/mm/rmap.c
index dc3be5f..dbc2ca2 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -471,11 +471,12 @@ int page_mkclean(struct page *page)
if (page_mapped(page)) {
struct address_space *mapping = page_mapping(page);
- if (mapping)
+ if (mapping) {
ret = page_mkclean_file(mapping, page);
- if (page_test_dirty(page)) {
- page_clear_dirty(page);
- ret = 1;
+ if (page_test_dirty(page)) {
+ page_clear_dirty(page);
+ ret = 1;
+ }
}
}
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index a2f5a6e..7698f6c 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -97,7 +97,7 @@ struct iucv_irq_list {
struct iucv_irq_data data;
};
-static struct iucv_irq_data *iucv_irq_data;
+static struct iucv_irq_data *iucv_irq_data[NR_CPUS];
static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE;
static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE;
@@ -277,7 +277,7 @@ union iucv_param {
/*
* Anchor for per-cpu IUCV command parameter block.
*/
-static union iucv_param *iucv_param;
+static union iucv_param *iucv_param[NR_CPUS];
/**
* iucv_call_b2f0
@@ -356,7 +356,7 @@ static void iucv_allow_cpu(void *data)
* 0x10 - Flag to allow priority message completion interrupts
* 0x08 - Flag to allow IUCV control interrupts
*/
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[cpu];
memset(parm, 0, sizeof(union iucv_param));
parm->set_mask.ipmask = 0xf8;
iucv_call_b2f0(IUCV_SETMASK, parm);
@@ -377,7 +377,7 @@ static void iucv_block_cpu(void *data)
union iucv_param *parm;
/* Disable all iucv interrupts. */
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[cpu];
memset(parm, 0, sizeof(union iucv_param));
iucv_call_b2f0(IUCV_SETMASK, parm);
@@ -401,9 +401,9 @@ static void iucv_declare_cpu(void *data)
return;
/* Declare interrupt buffer. */
- parm = percpu_ptr(iucv_param, cpu);
+ parm = iucv_param[cpu];
memset(parm, 0, sizeof(union iucv_param));
- parm->db.ipbfadr1 = virt_to_phys(percpu_ptr(iucv_irq_data, cpu));
+ parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
if (rc) {
char *err = "Unknown";
@@ -458,7 +458,7 @@ static void iucv_retrieve_cpu(void *data)
iucv_block_cpu(NULL);
/* Retrieve interrupt buffer. */
- parm = percpu_ptr(iucv_param, cpu);
+ parm = iucv_param[cpu];
iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
/* Clear indication that an iucv buffer exists for this cpu. */
@@ -558,22 +558,23 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
switch (action) {
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
- if (!percpu_populate(iucv_irq_data,
- sizeof(struct iucv_irq_data),
- GFP_KERNEL|GFP_DMA, cpu))
+ iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
+ GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+ if (!iucv_irq_data[cpu])
return NOTIFY_BAD;
- if (!percpu_populate(iucv_param, sizeof(union iucv_param),
- GFP_KERNEL|GFP_DMA, cpu)) {
- percpu_depopulate(iucv_irq_data, cpu);
+ iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
+ GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+ if (!iucv_param[cpu])
return NOTIFY_BAD;
- }
break;
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- percpu_depopulate(iucv_param, cpu);
- percpu_depopulate(iucv_irq_data, cpu);
+ kfree(iucv_param[cpu]);
+ iucv_param[cpu] = NULL;
+ kfree(iucv_irq_data[cpu]);
+ iucv_irq_data[cpu] = NULL;
break;
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
@@ -612,7 +613,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16])
{
union iucv_param *parm;
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
@@ -755,7 +756,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
local_bh_disable();
/* Prepare parameter block. */
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->ctrl.ippathid = path->pathid;
parm->ctrl.ipmsglim = path->msglim;
@@ -799,7 +800,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
BUG_ON(in_atomic());
spin_lock_bh(&iucv_table_lock);
iucv_cleanup_queue();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->ctrl.ipmsglim = path->msglim;
parm->ctrl.ipflags1 = path->flags;
@@ -854,7 +855,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
@@ -881,7 +882,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16])
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
@@ -936,7 +937,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->purge.ippathid = path->pathid;
parm->purge.ipmsgid = msg->id;
@@ -1003,7 +1004,7 @@ int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
}
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->db.ipbfadr1 = (u32)(addr_t) buffer;
parm->db.ipbfln1f = (u32) size;
@@ -1040,7 +1041,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
parm->db.ippathid = path->pathid;
parm->db.ipmsgid = msg->id;
@@ -1074,7 +1075,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (flags & IUCV_IPRMDATA) {
parm->dpl.ippathid = path->pathid;
@@ -1118,7 +1119,7 @@ int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (flags & IUCV_IPRMDATA) {
/* Message of 8 bytes can be placed into the parameter list. */
@@ -1172,7 +1173,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
int rc;
local_bh_disable();
- parm = percpu_ptr(iucv_param, smp_processor_id());
+ parm = iucv_param[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (flags & IUCV_IPRMDATA) {
parm->dpl.ippathid = path->pathid;
@@ -1559,7 +1560,7 @@ static void iucv_external_interrupt(u16 code)
struct iucv_irq_data *p;
struct iucv_irq_list *work;
- p = percpu_ptr(iucv_irq_data, smp_processor_id());
+ p = iucv_irq_data[smp_processor_id()];
if (p->ippathid >= iucv_max_pathid) {
printk(KERN_WARNING "iucv_do_int: Got interrupt with "
"pathid %d > max_connections (%ld)\n",
@@ -1598,6 +1599,7 @@ static void iucv_external_interrupt(u16 code)
static int __init iucv_init(void)
{
int rc;
+ int cpu;
if (!MACHINE_IS_VM) {
rc = -EPROTONOSUPPORT;
@@ -1617,19 +1619,23 @@ static int __init iucv_init(void)
rc = PTR_ERR(iucv_root);
goto out_bus;
}
- /* Note: GFP_DMA used to get memory below 2G */
- iucv_irq_data = percpu_alloc(sizeof(struct iucv_irq_data),
- GFP_KERNEL|GFP_DMA);
- if (!iucv_irq_data) {
- rc = -ENOMEM;
- goto out_root;
- }
- /* Allocate parameter blocks. */
- iucv_param = percpu_alloc(sizeof(union iucv_param),
- GFP_KERNEL|GFP_DMA);
- if (!iucv_param) {
- rc = -ENOMEM;
- goto out_extint;
+
+ for_each_online_cpu(cpu) {
+ /* Note: GFP_DMA used to get memory below 2G */
+ iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
+ GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+ if (!iucv_irq_data[cpu]) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+
+ /* Allocate parameter blocks. */
+ iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
+ GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+ if (!iucv_param[cpu]) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
}
register_hotcpu_notifier(&iucv_cpu_notifier);
ASCEBC(iucv_error_no_listener, 16);
@@ -1638,9 +1644,13 @@ static int __init iucv_init(void)
iucv_available = 1;
return 0;
-out_extint:
- percpu_free(iucv_irq_data);
-out_root:
+out_free:
+ for_each_possible_cpu(cpu) {
+ kfree(iucv_param[cpu]);
+ iucv_param[cpu] = NULL;
+ kfree(iucv_irq_data[cpu]);
+ iucv_irq_data[cpu] = NULL;
+ }
s390_root_dev_unregister(iucv_root);
out_bus:
bus_unregister(&iucv_bus);
@@ -1658,6 +1668,7 @@ out:
static void __exit iucv_exit(void)
{
struct iucv_irq_list *p, *n;
+ int cpu;
spin_lock_irq(&iucv_queue_lock);
list_for_each_entry_safe(p, n, &iucv_task_queue, list)
@@ -1666,8 +1677,12 @@ static void __exit iucv_exit(void)
kfree(p);
spin_unlock_irq(&iucv_queue_lock);
unregister_hotcpu_notifier(&iucv_cpu_notifier);
- percpu_free(iucv_param);
- percpu_free(iucv_irq_data);
+ for_each_possible_cpu(cpu) {
+ kfree(iucv_param[cpu]);
+ iucv_param[cpu] = NULL;
+ kfree(iucv_irq_data[cpu]);
+ iucv_irq_data[cpu] = NULL;
+ }
s390_root_dev_unregister(iucv_root);
bus_unregister(&iucv_bus);
unregister_external_interrupt(0x4000, iucv_external_interrupt);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2007-12-17 15:42 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2007-12-17 15:42 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
include/asm-s390/pgtable.h | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
Martin Schwidefsky (1):
[S390] pud_present/pmd_present bug.
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index f2cc25b..1f530f8 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -453,12 +453,12 @@ static inline int pgd_bad(pgd_t pgd) { return 0; }
static inline int pud_present(pud_t pud)
{
- return pud_val(pud) & _REGION_ENTRY_ORIGIN;
+ return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL;
}
static inline int pud_none(pud_t pud)
{
- return pud_val(pud) & _REGION_ENTRY_INV;
+ return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL;
}
static inline int pud_bad(pud_t pud)
@@ -471,12 +471,12 @@ static inline int pud_bad(pud_t pud)
static inline int pmd_present(pmd_t pmd)
{
- return pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
+ return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL;
}
static inline int pmd_none(pmd_t pmd)
{
- return pmd_val(pmd) & _SEGMENT_ENTRY_INV;
+ return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL;
}
static inline int pmd_bad(pmd_t pmd)
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-01-26 13:23 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-01-26 13:23 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
Documentation/DocBook/s390-drivers.tmpl | 1 +
Documentation/cpu-hotplug.txt | 2 +-
Documentation/kernel-parameters.txt | 9 +-
Documentation/s390/CommonIO | 5 +
arch/s390/Kconfig | 3 -
arch/s390/crypto/Kconfig | 60 --
arch/s390/crypto/aes_s390.c | 2 +-
arch/s390/crypto/prng.c | 4 +-
arch/s390/kernel/Makefile | 4 -
arch/s390/kernel/early.c | 2 +-
arch/s390/kernel/head64.S | 2 +-
arch/s390/kernel/ipl.c | 948 +++++++++++------
arch/s390/kernel/process.c | 18 +-
arch/s390/kernel/ptrace.c | 15 +-
arch/s390/kernel/setup.c | 139 +--
arch/s390/kernel/signal.c | 20 +-
arch/s390/kernel/smp.c | 575 ++++++++---
arch/s390/kernel/traps.c | 20 +-
arch/s390/kernel/vmlinux.lds.S | 12 +-
arch/s390/lib/spinlock.c | 35 +-
arch/s390/mm/extmem.c | 2 +-
arch/s390/mm/vmem.c | 26 +-
drivers/crypto/Kconfig | 63 ++-
drivers/s390/block/Makefile | 4 +-
drivers/s390/block/dasd.c | 1690 +++++++++++++++++--------------
drivers/s390/block/dasd_3370_erp.c | 84 --
drivers/s390/block/dasd_3990_erp.c | 360 +++-----
drivers/s390/block/dasd_9336_erp.c | 41 -
drivers/s390/block/dasd_9343_erp.c | 21 -
drivers/s390/block/dasd_alias.c | 903 +++++++++++++++++
drivers/s390/block/dasd_devmap.c | 94 +-
drivers/s390/block/dasd_diag.c | 107 ++-
drivers/s390/block/dasd_eckd.c | 789 +++++++++++----
drivers/s390/block/dasd_eckd.h | 125 +++-
drivers/s390/block/dasd_eer.c | 11 +-
drivers/s390/block/dasd_erp.c | 25 +-
drivers/s390/block/dasd_fba.c | 119 ++-
drivers/s390/block/dasd_genhd.c | 76 +-
drivers/s390/block/dasd_int.h | 209 +++--
drivers/s390/block/dasd_ioctl.c | 172 ++--
drivers/s390/block/dasd_proc.c | 23 +-
drivers/s390/block/dcssblk.c | 2 +-
drivers/s390/char/Makefile | 2 +-
drivers/s390/char/monwriter.c | 2 +-
drivers/s390/char/raw3270.c | 4 +-
drivers/s390/char/sclp.h | 4 +-
drivers/s390/char/sclp_chp.c | 200 ----
drivers/s390/char/sclp_cmd.c | 398 ++++++++
drivers/s390/char/sclp_cpi.c | 246 +-----
drivers/s390/char/sclp_cpi_sys.c | 400 ++++++++
drivers/s390/char/sclp_cpi_sys.h | 15 +
drivers/s390/char/sclp_info.c | 116 ---
drivers/s390/char/sclp_rw.c | 2 +-
drivers/s390/char/tape_3590.c | 2 +-
drivers/s390/char/tape_core.c | 2 +-
drivers/s390/char/tape_proc.c | 2 +-
drivers/s390/char/vmlogrdr.c | 2 +-
drivers/s390/char/vmur.c | 2 +-
drivers/s390/char/zcore.c | 2 +-
drivers/s390/cio/airq.c | 171 +++-
drivers/s390/cio/airq.h | 10 -
drivers/s390/cio/blacklist.c | 2 +-
drivers/s390/cio/ccwgroup.c | 25 +-
drivers/s390/cio/chsc.c | 121 +--
drivers/s390/cio/cio.c | 106 ++-
drivers/s390/cio/cio.h | 89 +-
drivers/s390/cio/cio_debug.h | 22 +-
drivers/s390/cio/css.c | 198 +++-
drivers/s390/cio/css.h | 78 +--
drivers/s390/cio/device.c | 157 +++-
drivers/s390/cio/device.h | 5 +-
drivers/s390/cio/device_fsm.c | 124 ++-
drivers/s390/cio/device_id.c | 9 +-
drivers/s390/cio/device_ops.c | 2 +-
drivers/s390/cio/device_pgid.c | 6 +-
drivers/s390/cio/device_status.c | 13 +-
drivers/s390/cio/io_sch.h | 163 +++
drivers/s390/cio/ioasm.h | 66 --
drivers/s390/cio/qdio.c | 38 +-
drivers/s390/cio/qdio.h | 2 +-
drivers/s390/net/claw.c | 2 +-
drivers/s390/net/lcs.c | 2 +-
drivers/s390/net/netiucv.c | 3 +-
drivers/s390/net/qeth_proc.c | 4 +-
drivers/s390/net/smsgiucv.c | 2 +-
drivers/s390/scsi/zfcp_erp.c | 2 +-
drivers/s390/scsi/zfcp_fsf.c | 10 +-
drivers/s390/scsi/zfcp_qdio.c | 2 +-
include/asm-s390/airq.h | 19 +
include/asm-s390/cio.h | 4 +-
include/asm-s390/dasd.h | 2 +-
include/asm-s390/ipl.h | 8 +-
include/asm-s390/mmu_context.h | 27 +-
include/asm-s390/pgtable.h | 46 +-
include/asm-s390/processor.h | 4 -
include/asm-s390/ptrace.h | 8 +
include/asm-s390/qdio.h | 2 +-
include/asm-s390/rwsem.h | 4 +-
include/asm-s390/sclp.h | 20 +-
include/asm-s390/smp.h | 5 +-
include/asm-s390/spinlock.h | 32 +-
include/asm-s390/spinlock_types.h | 1 -
include/asm-s390/tlbflush.h | 32 +-
include/asm-s390/zcrypt.h | 2 +-
kernel/sysctl_check.c | 1 -
105 files changed, 6216 insertions(+), 3658 deletions(-)
delete mode 100644 arch/s390/crypto/Kconfig
delete mode 100644 drivers/s390/block/dasd_3370_erp.c
delete mode 100644 drivers/s390/block/dasd_9336_erp.c
delete mode 100644 drivers/s390/block/dasd_9343_erp.c
create mode 100644 drivers/s390/block/dasd_alias.c
delete mode 100644 drivers/s390/char/sclp_chp.c
create mode 100644 drivers/s390/char/sclp_cmd.c
create mode 100644 drivers/s390/char/sclp_cpi_sys.c
create mode 100644 drivers/s390/char/sclp_cpi_sys.h
delete mode 100644 drivers/s390/char/sclp_info.c
delete mode 100644 drivers/s390/cio/airq.h
create mode 100644 drivers/s390/cio/io_sch.h
create mode 100644 include/asm-s390/airq.h
Carsten Otte (1):
[S390] add smp_call_function_mask
Christian Borntraeger (2):
[S390] Change vmalloc defintions
[S390] vmemmap: allocate struct pages before 1:1 mapping
Cornelia Huck (11):
[S390] cio: Use helpers instead of container_of().
[S390] cio: css_driver: Use consistent parameters.
[S390] cio: Reset sch->driver.
[S390] cio: Add css_driver_{register,unregister}.
[S390] cio: Cleanup debug feature usage.
[S390] cio: Introduce subchannel->private.
[S390] cio: I/O subchannel specific fields.
[S390] cio: Use dev_{g,s}et_drvdata().
[S390] cio: Set driver->owner on css, ccw and ccwgroup busses.
[S390] cio: Delete timer in ccw_device_verify_done().
[S390] cio: Fix ungroup vs. machine check race in ccwgroup.
Denis Cheng (1):
[S390] use LIST_HEAD instead of LIST_HEAD_INIT
Heiko Carstens (9):
[S390] Standby cpu activation/deactivation.
[S390] sclp: convert channel path configure code to use sync interface.
[S390] Print kernel version in dump_stack() and show_regs().
[S390] Get rid of HOLES_IN_ZONE requirement.
[S390] Remove owner_pc member from raw_spinlock_t.
[S390] Use new style spinlock initializer in __RWSEM_INITIALIZER.
[S390] Get rid of additional_cpus kernel parameter.
[S390] Remove appldata include from sysctl_check.c
[S390] Allocate and free cpu lowcores and stacks when needed/possible.
Hisashi Hifumi (1):
[S390] do local_irq_restore while spinning in spin_lock_irqsave.
Jan Engelhardt (1):
[S390] constify function pointer tables.
Jan Glauber (1):
[S390] crypto: move s390 Kconfig options.
Joe Perches (5):
[S390] arch/s390: Add missing "space"
[S390] drivers/s390: Add missing "space"
[S390] arch/s390/: Spelling fixes
[S390] include/asm-s390/: Spelling fixes
[S390] drivers/s390/: Spelling fixes
Martin Schwidefsky (5):
[S390] Fix tlb flushing with idte.
[S390] Avoid warnings in tlblush.h
[S390] Move NOTES and BUG_TABLE.
[S390] Unused field / extern declaration in processor.h
[S390] replace lock_cpu_hotplug with get_online_cpus
Michael Ernst (2):
[S390] cio: memory leak in cio processing
[S390] sclp: sysfs interface for SCLP cpi
Michael Holzheu (4):
[S390] kernel: Shutdown Actions Interface
[S390] Load disabled wait psw instead of stopping cpu on halt.
[S390] Initialize sclp_ipl_info
[S390] Use diag308 subcodes 3 and 6 for reboot and dump when possible.
Peter Oberparleiter (3):
[S390] cio: Extend adapter interrupt interface.
[S390] cio: reduce cpu utilization during device scan
[S390] cio: introduce timed recovery procedure
Peter Tiedemann (1):
[S390] usage of s390dbf: shrink number of debug areas to use.
Roland McGrath (1):
[S390] single-step cleanup
Sebastian Ott (3):
[S390] Cleanup in Documentation/kernel-parameters.txt.
[S390] cio: Dump ccw device information in case of timeout.
[S390] qdio: Remove double checked value.
Stefan Haberland (2):
[S390] dasd: fix return value of dasd_generic_probe()
[S390] dasd: fix loop in request expiration handling
Stefan Weinhuber (1):
[S390] dasd: add hyper PAV support to DASD device driver, part 1
Ursula Braun (1):
[S390] qdio: set QDIO_ACTIVATE_TIMEOUT to 5s
WANG Cong (1):
[S390] Remove TOPDIR from Makefile
^ permalink raw reply [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-02-19 14:46 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-02-19 14:46 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/Kconfig | 3 +-
arch/s390/kernel/process.c | 15 ++++++----
arch/s390/kernel/smp.c | 53 +++++++++++++++++++++++++++----------
arch/s390/kernel/time.c | 2 -
arch/s390/lib/uaccess_std.c | 8 +++---
drivers/s390/block/dasd.c | 12 ++++----
drivers/s390/block/dcssblk.c | 2 +-
drivers/s390/char/sclp.c | 12 ++++----
drivers/s390/char/sclp.h | 6 +++-
drivers/s390/char/sclp_config.c | 2 +-
drivers/s390/char/sclp_cpi_sys.c | 2 +-
drivers/s390/char/sclp_rw.c | 4 +-
drivers/s390/char/sclp_vt220.c | 2 +-
drivers/s390/cio/device.c | 15 +++++++++-
drivers/s390/cio/qdio.c | 13 +--------
drivers/s390/cio/qdio.h | 2 +-
include/asm-s390/bitops.h | 20 ++++++++-----
17 files changed, 103 insertions(+), 70 deletions(-)
Cornelia Huck (2):
[S390] cio: Remember to initialize recovery_lock.
[S390] cio: Do timed recovery on workqueue.
Heiko Carstens (6):
[S390] Let NR_CPUS default to 32/64 on s390/s390x.
[S390] Make sure enabled wait psw is loaded in default_idle.
[S390] Initialize per cpu lowcores on cpu hotplug.
[S390] qdio: fix qdio_activate timeout handling.
[S390] etr: fix compile error on !SMP
[S390] Fix futex_atomic_cmpxchg_std inline assembly.
Martin Schwidefsky (1):
[S390] find bit corner case.
Peter Oberparleiter (1):
[S390] sclp: clean up send/receive naming scheme
Roel Kluin (1):
[S390] dcss: Fix Unlikely(x) != y
Stefan Weinhuber (1):
[S390] dasd: fix locking in __dasd_device_process_final_queue
Ursula Braun (1):
[S390] qdio: FCP/SCSI write I/O stagnates on LPAR
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 92a4f7b..b21444b 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -100,7 +100,8 @@ config NR_CPUS
int "Maximum number of CPUs (2-64)"
range 2 64
depends on SMP
- default "32"
+ default "32" if !64BIT
+ default "64" if 64BIT
help
This allows you to specify the maximum number of CPUs which this
kernel will support. The maximum supported value is 64 and the
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index a6a4729..1c59ec1 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -114,24 +114,27 @@ extern void s390_handle_mcck(void);
static void default_idle(void)
{
int cpu, rc;
+ int nr_calls = 0;
+ void *hcpu;
#ifdef CONFIG_SMP
struct s390_idle_data *idle;
#endif
/* CPU is going idle. */
cpu = smp_processor_id();
-
+ hcpu = (void *)(long)cpu;
local_irq_disable();
if (need_resched()) {
local_irq_enable();
return;
}
- rc = atomic_notifier_call_chain(&idle_chain,
- S390_CPU_IDLE, (void *)(long) cpu);
- if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
- BUG();
- if (rc != NOTIFY_OK) {
+ rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
+ &nr_calls);
+ if (rc == NOTIFY_BAD) {
+ nr_calls--;
+ __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+ hcpu, nr_calls, NULL);
local_irq_enable();
return;
}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8506065..818bd09 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -626,13 +626,17 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
if (!lowcore)
return -ENOMEM;
async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
- if (!async_stack)
- goto out_async_stack;
panic_stack = __get_free_page(GFP_KERNEL);
- if (!panic_stack)
- goto out_panic_stack;
-
- *lowcore = S390_lowcore;
+ if (!panic_stack || !async_stack)
+ goto out;
+ /*
+ * Only need to copy the first 512 bytes from address 0. But since
+ * the compiler emits a warning if src == NULL for memcpy use copy_page
+ * instead. Copies more than needed but this code is not performance
+ * critical.
+ */
+ copy_page(lowcore, &S390_lowcore);
+ memset((void *)lowcore + 512, 0, sizeof(*lowcore) - 512);
lowcore->async_stack = async_stack + ASYNC_SIZE;
lowcore->panic_stack = panic_stack + PAGE_SIZE;
@@ -653,9 +657,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
out_save_area:
free_page(panic_stack);
#endif
-out_panic_stack:
+out:
free_pages(async_stack, ASYNC_ORDER);
-out_async_stack:
free_pages((unsigned long) lowcore, lc_order);
return -ENOMEM;
}
@@ -719,8 +722,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
cpu_lowcore->current_task = (unsigned long) idle;
cpu_lowcore->cpu_data.cpu_nr = cpu;
- cpu_lowcore->softirq_pending = 0;
- cpu_lowcore->ext_call_fast = 0;
+ cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
+ cpu_lowcore->ipl_device = S390_lowcore.ipl_device;
eieio();
while (signal_processor(cpu, sigp_restart) == sigp_busy)
@@ -797,23 +800,43 @@ void cpu_die(void)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
+#ifndef CONFIG_64BIT
+ unsigned long save_area = 0;
+#endif
+ unsigned long async_stack, panic_stack;
+ struct _lowcore *lowcore;
unsigned int cpu;
+ int lc_order;
smp_detect_cpus();
/* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201");
- memset(lowcore_ptr, 0, sizeof(lowcore_ptr));
print_cpu_info(&S390_lowcore.cpu_data);
- smp_alloc_lowcore(smp_processor_id());
+ /* Reallocate current lowcore, but keep its contents. */
+ lc_order = sizeof(long) == 8 ? 1 : 0;
+ lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order);
+ panic_stack = __get_free_page(GFP_KERNEL);
+ async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE)
- ctl_set_bit(14, 29); /* enable extended save area */
+ save_area = get_zeroed_page(GFP_KERNEL);
#endif
- set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
-
+ local_irq_disable();
+ local_mcck_disable();
+ lowcore_ptr[smp_processor_id()] = lowcore;
+ *lowcore = S390_lowcore;
+ lowcore->panic_stack = panic_stack + PAGE_SIZE;
+ lowcore->async_stack = async_stack + ASYNC_SIZE;
+#ifndef CONFIG_64BIT
+ if (MACHINE_HAS_IEEE)
+ lowcore->extended_save_area_addr = (u32) save_area;
+#endif
+ set_prefix((u32)(unsigned long) lowcore);
+ local_mcck_enable();
+ local_irq_enable();
for_each_possible_cpu(cpu)
if (cpu != smp_processor_id())
smp_create_idle(cpu);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 3bbac12..76a5dd1 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -744,7 +744,6 @@ static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
}
}
-#ifdef CONFIG_SMP
static void etr_sync_cpu_start(void *dummy)
{
int *in_sync = dummy;
@@ -777,7 +776,6 @@ static void etr_sync_cpu_start(void *dummy)
static void etr_sync_cpu_end(void *dummy)
{
}
-#endif /* CONFIG_SMP */
/*
* Sync the TOD clock using the port refered to by aibp. This port
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index 28c4500..d2ffbad 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -293,10 +293,10 @@ int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
asm volatile(
" sacf 256\n"
- " cs %1,%4,0(%5)\n"
- "0: lr %0,%1\n"
- "1: sacf 0\n"
- EX_TABLE(0b,1b)
+ "0: cs %1,%4,0(%5)\n"
+ "1: lr %0,%1\n"
+ "2: sacf 0\n"
+ EX_TABLE(0b,2b) EX_TABLE(1b,2b)
: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
: "cc", "memory" );
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d984e0f..ccf46c9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1149,12 +1149,14 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
{
struct list_head *l, *n;
struct dasd_ccw_req *cqr;
+ struct dasd_block *block;
list_for_each_safe(l, n, final_queue) {
cqr = list_entry(l, struct dasd_ccw_req, devlist);
list_del_init(&cqr->devlist);
- if (cqr->block)
- spin_lock_bh(&cqr->block->queue_lock);
+ block = cqr->block;
+ if (block)
+ spin_lock_bh(&block->queue_lock);
switch (cqr->status) {
case DASD_CQR_SUCCESS:
cqr->status = DASD_CQR_DONE;
@@ -1172,15 +1174,13 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
cqr, cqr->status);
BUG();
}
- if (cqr->block)
- spin_unlock_bh(&cqr->block->queue_lock);
if (cqr->callback != NULL)
(cqr->callback)(cqr, cqr->callback_data);
+ if (block)
+ spin_unlock_bh(&block->queue_lock);
}
}
-
-
/*
* Take a look at the first request on the ccw queue and check
* if it reached its expire time. If so, terminate the IO.
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 3faf053..e6c94db 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -666,7 +666,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
page_addr = (unsigned long)
page_address(bvec->bv_page) + bvec->bv_offset;
source_addr = dev_info->start + (index<<12) + bytes_done;
- if (unlikely(page_addr & 4095) != 0 || (bvec->bv_len & 4095) != 0)
+ if (unlikely((page_addr & 4095) != 0) || (bvec->bv_len & 4095) != 0)
// More paranoia.
goto fail;
if (bio_data_dir(bio) == READ) {
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 25629b9..2c7a1ee 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -29,10 +29,10 @@ static ext_int_info_t ext_int_info_hwc;
/* Lock to protect internal data consistency. */
static DEFINE_SPINLOCK(sclp_lock);
-/* Mask of events that we can receive from the sclp interface. */
+/* Mask of events that we can send to the sclp interface. */
static sccb_mask_t sclp_receive_mask;
-/* Mask of events that we can send to the sclp interface. */
+/* Mask of events that we can receive from the sclp interface. */
static sccb_mask_t sclp_send_mask;
/* List of registered event listeners and senders. */
@@ -380,7 +380,7 @@ sclp_interrupt_handler(__u16 code)
}
sclp_running_state = sclp_running_state_idle;
}
- if (evbuf_pending && sclp_receive_mask != 0 &&
+ if (evbuf_pending &&
sclp_activation_state == sclp_activation_state_active)
__sclp_queue_read_req();
spin_unlock(&sclp_lock);
@@ -459,8 +459,8 @@ sclp_dispatch_state_change(void)
reg = NULL;
list_for_each(l, &sclp_reg_list) {
reg = list_entry(l, struct sclp_register, list);
- receive_mask = reg->receive_mask & sclp_receive_mask;
- send_mask = reg->send_mask & sclp_send_mask;
+ receive_mask = reg->send_mask & sclp_receive_mask;
+ send_mask = reg->receive_mask & sclp_send_mask;
if (reg->sclp_receive_mask != receive_mask ||
reg->sclp_send_mask != send_mask) {
reg->sclp_receive_mask = receive_mask;
@@ -615,8 +615,8 @@ struct init_sccb {
u16 mask_length;
sccb_mask_t receive_mask;
sccb_mask_t send_mask;
- sccb_mask_t sclp_send_mask;
sccb_mask_t sclp_receive_mask;
+ sccb_mask_t sclp_send_mask;
} __attribute__((packed));
/* Prepare init mask request. Called while sclp_lock is locked. */
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index aa8186d..bac80e8 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -122,11 +122,13 @@ struct sclp_req {
/* of some routines it wants to be called from the low level driver */
struct sclp_register {
struct list_head list;
- /* event masks this user is registered for */
+ /* User wants to receive: */
sccb_mask_t receive_mask;
+ /* User wants to send: */
sccb_mask_t send_mask;
- /* actually present events */
+ /* H/W can receive: */
sccb_mask_t sclp_receive_mask;
+ /* H/W can send: */
sccb_mask_t sclp_send_mask;
/* called if event type availability changes */
void (*state_change_fn)(struct sclp_register *);
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 9dc77f1..b8f35bc 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -64,7 +64,7 @@ static int __init sclp_conf_init(void)
return rc;
}
- if (!(sclp_conf_register.sclp_receive_mask & EVTYP_CONFMGMDATA_MASK)) {
+ if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) {
printk(KERN_WARNING TAG "no configuration management.\n");
sclp_unregister(&sclp_conf_register);
rc = -ENOSYS;
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c
index 4161703..9f37456 100644
--- a/drivers/s390/char/sclp_cpi_sys.c
+++ b/drivers/s390/char/sclp_cpi_sys.c
@@ -129,7 +129,7 @@ static int cpi_req(void)
"to hardware console.\n");
goto out;
}
- if (!(sclp_cpi_event.sclp_send_mask & EVTYP_CTLPROGIDENT_MASK)) {
+ if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) {
printk(KERN_WARNING "cpi: no control program "
"identification support\n");
rc = -EOPNOTSUPP;
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index ad7195d..da09781 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -452,10 +452,10 @@ sclp_emit_buffer(struct sclp_buffer *buffer,
return -EIO;
sccb = buffer->sccb;
- if (sclp_rw_event.sclp_send_mask & EVTYP_MSG_MASK)
+ if (sclp_rw_event.sclp_receive_mask & EVTYP_MSG_MASK)
/* Use normal write message */
sccb->msg_buf.header.type = EVTYP_MSG;
- else if (sclp_rw_event.sclp_send_mask & EVTYP_PMSGCMD_MASK)
+ else if (sclp_rw_event.sclp_receive_mask & EVTYP_PMSGCMD_MASK)
/* Use write priority message */
sccb->msg_buf.header.type = EVTYP_PMSGCMD;
else
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index f47f4a7..92f5272 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -202,7 +202,7 @@ sclp_vt220_callback(struct sclp_req *request, void *data)
static int
__sclp_vt220_emit(struct sclp_vt220_request *request)
{
- if (!(sclp_vt220_register.sclp_send_mask & EVTYP_VT220MSG_MASK)) {
+ if (!(sclp_vt220_register.sclp_receive_mask & EVTYP_VT220MSG_MASK)) {
request->sclp_req.status = SCLP_REQ_FAILED;
return -EIO;
}
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index d35dc3f..fec004f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -32,7 +32,7 @@
#include "io_sch.h"
static struct timer_list recovery_timer;
-static spinlock_t recovery_lock;
+static DEFINE_SPINLOCK(recovery_lock);
static int recovery_phase;
static const unsigned long recovery_delay[] = { 3, 30, 300 };
@@ -1535,7 +1535,7 @@ static int recovery_check(struct device *dev, void *data)
return 0;
}
-static void recovery_func(unsigned long data)
+static void recovery_work_func(struct work_struct *unused)
{
int redo = 0;
@@ -1553,6 +1553,17 @@ static void recovery_func(unsigned long data)
CIO_MSG_EVENT(2, "recovery: end\n");
}
+static DECLARE_WORK(recovery_work, recovery_work_func);
+
+static void recovery_func(unsigned long data)
+{
+ /*
+ * We can't do our recovery in softirq context and it's not
+ * performance critical, so we schedule it.
+ */
+ schedule_work(&recovery_work);
+}
+
void ccw_device_schedule_recovery(void)
{
unsigned long flags;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 097fc09..2b5bfb7 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -32,7 +32,7 @@
#include <linux/module.h>
#include <linux/init.h>
-
+#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
@@ -1215,9 +1215,6 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used)
return 1;
- if (!q->siga_sync && !irq->is_qebsm)
- /* we'll check for more primed buffers in qeth_stop_polling */
- return 0;
if (irq->is_qebsm) {
count = 1;
start_buf = q->first_to_check;
@@ -3332,13 +3329,7 @@ qdio_activate(struct ccw_device *cdev, int flags)
}
}
- wait_event_interruptible_timeout(cdev->private->wait_q,
- ((irq_ptr->state ==
- QDIO_IRQ_STATE_STOPPED) ||
- (irq_ptr->state ==
- QDIO_IRQ_STATE_ERR)),
- QDIO_ACTIVATE_TIMEOUT);
-
+ msleep(QDIO_ACTIVATE_TIMEOUT);
switch (irq_ptr->state) {
case QDIO_IRQ_STATE_STOPPED:
case QDIO_IRQ_STATE_ERR:
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 37870e4..da8a272 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -57,10 +57,10 @@
of the queue to 0 */
#define QDIO_ESTABLISH_TIMEOUT (1*HZ)
-#define QDIO_ACTIVATE_TIMEOUT (5*HZ)
#define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ)
#define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ)
#define QDIO_FORCE_CHECK_TIMEOUT (10*HZ)
+#define QDIO_ACTIVATE_TIMEOUT (5) /* 5 ms */
enum qdio_irq_states {
QDIO_IRQ_STATE_INACTIVE,
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index ab83c84..965394e 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -456,16 +456,18 @@ static inline unsigned long __ffz_word_loop(const unsigned long *addr,
asm volatile(
#ifndef __s390x__
- " ahi %1,31\n"
- " srl %1,5\n"
+ " ahi %1,-1\n"
+ " sra %1,5\n"
+ " jz 1f\n"
"0: c %2,0(%0,%3)\n"
" jne 1f\n"
" la %0,4(%0)\n"
" brct %1,0b\n"
"1:\n"
#else
- " aghi %1,63\n"
- " srlg %1,%1,6\n"
+ " aghi %1,-1\n"
+ " srag %1,%1,6\n"
+ " jz 1f\n"
"0: cg %2,0(%0,%3)\n"
" jne 1f\n"
" la %0,8(%0)\n"
@@ -491,16 +493,18 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr,
asm volatile(
#ifndef __s390x__
- " ahi %1,31\n"
- " srl %1,5\n"
+ " ahi %1,-1\n"
+ " sra %1,5\n"
+ " jz 1f\n"
"0: c %2,0(%0,%3)\n"
" jne 1f\n"
" la %0,4(%0)\n"
" brct %1,0b\n"
"1:\n"
#else
- " aghi %1,63\n"
- " srlg %1,%1,6\n"
+ " aghi %1,-1\n"
+ " srag %1,%1,6\n"
+ " jz 1f\n"
"0: cg %2,0(%0,%3)\n"
" jne 1f\n"
" la %0,8(%0)\n"
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-03-20 16:13 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-03-20 16:13 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/lib/uaccess_pt.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
Heiko Carstens (1):
[S390] futex: let futex_atomic_cmpxchg_pt survive early functional tests.
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 7e8efaa..5efdfe9 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -406,6 +406,8 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
{
int ret;
+ if (!current->mm)
+ return -EFAULT;
spin_lock(¤t->mm->page_table_lock);
uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
if (!uaddr) {
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-04-30 12:06 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-04-30 12:06 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/Kconfig | 8 ++
arch/s390/defconfig | 141 +++++++++++++++++++++---------
arch/s390/kernel/Makefile | 2 -
arch/s390/kernel/early.c | 125 ++++++++++++++++++++++++++-
arch/s390/kernel/head31.S | 61 -------------
arch/s390/kernel/head64.S | 64 +-------------
arch/s390/kernel/process.c | 18 ----
arch/s390/kernel/ptrace.c | 57 +------------
arch/s390/kernel/setup.c | 21 ++---
arch/s390/kernel/smp.c | 31 ++++---
arch/s390/kernel/topology.c | 35 +++++++-
arch/s390/kernel/traps.c | 26 +++++-
arch/s390/kvm/priv.c | 11 +--
arch/s390/lib/Makefile | 2 -
arch/s390/lib/uaccess_mvcos.c | 2 +
arch/s390/math-emu/Makefile | 1 -
arch/s390/mm/Makefile | 2 +-
arch/s390/mm/extmem.c | 8 +-
arch/s390/mm/fault.c | 3 +
arch/s390/mm/hugetlbpage.c | 134 ++++++++++++++++++++++++++++
arch/s390/mm/init.c | 25 +-----
arch/s390/mm/vmem.c | 135 +++++++++++-----------------
drivers/s390/char/sclp_config.c | 17 ++++-
drivers/s390/cio/ccwgroup.c | 7 +-
drivers/s390/cio/cio.c | 9 +-
drivers/s390/cio/cio.h | 3 +-
drivers/s390/cio/cmf.c | 11 ++-
drivers/s390/cio/css.c | 10 ++-
drivers/s390/cio/device.c | 17 +++--
drivers/s390/cio/device_fsm.c | 10 +--
drivers/s390/cio/device_ops.c | 2 +-
drivers/s390/cio/qdio.c | 8 +-
drivers/s390/kvm/kvm_virtio.c | 23 +++---
fs/Kconfig | 3 +-
include/asm-s390/hugetlb.h | 183 +++++++++++++++++++++++++++++++++++++++
include/asm-s390/page.h | 49 +++++------
include/asm-s390/pgtable.h | 21 +++--
include/asm-s390/processor.h | 9 --
include/asm-s390/ptrace.h | 2 -
include/asm-s390/setup.h | 39 ++++++--
include/asm-s390/smp.h | 12 ++-
include/asm-s390/sparsemem.h | 18 ++++
include/asm-s390/sysinfo.h | 5 +
include/asm-s390/system.h | 18 ++++
include/asm-s390/tlbflush.h | 1 +
include/asm-s390/topology.h | 4 +
46 files changed, 892 insertions(+), 501 deletions(-)
create mode 100644 arch/s390/mm/hugetlbpage.c
create mode 100644 include/asm-s390/hugetlb.h
create mode 100644 include/asm-s390/sparsemem.h
Cornelia Huck (2):
[S390] cio: Use strict_strtoul() for attributes.
[S390] cio: Make isc handling more robust.
Gerald Schaefer (1):
[S390] System z large page support.
Heiko Carstens (11):
[S390] Move show_regs to traps.c.
[S390] Add missing ifndef/define to include/asm-s390/sysinfo.h.
[S390] smp: Fix locking order.
[S390] Automatically detect added cpus.
[S390] Add topology_core_siblings to topology.h
[S390] cpu topology: Fix possible deadlock.
[S390] uaccess_mvcos: #ifdef config dependent code.
[S390] Move stfl to system.h and delete duplicated version.
[S390] vmemmap: use clear_table to initialise page tables.
[S390] Convert machine feature detection code to C.
[S390] Convert to SPARSEMEM & SPARSEMEM_VMEMMAP
Martin Schwidefsky (3):
[S390] Remove self ptrace IEEE_IP hack.
[S390] use generic sys_ptrace
[S390] Update default configuration.
Mathieu Desnoyers (1):
[S390] remove -traditional
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8f5f021..29a7940 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -300,6 +300,14 @@ comment "Kernel preemption"
source "kernel/Kconfig.preempt"
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ select SPARSEMEM_VMEMMAP_ENABLE
+ select SPARSEMEM_VMEMMAP
+
+config ARCH_SPARSEMEM_DEFAULT
+ def_bool y
+
source "mm/Kconfig"
comment "I/O subsystem configuration"
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index a72f208..aa341d0 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25-rc4
-# Wed Mar 5 11:22:59 2008
+# Linux kernel version: 2.6.25
+# Wed Apr 30 11:07:45 2008
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -14,10 +14,12 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_BUG=y
CONFIG_NO_IOMEM=y
CONFIG_NO_DMA=y
CONFIG_GENERIC_LOCKBREAK=y
+CONFIG_PGSTE=y
CONFIG_S390=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -43,6 +45,7 @@ CONFIG_LOG_BUF_SHIFT=17
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_NS=y
+# CONFIG_CGROUP_DEVICE is not set
# CONFIG_CPUSETS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
@@ -65,6 +68,7 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -92,6 +96,7 @@ CONFIG_KPROBES=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -121,8 +126,8 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
#
# Base setup
@@ -131,6 +136,10 @@ CONFIG_CLASSIC_RCU=y
#
# Processor type and features
#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_64BIT=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
@@ -161,15 +170,20 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
@@ -205,11 +219,10 @@ CONFIG_HZ_100=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
# CONFIG_SCHED_HRTICK is not set
-CONFIG_NO_IDLE_HZ=y
-CONFIG_NO_IDLE_HZ_INIT=y
CONFIG_S390_HYPFS_FS=y
CONFIG_KEXEC=y
# CONFIG_ZFCPDUMP is not set
+CONFIG_S390_GUEST=y
#
# Networking
@@ -272,8 +285,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
CONFIG_INET6_XFRM_MODE_BEET=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -289,6 +304,7 @@ CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CT_ACCT is not set
# CONFIG_NF_CONNTRACK_MARK is not set
# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
# CONFIG_NF_CT_PROTO_SCTP is not set
# CONFIG_NF_CT_PROTO_UDPLITE is not set
# CONFIG_NF_CONNTRACK_AMANDA is not set
@@ -439,6 +455,7 @@ CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
CONFIG_DASD_DIAG=y
CONFIG_DASD_EER=y
+CONFIG_VIRTIO_BLK=m
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
@@ -533,7 +550,7 @@ CONFIG_NETDEV_10000=y
# S/390 network device drivers
#
CONFIG_LCS=m
-CONFIG_CTC=m
+CONFIG_CTCM=m
# CONFIG_NETIUCV is not set
# CONFIG_SMSGIUCV is not set
# CONFIG_CLAW is not set
@@ -547,10 +564,12 @@ CONFIG_CCWGROUP=y
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_VIRTIO_NET=m
#
# Character devices
#
+CONFIG_DEVKMEM=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -600,6 +619,7 @@ CONFIG_S390_VMUR=m
# Sonics Silicon Backplane
#
# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
#
# File systems
@@ -652,6 +672,7 @@ CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
@@ -678,12 +699,10 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
@@ -731,6 +750,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
@@ -754,6 +774,7 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_FRAME_POINTER is not set
@@ -775,58 +796,88 @@ CONFIG_SAMPLES=y
# CONFIG_SECURITY is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_SEQIV=m
CONFIG_CRYPTO_HASH=m
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
CONFIG_CRYPTO_HMAC=m
# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_XTS is not set
-CONFIG_CRYPTO_CTR=m
-CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CCM=m
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_DES is not set
-CONFIG_CRYPTO_FCRYPT=m
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_CAMELLIA=m
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_FCRYPT=m
# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_HW=y
CONFIG_ZCRYPT=m
# CONFIG_ZCRYPT_MONOLITHIC is not set
# CONFIG_CRYPTO_SHA1_S390 is not set
# CONFIG_CRYPTO_SHA256_S390 is not set
+CONFIG_CRYPTO_SHA512_S390=m
# CONFIG_CRYPTO_DES_S390 is not set
# CONFIG_CRYPTO_AES_S390 is not set
CONFIG_S390_PRNG=m
@@ -835,6 +886,8 @@ CONFIG_S390_PRNG=m
# Library routines
#
CONFIG_BITREVERSE=m
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_ITU_T is not set
@@ -844,3 +897,9 @@ CONFIG_LIBCRC32C=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
CONFIG_PLIST=y
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_RING=y
+CONFIG_VIRTIO_BALLOON=m
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 77051cd..6302f50 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -2,8 +2,6 @@
# Makefile for the linux kernel.
#
-EXTRA_AFLAGS := -traditional
-
#
# Passing null pointers is ok for smp code, since we access the lowcore here.
#
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 68ec408..d0e0968 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -139,15 +139,15 @@ static noinline __init void detect_machine_type(void)
/* Running under z/VM ? */
if (cpuinfo->cpu_id.version == 0xff)
- machine_flags |= 1;
+ machine_flags |= MACHINE_FLAG_VM;
/* Running on a P/390 ? */
if (cpuinfo->cpu_id.machine == 0x7490)
- machine_flags |= 4;
+ machine_flags |= MACHINE_FLAG_P390;
/* Running under KVM ? */
if (cpuinfo->cpu_id.version == 0xfe)
- machine_flags |= 64;
+ machine_flags |= MACHINE_FLAG_KVM;
}
#ifdef CONFIG_64BIT
@@ -268,6 +268,118 @@ static noinline __init void setup_lowcore_early(void)
s390_base_pgm_handler_fn = early_pgm_check_handler;
}
+static noinline __init void setup_hpage(void)
+{
+#ifndef CONFIG_DEBUG_PAGEALLOC
+ unsigned int facilities;
+
+ facilities = stfl();
+ if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29)))
+ return;
+ machine_flags |= MACHINE_FLAG_HPAGE;
+ __ctl_set_bit(0, 23);
+#endif
+}
+
+static __init void detect_mvpg(void)
+{
+#ifndef CONFIG_64BIT
+ int rc;
+
+ asm volatile(
+ " la 0,0\n"
+ " mvpg %2,%2\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (rc) : "0" (-EOPNOTSUPP), "a" (0) : "memory", "cc", "0");
+ if (!rc)
+ machine_flags |= MACHINE_FLAG_MVPG;
+#endif
+}
+
+static __init void detect_ieee(void)
+{
+#ifndef CONFIG_64BIT
+ int rc, tmp;
+
+ asm volatile(
+ " efpc %1,0\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (rc), "=d" (tmp): "0" (-EOPNOTSUPP) : "cc");
+ if (!rc)
+ machine_flags |= MACHINE_FLAG_IEEE;
+#endif
+}
+
+static __init void detect_csp(void)
+{
+#ifndef CONFIG_64BIT
+ int rc;
+
+ asm volatile(
+ " la 0,0\n"
+ " la 1,0\n"
+ " la 2,4\n"
+ " csp 0,2\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc", "0", "1", "2");
+ if (!rc)
+ machine_flags |= MACHINE_FLAG_CSP;
+#endif
+}
+
+static __init void detect_diag9c(void)
+{
+ unsigned int cpu_address;
+ int rc;
+
+ cpu_address = stap();
+ asm volatile(
+ " diag %2,0,0x9c\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc");
+ if (!rc)
+ machine_flags |= MACHINE_FLAG_DIAG9C;
+}
+
+static __init void detect_diag44(void)
+{
+#ifdef CONFIG_64BIT
+ int rc;
+
+ asm volatile(
+ " diag 0,0,0x44\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc");
+ if (!rc)
+ machine_flags |= MACHINE_FLAG_DIAG44;
+#endif
+}
+
+static __init void detect_machine_facilities(void)
+{
+#ifdef CONFIG_64BIT
+ unsigned int facilities;
+
+ facilities = stfl();
+ if (facilities & (1 << 28))
+ machine_flags |= MACHINE_FLAG_IDTE;
+ if (facilities & (1 << 23))
+ machine_flags |= MACHINE_FLAG_PFMF;
+ if (facilities & (1 << 4))
+ machine_flags |= MACHINE_FLAG_MVCOS;
+#endif
+}
+
/*
* Save ipl parameters, clear bss memory, initialize storage keys
* and create a kernel NSS at startup if the SAVESYS= parm is defined
@@ -285,6 +397,13 @@ void __init startup_init(void)
create_kernel_nss();
sort_main_extable();
setup_lowcore_early();
+ detect_mvpg();
+ detect_ieee();
+ detect_csp();
+ detect_diag9c();
+ detect_diag44();
+ detect_machine_facilities();
+ setup_hpage();
sclp_read_info_early();
sclp_facilities_detect();
memsize = sclp_memory_detect();
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index dc364c1..a816e2d 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -57,61 +57,6 @@ startup_continue:
#
l %r14,.Lstartup_init-.LPG1(%r13)
basr %r14,%r14
-
- l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
-#
-# find out if we have an IEEE fpu
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
- efpc %r0,0 # test IEEE extract fpc instruction
- oi 3(%r12),2 # set IEEE fpu flag
-.Lchkfpu:
-
-#
-# find out if we have the CSP instruction
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
- la %r0,0
- lr %r1,%r0
- la %r2,4
- csp %r0,%r2 # Test CSP instruction
- oi 3(%r12),8 # set CSP flag
-.Lchkcsp:
-
-#
-# find out if we have the MVPG instruction
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
- sr %r0,%r0
- la %r1,0
- la %r2,0
- mvpg %r1,%r2 # Test CSP instruction
- oi 3(%r12),16 # set MVPG flag
-.Lchkmvpg:
-
-#
-# find out if we have the IDTE instruction
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
- .long 0xb2b10000 # store facility list
- tm 0xc8,0x08 # check bit for clearing-by-ASCE
- bno .Lchkidte-.LPG1(%r13)
- lhi %r1,2094
- lhi %r2,0
- .long 0xb98e2001
- oi 3(%r12),0x80 # set IDTE flag
-.Lchkidte:
-
-#
-# find out if the diag 0x9c is available
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13)
- stap __LC_CPUID+4 # store cpu address
- lh %r1,__LC_CPUID+4
- diag %r1,0,0x9c # test diag 0x9c
- oi 2(%r12),1 # set diag9c flag
-.Lchkdiag9c:
-
lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space,
# virtual and never return ...
.align 8
@@ -132,13 +77,7 @@ startup_continue:
.long 0 # cr13: home space segment table
.long 0xc0000000 # cr14: machine check handling off
.long 0 # cr15: linkage stack operations
-.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
-.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
-.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
-.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
-.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
.Lmchunk:.long memory_chunk
-.Lmflags:.long machine_flags
.Lbss_bgn: .long __bss_start
.Lbss_end: .long _end
.Lparmaddr: .long PARMAREA
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 79dccd2..1d06961 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -125,73 +125,11 @@ startup_continue:
# and create a kernel NSS if the SAVESYS= parm is defined
#
brasl %r14,startup_init
- # set program check new psw mask
- mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
- larl %r12,machine_flags
-#
-# find out if we have the MVPG instruction
-#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- sgr %r0,%r0
- lghi %r1,0
- lghi %r2,0
- mvpg %r1,%r2 # test MVPG instruction
- oi 7(%r12),16 # set MVPG flag
-0:
-
-#
-# find out if the diag 0x44 works in 64 bit mode
-#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- diag 0,0,0x44 # test diag 0x44
- oi 7(%r12),32 # set diag44 flag
-0:
-
-#
-# find out if we have the IDTE instruction
-#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- .long 0xb2b10000 # store facility list
- tm 0xc8,0x08 # check bit for clearing-by-ASCE
- bno 0f-.LPG1(%r13)
- lhi %r1,2048
- lhi %r2,0
- .long 0xb98e2001
- oi 7(%r12),0x80 # set IDTE flag
-0:
-
-#
-# find out if the diag 0x9c is available
-#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- stap __LC_CPUID+4 # store cpu address
- lh %r1,__LC_CPUID+4
- diag %r1,0,0x9c # test diag 0x9c
- oi 6(%r12),1 # set diag9c flag
-0:
-
-#
-# find out if we have the MVCOS instruction
-#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- .short 0xc800 # mvcos 0(%r0),0(%r0),%r0
- .short 0x0000
- .short 0x0000
-0: tm 0x8f,0x13 # special-operation exception?
- bno 1f-.LPG1(%r13) # if yes, MVCOS is present
- oi 6(%r12),2 # set MVCOS flag
-1:
-
lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
# virtual and never return ...
.align 16
.Lentry:.quad 0x0000000180000000,_stext
-.Lctl: .quad 0x04b50002 # cr0: various things
+.Lctl: .quad 0x04350002 # cr0: various things
.quad 0 # cr1: primary space segment table
.quad .Lduct # cr2: dispatchable unit control table
.quad 0 # cr3: instruction authorization
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index c1aff19..7920861 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -180,24 +180,6 @@ void cpu_idle(void)
}
}
-void show_regs(struct pt_regs *regs)
-{
- print_modules();
- printk("CPU: %d %s %s %.*s\n",
- task_thread_info(current)->cpu, print_tainted(),
- init_utsname()->release,
- (int)strcspn(init_utsname()->version, " "),
- init_utsname()->version);
- printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
- current->comm, current->pid, current,
- (void *) current->thread.ksp);
- show_registers(regs);
- /* Show stack backtrace if pt_regs is from kernel mode */
- if (!(regs->psw.mask & PSW_MASK_PSTATE))
- show_trace(NULL, (unsigned long *) regs->gprs[15]);
- show_last_breaking_event(regs);
-}
-
extern void kernel_thread_starter(void);
asm(
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 58a0642..7f42701 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -607,38 +607,8 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
}
#endif
-#define PT32_IEEE_IP 0x13c
-
-static int
-do_ptrace(struct task_struct *child, long request, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- int ret;
-
- if (request == PTRACE_ATTACH)
- return ptrace_attach(child);
-
- /*
- * Special cases to get/store the ieee instructions pointer.
- */
- if (child == current) {
- if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP)
- return peek_user(child, addr, data);
- if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
- return poke_user(child, addr, data);
-#ifdef CONFIG_COMPAT
- if (request == PTRACE_PEEKUSR &&
- addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
- return peek_user_emu31(child, addr, data);
- if (request == PTRACE_POKEUSR &&
- addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
- return poke_user_emu31(child, addr, data);
-#endif
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- return ret;
-
switch (request) {
case PTRACE_SYSCALL:
/* continue and stop at next (return from) syscall */
@@ -693,31 +663,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
return -EIO;
}
-asmlinkage long
-sys_ptrace(long request, long pid, long addr, long data)
-{
- struct task_struct *child;
- int ret;
-
- lock_kernel();
- if (request == PTRACE_TRACEME) {
- ret = ptrace_traceme();
- goto out;
- }
-
- child = ptrace_get_task_struct(pid);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- goto out;
- }
-
- ret = do_ptrace(child, request, addr, data);
- put_task_struct(child);
-out:
- unlock_kernel();
- return ret;
-}
-
asmlinkage void
syscall_trace(struct pt_regs *regs, int entryexit)
{
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index a9d18aa..2bc70b6 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(uaccess);
unsigned int console_mode = 0;
unsigned int console_devno = -1;
unsigned int console_irq = -1;
-unsigned long machine_flags = 0;
+unsigned long machine_flags;
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
@@ -683,15 +683,6 @@ setup_memory(void)
#endif
}
-static __init unsigned int stfl(void)
-{
- asm volatile(
- " .insn s,0xb2b10000,0(0)\n" /* stfl */
- "0:\n"
- EX_TABLE(0b,0b));
- return S390_lowcore.stfl_fac_list;
-}
-
static int __init __stfle(unsigned long long *list, int doublewords)
{
typedef struct { unsigned long long _[doublewords]; } addrtype;
@@ -758,6 +749,9 @@ static void __init setup_hwcaps(void)
elf_hwcap |= 1UL << 6;
}
+ if (MACHINE_HAS_HPAGE)
+ elf_hwcap |= 1UL << 7;
+
switch (cpuinfo->cpu_id.machine) {
case 0x9672:
#if !defined(CONFIG_64BIT)
@@ -881,8 +875,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
static int show_cpuinfo(struct seq_file *m, void *v)
{
- static const char *hwcap_str[7] = {
- "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
+ static const char *hwcap_str[8] = {
+ "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
+ "edat"
};
struct cpuinfo_S390 *cpuinfo;
unsigned long n = (unsigned long) v - 1;
@@ -897,7 +892,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
num_online_cpus(), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100);
seq_puts(m, "features\t: ");
- for (i = 0; i < 7; i++)
+ for (i = 0; i < 8; i++)
if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
seq_printf(m, "%s ", hwcap_str[i]);
seq_puts(m, "\n");
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 0dfa988..0aeb290 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -505,7 +505,7 @@ out:
return rc;
}
-static int smp_rescan_cpus(void)
+static int __smp_rescan_cpus(void)
{
cpumask_t avail;
@@ -570,7 +570,7 @@ out:
kfree(info);
printk(KERN_INFO "CPUs: %d configured, %d standby\n", c_cpus, s_cpus);
get_online_cpus();
- smp_rescan_cpus();
+ __smp_rescan_cpus();
put_online_cpus();
}
@@ -890,8 +890,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
if (val != 0 && val != 1)
return -EINVAL;
- mutex_lock(&smp_cpu_state_mutex);
get_online_cpus();
+ mutex_lock(&smp_cpu_state_mutex);
rc = -EBUSY;
if (cpu_online(cpu))
goto out;
@@ -919,8 +919,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
break;
}
out:
- put_online_cpus();
mutex_unlock(&smp_cpu_state_mutex);
+ put_online_cpus();
return rc ? rc : count;
}
static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
@@ -1088,17 +1088,17 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t __ref rescan_store(struct sys_device *dev,
- const char *buf, size_t count)
+
+int smp_rescan_cpus(void)
{
cpumask_t newcpus;
int cpu;
int rc;
- mutex_lock(&smp_cpu_state_mutex);
get_online_cpus();
+ mutex_lock(&smp_cpu_state_mutex);
newcpus = cpu_present_map;
- rc = smp_rescan_cpus();
+ rc = __smp_rescan_cpus();
if (rc)
goto out;
cpus_andnot(newcpus, cpu_present_map, newcpus);
@@ -1109,10 +1109,19 @@ static ssize_t __ref rescan_store(struct sys_device *dev,
}
rc = 0;
out:
- put_online_cpus();
mutex_unlock(&smp_cpu_state_mutex);
+ put_online_cpus();
if (!cpus_empty(newcpus))
topology_schedule_update();
+ return rc;
+}
+
+static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ int rc;
+
+ rc = smp_rescan_cpus();
return rc ? rc : count;
}
static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
@@ -1139,16 +1148,16 @@ static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
if (val != 0 && val != 1)
return -EINVAL;
rc = 0;
- mutex_lock(&smp_cpu_state_mutex);
get_online_cpus();
+ mutex_lock(&smp_cpu_state_mutex);
if (cpu_management == val)
goto out;
rc = topology_set_cpu_management(val);
if (!rc)
cpu_management = val;
out:
- put_online_cpus();
mutex_unlock(&smp_cpu_state_mutex);
+ put_online_cpus();
return rc ? rc : count;
}
static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 12b39b3..661a072 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/sched.h>
+#include <linux/kthread.h>
#include <linux/workqueue.h>
#include <linux/cpu.h>
#include <linux/smp.h>
@@ -66,6 +67,8 @@ static struct timer_list topology_timer;
static void set_topology_timer(void);
static DECLARE_WORK(topology_work, topology_work_fn);
+cpumask_t cpu_core_map[NR_CPUS];
+
cpumask_t cpu_coregroup_map(unsigned int cpu)
{
struct core_info *core = &core_info;
@@ -199,6 +202,14 @@ int topology_set_cpu_management(int fc)
return rc;
}
+static void update_cpu_core_map(void)
+{
+ int cpu;
+
+ for_each_present_cpu(cpu)
+ cpu_core_map[cpu] = cpu_coregroup_map(cpu);
+}
+
void arch_update_cpu_topology(void)
{
struct tl_info *info = tl_info;
@@ -206,20 +217,33 @@ void arch_update_cpu_topology(void)
int cpu;
if (!machine_has_topology) {
+ update_cpu_core_map();
topology_update_polarization_simple();
return;
}
stsi(info, 15, 1, 2);
tl_to_cores(info);
+ update_cpu_core_map();
for_each_online_cpu(cpu) {
sysdev = get_cpu_sysdev(cpu);
kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
}
}
-static void topology_work_fn(struct work_struct *work)
+static int topology_kthread(void *data)
{
arch_reinit_sched_domains();
+ return 0;
+}
+
+static void topology_work_fn(struct work_struct *work)
+{
+ /* We can't call arch_reinit_sched_domains() from a multi-threaded
+ * workqueue context since it may deadlock in case of cpu hotplug.
+ * So we have to create a kernel thread in order to call
+ * arch_reinit_sched_domains().
+ */
+ kthread_run(topology_kthread, NULL, "topology_update");
}
void topology_schedule_update(void)
@@ -251,20 +275,23 @@ static int __init init_topology_update(void)
{
int rc;
+ rc = 0;
if (!machine_has_topology) {
topology_update_polarization_simple();
- return 0;
+ goto out;
}
init_timer_deferrable(&topology_timer);
if (machine_has_topology_irq) {
rc = register_external_interrupt(0x2005, topology_interrupt);
if (rc)
- return rc;
+ goto out;
ctl_set_bit(0, 8);
}
else
set_topology_timer();
- return 0;
+out:
+ update_cpu_core_map();
+ return rc;
}
__initcall(init_topology_update);
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 57b607b..4584d81 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -113,7 +113,7 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high)
}
}
-void show_trace(struct task_struct *task, unsigned long *stack)
+static void show_trace(struct task_struct *task, unsigned long *stack)
{
register unsigned long __r15 asm ("15");
unsigned long sp;
@@ -161,14 +161,14 @@ void show_stack(struct task_struct *task, unsigned long *sp)
show_trace(task, sp);
}
-#ifdef CONFIG_64BIT
-void show_last_breaking_event(struct pt_regs *regs)
+static void show_last_breaking_event(struct pt_regs *regs)
{
+#ifdef CONFIG_64BIT
printk("Last Breaking-Event-Address:\n");
printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
-}
#endif
+}
/*
* The architecture-independent dump_stack generator
@@ -223,6 +223,24 @@ void show_registers(struct pt_regs *regs)
show_code(regs);
}
+void show_regs(struct pt_regs *regs)
+{
+ print_modules();
+ printk("CPU: %d %s %s %.*s\n",
+ task_thread_info(current)->cpu, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+ printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+ current->comm, current->pid, current,
+ (void *) current->thread.ksp);
+ show_registers(regs);
+ /* Show stack backtrace if pt_regs is from kernel mode */
+ if (!(regs->psw.mask & PSW_MASK_PSTATE))
+ show_trace(NULL, (unsigned long *) regs->gprs[15]);
+ show_last_breaking_event(regs);
+}
+
/* This is called from fs/proc/array.c */
void task_show_regs(struct seq_file *m, struct task_struct *task)
{
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 1465946..c02286c 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -151,18 +151,9 @@ static int handle_chsc(struct kvm_vcpu *vcpu)
return 0;
}
-static unsigned int kvm_stfl(void)
-{
- asm volatile(
- " .insn s,0xb2b10000,0(0)\n" /* stfl */
- "0:\n"
- EX_TABLE(0b, 0b));
- return S390_lowcore.stfl_fac_list;
-}
-
static int handle_stfl(struct kvm_vcpu *vcpu)
{
- unsigned int facility_list = kvm_stfl();
+ unsigned int facility_list = stfl();
int rc;
vcpu->stat.instruction_stfl++;
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 5208443..ab6735d 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -2,8 +2,6 @@
# Makefile for s390-specific library files..
#
-EXTRA_AFLAGS := -traditional
-
lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 6d87723..3f15aaf 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -162,6 +162,7 @@ static size_t clear_user_mvcos(size_t size, void __user *to)
return size;
}
+#ifdef CONFIG_S390_SWITCH_AMODE
static size_t strnlen_user_mvcos(size_t count, const char __user *src)
{
char buf[256];
@@ -199,6 +200,7 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
} while ((len_str == len) && (done < count));
return done;
}
+#endif /* CONFIG_S390_SWITCH_AMODE */
struct uaccess_ops uaccess_mvcos = {
.copy_from_user = copy_from_user_mvcos_check,
diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile
index 73b3e72..c848903 100644
--- a/arch/s390/math-emu/Makefile
+++ b/arch/s390/math-emu/Makefile
@@ -5,4 +5,3 @@
obj-$(CONFIG_MATHEMU) := math.o
EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
-EXTRA_AFLAGS := -traditional
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 6640193..fb988a4 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -4,4 +4,4 @@
obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o
-
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index ed2af0a..f231f5e 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -287,7 +287,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
if (rc < 0)
goto out_free;
- rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+ rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
if (rc)
goto out_free;
@@ -351,7 +351,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
release_resource(seg->res);
kfree(seg->res);
out_shared:
- remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+ vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
out_free:
kfree(seg);
out:
@@ -474,7 +474,7 @@ segment_modify_shared (char *name, int do_nonshared)
rc = 0;
goto out_unlock;
out_del:
- remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+ vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
list_del(&seg->list);
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
kfree(seg);
@@ -508,7 +508,7 @@ segment_unload(char *name)
goto out_unlock;
release_resource(seg->res);
kfree(seg->res);
- remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+ vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
list_del(&seg->list);
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
kfree(seg);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2650f46..4d53720 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -28,6 +28,7 @@
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
+#include <linux/hugetlb.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
@@ -367,6 +368,8 @@ good_area:
}
survive:
+ if (is_vm_hugetlb_page(vma))
+ address &= HPAGE_MASK;
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
new file mode 100644
index 0000000..f4b6124
--- /dev/null
+++ b/arch/s390/mm/hugetlbpage.c
@@ -0,0 +1,134 @@
+/*
+ * IBM System z Huge TLB Page Support for Kernel.
+ *
+ * Copyright 2007 IBM Corp.
+ * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *pteptr, pte_t pteval)
+{
+ pmd_t *pmdp = (pmd_t *) pteptr;
+ pte_t shadow_pteval = pteval;
+ unsigned long mask;
+
+ if (!MACHINE_HAS_HPAGE) {
+ pteptr = (pte_t *) pte_page(pteval)[1].index;
+ mask = pte_val(pteval) &
+ (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
+ pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
+ if (mm->context.noexec) {
+ pteptr += PTRS_PER_PTE;
+ pte_val(shadow_pteval) =
+ (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
+ }
+ }
+
+ pmd_val(*pmdp) = pte_val(pteval);
+ if (mm->context.noexec) {
+ pmdp = get_shadow_table(pmdp);
+ pmd_val(*pmdp) = pte_val(shadow_pteval);
+ }
+}
+
+int arch_prepare_hugepage(struct page *page)
+{
+ unsigned long addr = page_to_phys(page);
+ pte_t pte;
+ pte_t *ptep;
+ int i;
+
+ if (MACHINE_HAS_HPAGE)
+ return 0;
+
+ ptep = (pte_t *) pte_alloc_one(&init_mm, address);
+ if (!ptep)
+ return -ENOMEM;
+
+ pte = mk_pte(page, PAGE_RW);
+ for (i = 0; i < PTRS_PER_PTE; i++) {
+ set_pte_at(&init_mm, addr + i * PAGE_SIZE, ptep + i, pte);
+ pte_val(pte) += PAGE_SIZE;
+ }
+ page[1].index = (unsigned long) ptep;
+ return 0;
+}
+
+void arch_release_hugepage(struct page *page)
+{
+ pte_t *ptep;
+
+ if (MACHINE_HAS_HPAGE)
+ return;
+
+ ptep = (pte_t *) page[1].index;
+ if (!ptep)
+ return;
+ pte_free(&init_mm, ptep);
+ page[1].index = 0;
+}
+
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgdp;
+ pud_t *pudp;
+ pmd_t *pmdp = NULL;
+
+ pgdp = pgd_offset(mm, addr);
+ pudp = pud_alloc(mm, pgdp, addr);
+ if (pudp)
+ pmdp = pmd_alloc(mm, pudp, addr);
+ return (pte_t *) pmdp;
+}
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgdp;
+ pud_t *pudp;
+ pmd_t *pmdp = NULL;
+
+ pgdp = pgd_offset(mm, addr);
+ if (pgd_present(*pgdp)) {
+ pudp = pud_offset(pgdp, addr);
+ if (pud_present(*pudp))
+ pmdp = pmd_offset(pudp, addr);
+ }
+ return (pte_t *) pmdp;
+}
+
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+ return 0;
+}
+
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+ int write)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+int pmd_huge(pmd_t pmd)
+{
+ if (!MACHINE_HAS_HPAGE)
+ return 0;
+
+ return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
+}
+
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmdp, int write)
+{
+ struct page *page;
+
+ if (!MACHINE_HAS_HPAGE)
+ return NULL;
+
+ page = pmd_page(*pmdp);
+ if (page)
+ page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
+ return page;
+}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 202c952..fa31de6 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -77,28 +77,6 @@ void show_mem(void)
printk("%lu pages pagetables\n", global_page_state(NR_PAGETABLE));
}
-static void __init setup_ro_region(void)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t new_pte;
- unsigned long address, end;
-
- address = ((unsigned long)&_stext) & PAGE_MASK;
- end = PFN_ALIGN((unsigned long)&_eshared);
-
- for (; address < end; address += PAGE_SIZE) {
- pgd = pgd_offset_k(address);
- pud = pud_offset(pgd, address);
- pmd = pmd_offset(pud, address);
- pte = pte_offset_kernel(pmd, address);
- new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
- *pte = new_pte;
- }
-}
-
/*
* paging_init() sets up the page tables
*/
@@ -121,7 +99,6 @@ void __init paging_init(void)
clear_table((unsigned long *) init_mm.pgd, pgd_type,
sizeof(unsigned long)*2048);
vmem_map_init();
- setup_ro_region();
/* enable virtual mapping in kernel mode */
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
@@ -129,6 +106,8 @@ void __init paging_init(void)
__ctl_load(S390_lowcore.kernel_asce, 13, 13);
__raw_local_irq_ssm(ssm_mask);
+ sparse_memory_present_with_active_regions(MAX_NUMNODES);
+ sparse_init();
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
#ifdef CONFIG_ZONE_DMA
max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 35d90a4..beccacf 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -10,10 +10,12 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/list.h>
+#include <linux/hugetlb.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/setup.h>
#include <asm/tlbflush.h>
+#include <asm/sections.h>
static DEFINE_MUTEX(vmem_mutex);
@@ -25,43 +27,6 @@ struct memory_segment {
static LIST_HEAD(mem_segs);
-void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
- unsigned long start_pfn)
-{
- struct page *start, *end;
- struct page *map_start, *map_end;
- int i;
-
- start = pfn_to_page(start_pfn);
- end = start + size;
-
- for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
- unsigned long cstart, cend;
-
- cstart = PFN_DOWN(memory_chunk[i].addr);
- cend = cstart + PFN_DOWN(memory_chunk[i].size);
-
- map_start = mem_map + cstart;
- map_end = mem_map + cend;
-
- if (map_start < start)
- map_start = start;
- if (map_end > end)
- map_end = end;
-
- map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1))
- / sizeof(struct page);
- map_end += ((PFN_ALIGN((unsigned long) map_end)
- - (unsigned long) map_end)
- / sizeof(struct page));
-
- if (map_start < map_end)
- memmap_init_zone((unsigned long)(map_end - map_start),
- nid, zone, page_to_pfn(map_start),
- MEMMAP_EARLY);
- }
-}
-
static void __ref *vmem_alloc_pages(unsigned int order)
{
if (slab_is_available())
@@ -77,8 +42,7 @@ static inline pud_t *vmem_pud_alloc(void)
pud = vmem_alloc_pages(2);
if (!pud)
return NULL;
- pud_val(*pud) = _REGION3_ENTRY_EMPTY;
- memcpy(pud + 1, pud, (PTRS_PER_PUD - 1)*sizeof(pud_t));
+ clear_table((unsigned long *) pud, _REGION3_ENTRY_EMPTY, PAGE_SIZE * 4);
#endif
return pud;
}
@@ -91,7 +55,7 @@ static inline pmd_t *vmem_pmd_alloc(void)
pmd = vmem_alloc_pages(2);
if (!pmd)
return NULL;
- clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4);
+ clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE * 4);
#endif
return pmd;
}
@@ -114,7 +78,7 @@ static pte_t __init_refok *vmem_pte_alloc(void)
/*
* Add a physical memory range to the 1:1 mapping.
*/
-static int vmem_add_range(unsigned long start, unsigned long size)
+static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
{
unsigned long address;
pgd_t *pg_dir;
@@ -141,7 +105,19 @@ static int vmem_add_range(unsigned long start, unsigned long size)
pud_populate_kernel(&init_mm, pu_dir, pm_dir);
}
+ pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
pm_dir = pmd_offset(pu_dir, address);
+
+#ifdef __s390x__
+ if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) &&
+ (address + HPAGE_SIZE <= start + size) &&
+ (address >= HPAGE_SIZE)) {
+ pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
+ pmd_val(*pm_dir) = pte_val(pte);
+ address += HPAGE_SIZE - PAGE_SIZE;
+ continue;
+ }
+#endif
if (pmd_none(*pm_dir)) {
pt_dir = vmem_pte_alloc();
if (!pt_dir)
@@ -150,7 +126,6 @@ static int vmem_add_range(unsigned long start, unsigned long size)
}
pt_dir = pte_offset_kernel(pm_dir, address);
- pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL);
*pt_dir = pte;
}
ret = 0;
@@ -181,6 +156,13 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
pm_dir = pmd_offset(pu_dir, address);
if (pmd_none(*pm_dir))
continue;
+
+ if (pmd_huge(*pm_dir)) {
+ pmd_clear_kernel(pm_dir);
+ address += HPAGE_SIZE - PAGE_SIZE;
+ continue;
+ }
+
pt_dir = pte_offset_kernel(pm_dir, address);
*pt_dir = pte;
}
@@ -190,10 +172,9 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
/*
* Add a backed mem_map array to the virtual mem_map array.
*/
-static int vmem_add_mem_map(unsigned long start, unsigned long size)
+int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
{
unsigned long address, start_addr, end_addr;
- struct page *map_start, *map_end;
pgd_t *pg_dir;
pud_t *pu_dir;
pmd_t *pm_dir;
@@ -201,11 +182,8 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
pte_t pte;
int ret = -ENOMEM;
- map_start = VMEM_MAP + PFN_DOWN(start);
- map_end = VMEM_MAP + PFN_DOWN(start + size);
-
- start_addr = (unsigned long) map_start & PAGE_MASK;
- end_addr = PFN_ALIGN((unsigned long) map_end);
+ start_addr = (unsigned long) start;
+ end_addr = (unsigned long) (start + nr);
for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
pg_dir = pgd_offset_k(address);
@@ -249,16 +227,6 @@ out:
return ret;
}
-static int vmem_add_mem(unsigned long start, unsigned long size)
-{
- int ret;
-
- ret = vmem_add_mem_map(start, size);
- if (ret)
- return ret;
- return vmem_add_range(start, size);
-}
-
/*
* Add memory segment to the segment list if it doesn't overlap with
* an already present segment.
@@ -296,7 +264,7 @@ static void __remove_shared_memory(struct memory_segment *seg)
vmem_remove_range(seg->start, seg->size);
}
-int remove_shared_memory(unsigned long start, unsigned long size)
+int vmem_remove_mapping(unsigned long start, unsigned long size)
{
struct memory_segment *seg;
int ret;
@@ -320,11 +288,9 @@ out:
return ret;
}
-int add_shared_memory(unsigned long start, unsigned long size)
+int vmem_add_mapping(unsigned long start, unsigned long size)
{
struct memory_segment *seg;
- struct page *page;
- unsigned long pfn, num_pfn, end_pfn;
int ret;
mutex_lock(&vmem_mutex);
@@ -339,24 +305,9 @@ int add_shared_memory(unsigned long start, unsigned long size)
if (ret)
goto out_free;
- ret = vmem_add_mem(start, size);
+ ret = vmem_add_mem(start, size, 0);
if (ret)
goto out_remove;
-
- pfn = PFN_DOWN(start);
- num_pfn = PFN_DOWN(size);
- end_pfn = pfn + num_pfn;
-
- page = pfn_to_page(pfn);
- memset(page, 0, num_pfn * sizeof(struct page));
-
- for (; pfn < end_pfn; pfn++) {
- page = pfn_to_page(pfn);
- init_page_count(page);
- reset_page_mapcount(page);
- SetPageReserved(page);
- INIT_LIST_HEAD(&page->lru);
- }
goto out;
out_remove:
@@ -375,14 +326,34 @@ out:
*/
void __init vmem_map_init(void)
{
+ unsigned long ro_start, ro_end;
+ unsigned long start, end;
int i;
INIT_LIST_HEAD(&init_mm.context.crst_list);
INIT_LIST_HEAD(&init_mm.context.pgtable_list);
init_mm.context.noexec = 0;
- NODE_DATA(0)->node_mem_map = VMEM_MAP;
- for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
- vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
+ ro_start = ((unsigned long)&_stext) & PAGE_MASK;
+ ro_end = PFN_ALIGN((unsigned long)&_eshared);
+ for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+ start = memory_chunk[i].addr;
+ end = memory_chunk[i].addr + memory_chunk[i].size;
+ if (start >= ro_end || end <= ro_start)
+ vmem_add_mem(start, end - start, 0);
+ else if (start >= ro_start && end <= ro_end)
+ vmem_add_mem(start, end - start, 1);
+ else if (start >= ro_start) {
+ vmem_add_mem(start, ro_end - start, 1);
+ vmem_add_mem(ro_end, end - ro_end, 0);
+ } else if (end < ro_end) {
+ vmem_add_mem(start, ro_start - start, 0);
+ vmem_add_mem(ro_start, end - ro_start, 1);
+ } else {
+ vmem_add_mem(start, ro_start - start, 0);
+ vmem_add_mem(ro_start, ro_end - ro_start, 1);
+ vmem_add_mem(ro_end, end - ro_end, 0);
+ }
+ }
}
/*
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index b8f35bc..9e784d5 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -10,6 +10,7 @@
#include <linux/cpu.h>
#include <linux/sysdev.h>
#include <linux/workqueue.h>
+#include <asm/smp.h>
#include "sclp.h"
#define TAG "sclp_config: "
@@ -19,9 +20,11 @@ struct conf_mgm_data {
u8 ev_qualifier;
} __attribute__((packed));
+#define EV_QUAL_CPU_CHANGE 1
#define EV_QUAL_CAP_CHANGE 3
static struct work_struct sclp_cpu_capability_work;
+static struct work_struct sclp_cpu_change_work;
static void sclp_cpu_capability_notify(struct work_struct *work)
{
@@ -37,13 +40,24 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
put_online_cpus();
}
+static void sclp_cpu_change_notify(struct work_struct *work)
+{
+ smp_rescan_cpus();
+}
+
static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
{
struct conf_mgm_data *cdata;
cdata = (struct conf_mgm_data *)(evbuf + 1);
- if (cdata->ev_qualifier == EV_QUAL_CAP_CHANGE)
+ switch (cdata->ev_qualifier) {
+ case EV_QUAL_CPU_CHANGE:
+ schedule_work(&sclp_cpu_change_work);
+ break;
+ case EV_QUAL_CAP_CHANGE:
schedule_work(&sclp_cpu_capability_work);
+ break;
+ }
}
static struct sclp_register sclp_conf_register =
@@ -57,6 +71,7 @@ static int __init sclp_conf_init(void)
int rc;
INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify);
+ INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
rc = sclp_register(&sclp_conf_register);
if (rc) {
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index fe1ad17..85b2e51 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -318,7 +318,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
{
struct ccwgroup_device *gdev;
struct ccwgroup_driver *gdrv;
- unsigned int value;
+ unsigned long value;
int ret;
gdev = to_ccwgroupdev(dev);
@@ -329,7 +329,9 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
if (!try_module_get(gdrv->owner))
return -EINVAL;
- value = simple_strtoul(buf, NULL, 0);
+ ret = strict_strtoul(buf, 0, &value);
+ if (ret)
+ goto out;
ret = count;
if (value == 1)
ccwgroup_set_online(gdev);
@@ -337,6 +339,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
ccwgroup_set_offline(gdev);
else
ret = -EINVAL;
+out:
module_put(gdrv->owner);
return ret;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 23ffcc4..08a5781 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch)
/*
* Enable subchannel.
*/
-int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
- u32 intparm)
+int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
{
char dbf_txt[15];
int ccode;
@@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
for (retry = 5, ret = 0; retry > 0; retry--) {
sch->schib.pmcw.ena = 1;
- sch->schib.pmcw.isc = isc;
+ sch->schib.pmcw.isc = sch->isc;
sch->schib.pmcw.intparm = intparm;
ret = cio_modify(sch);
if (ret == -ENODEV)
@@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
else
sch->opm = chp_get_sch_opm(sch);
sch->lpm = sch->schib.pmcw.pam & sch->opm;
+ sch->isc = 3;
CIO_DEBUG(KERN_INFO, 0,
"Detected device %04x on subchannel 0.%x.%04X"
@@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
/*
* We now have to initially ...
- * ... set "interruption subclass"
* ... enable "concurrent sense"
* ... enable "multipath mode" if more than one
* CHPID is available. This is done regardless
* whether multiple paths are available for us.
*/
- sch->schib.pmcw.isc = 3; /* could be smth. else */
sch->schib.pmcw.csense = 1; /* concurrent sense */
sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0)
@@ -812,6 +810,7 @@ cio_probe_console(void)
* enable console I/O-interrupt subclass 7
*/
ctl_set_bit(6, 24);
+ console_subchannel.isc = 7;
console_subchannel.schib.pmcw.isc = 7;
console_subchannel.schib.pmcw.intparm =
(u32)(addr_t)&console_subchannel;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 08f2235..3c75412 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -74,6 +74,7 @@ struct subchannel {
__u8 lpm; /* logical path mask */
__u8 opm; /* operational path mask */
struct schib schib; /* subchannel information block */
+ int isc; /* desired interruption subclass */
struct chsc_ssd_info ssd_info; /* subchannel description */
struct device dev; /* entry in device tree */
struct css_driver *driver;
@@ -85,7 +86,7 @@ struct subchannel {
#define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
-extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32);
+extern int cio_enable_subchannel(struct subchannel *, u32);
extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *);
extern int cio_clear (struct subchannel *);
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index f4c132a..2808b68 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1219,16 +1219,21 @@ static ssize_t cmb_enable_store(struct device *dev,
{
struct ccw_device *cdev;
int ret;
+ unsigned long val;
+
+ ret = strict_strtoul(buf, 16, &val);
+ if (ret)
+ return ret;
cdev = to_ccwdev(dev);
- switch (buf[0]) {
- case '0':
+ switch (val) {
+ case 0:
ret = disable_cmf(cdev);
if (ret)
dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
break;
- case '1':
+ case 1:
ret = enable_cmf(cdev);
if (ret && ret != -EBUSY)
dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c1afab5..595e327 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -705,13 +705,17 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
{
struct channel_subsystem *css = to_css(dev);
int ret;
+ unsigned long val;
+ ret = strict_strtoul(buf, 16, &val);
+ if (ret)
+ return ret;
mutex_lock(&css->mutex);
- switch (buf[0]) {
- case '0':
+ switch (val) {
+ case 0:
ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
break;
- case '1':
+ case 1:
ret = css->cm_enabled ? 0 : chsc_secm(css, 1);
break;
default:
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e0c7adb..abfd601 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -512,8 +512,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct ccw_device *cdev = to_ccwdev(dev);
- int i, force;
- char *tmp;
+ int force, ret;
+ unsigned long i;
if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
return -EAGAIN;
@@ -525,25 +525,30 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
if (!strncmp(buf, "force\n", count)) {
force = 1;
i = 1;
+ ret = 0;
} else {
force = 0;
- i = simple_strtoul(buf, &tmp, 16);
+ ret = strict_strtoul(buf, 16, &i);
}
-
+ if (ret)
+ goto out;
switch (i) {
case 0:
online_store_handle_offline(cdev);
+ ret = count;
break;
case 1:
online_store_handle_online(cdev, force);
+ ret = count;
break;
default:
- count = -EINVAL;
+ ret = -EINVAL;
}
+out:
if (cdev->drv)
module_put(cdev->drv->owner);
atomic_set(&cdev->private->onoff, 0);
- return count;
+ return ret;
}
static ssize_t
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 4b92c84..99403b0 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev)
(cdev->private->state != DEV_STATE_BOXED))
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
- (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */
return ret;
@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev)
sch = to_subchannel(cdev->dev.parent);
if (css_init_done && !get_device(&cdev->dev))
return -ENODEV;
- ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
- (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret != 0) {
/* Couldn't enable the subchannel for i/o. Sick device. */
if (ret == -ENODEV)
@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
- (u32)(addr_t)sch) != 0)
+ if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */
return;
@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch)
*/
sch->lpm = sch->schib.pmcw.pam & sch->opm;
/* Re-set some bits in the pmcw that were lost. */
- sch->schib.pmcw.isc = 3;
sch->schib.pmcw.csense = 1;
sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0)
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index a1718a0..f308ad5 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev)
return -ENOMEM;
}
spin_lock_irqsave(sch->lock, flags);
- ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret)
goto out_unlock;
/*
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 43876e2..445cf36 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -3663,11 +3663,11 @@ qdio_performance_stats_show(struct bus_type *bus, char *buf)
static ssize_t
qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count)
{
- char *tmp;
- int i;
+ unsigned long i;
+ int ret;
- i = simple_strtoul(buf, &tmp, 16);
- if ((i == 0) || (i == 1)) {
+ ret = strict_strtoul(buf, 16, &i);
+ if (!ret && ((i == 0) || (i == 1))) {
if (i == qdio_performance_stats)
return count;
qdio_performance_stats = i;
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index bbef376..47a7e62 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -17,6 +17,7 @@
#include <linux/virtio_config.h>
#include <linux/interrupt.h>
#include <linux/virtio_ring.h>
+#include <linux/pfn.h>
#include <asm/io.h>
#include <asm/kvm_para.h>
#include <asm/kvm_virtio.h>
@@ -180,11 +181,10 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
config = kvm_vq_config(kdev->desc)+index;
- if (add_shared_memory(config->address,
- vring_size(config->num, PAGE_SIZE))) {
- err = -ENOMEM;
+ err = vmem_add_mapping(config->address,
+ vring_size(config->num, PAGE_SIZE));
+ if (err)
goto out;
- }
vq = vring_new_virtqueue(config->num, vdev, (void *) config->address,
kvm_notify, callback);
@@ -202,8 +202,8 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
vq->priv = config;
return vq;
unmap:
- remove_shared_memory(config->address, vring_size(config->num,
- PAGE_SIZE));
+ vmem_remove_mapping(config->address,
+ vring_size(config->num, PAGE_SIZE));
out:
return ERR_PTR(err);
}
@@ -213,8 +213,8 @@ static void kvm_del_vq(struct virtqueue *vq)
struct kvm_vqconfig *config = vq->priv;
vring_del_virtqueue(vq);
- remove_shared_memory(config->address,
- vring_size(config->num, PAGE_SIZE));
+ vmem_remove_mapping(config->address,
+ vring_size(config->num, PAGE_SIZE));
}
/*
@@ -318,12 +318,13 @@ static int __init kvm_devices_init(void)
return rc;
}
- if (add_shared_memory((max_pfn) << PAGE_SHIFT, PAGE_SIZE)) {
+ rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
+ if (rc) {
device_unregister(&kvm_root);
- return -ENOMEM;
+ return rc;
}
- kvm_devices = (void *) (max_pfn << PAGE_SHIFT);
+ kvm_devices = (void *) PFN_PHYS(max_pfn);
ctl_set_bit(0, 9);
register_external_interrupt(0x2603, kvm_extint_handler);
diff --git a/fs/Kconfig b/fs/Kconfig
index 2e43d46..cf12c40 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1005,7 +1005,8 @@ config TMPFS_POSIX_ACL
config HUGETLBFS
bool "HugeTLB file system support"
- depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN
+ depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \
+ (S390 && 64BIT) || BROKEN
help
hugetlbfs is a filesystem backing for HugeTLB pages, based on
ramfs. For architectures that support it, say Y here and read
diff --git a/include/asm-s390/hugetlb.h b/include/asm-s390/hugetlb.h
new file mode 100644
index 0000000..600a776
--- /dev/null
+++ b/include/asm-s390/hugetlb.h
@@ -0,0 +1,183 @@
+/*
+ * IBM System z Huge TLB Page Support for Kernel.
+ *
+ * Copyright IBM Corp. 2008
+ * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_HUGETLB_H
+#define _ASM_S390_HUGETLB_H
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+
+#define is_hugepage_only_range(mm, addr, len) 0
+#define hugetlb_free_pgd_range free_pgd_range
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+
+int arch_prepare_hugepage(struct page *page);
+void arch_release_hugepage(struct page *page);
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+ /*
+ * PROT_NONE needs to be remapped from the pte type to the ste type.
+ * The HW invalid bit is also different for pte and ste. The pte
+ * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE
+ * bit, so we don't have to clear it.
+ */
+ if (pte_val(pte) & _PAGE_INVALID) {
+ if (pte_val(pte) & _PAGE_SWT)
+ pte_val(pte) |= _HPAGE_TYPE_NONE;
+ pte_val(pte) |= _SEGMENT_ENTRY_INV;
+ }
+ /*
+ * Clear SW pte bits SWT and SWX, there are no SW bits in a segment
+ * table entry.
+ */
+ pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX);
+ /*
+ * Also set the change-override bit because we don't need dirty bit
+ * tracking for hugetlbfs pages.
+ */
+ pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
+ return pte;
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_RO;
+ return pte;
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+ return (pte_val(pte) & _SEGMENT_ENTRY_INV) &&
+ !(pte_val(pte) & _SEGMENT_ENTRY_RO);
+}
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ unsigned long mask;
+
+ if (!MACHINE_HAS_HPAGE) {
+ ptep = (pte_t *) (pte_val(pte) & _SEGMENT_ENTRY_ORIGIN);
+ if (ptep) {
+ mask = pte_val(pte) &
+ (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
+ pte = pte_mkhuge(*ptep);
+ pte_val(pte) |= mask;
+ }
+ }
+ return pte;
+}
+
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pte_t pte = huge_ptep_get(ptep);
+
+ pmd_clear((pmd_t *) ptep);
+ return pte;
+}
+
+static inline void __pmd_csp(pmd_t *pmdp)
+{
+ register unsigned long reg2 asm("2") = pmd_val(*pmdp);
+ register unsigned long reg3 asm("3") = pmd_val(*pmdp) |
+ _SEGMENT_ENTRY_INV;
+ register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5;
+
+ asm volatile(
+ " csp %1,%3"
+ : "=m" (*pmdp)
+ : "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc");
+ pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
+}
+
+static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
+{
+ unsigned long sto = (unsigned long) pmdp -
+ pmd_index(address) * sizeof(pmd_t);
+
+ if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INV)) {
+ asm volatile(
+ " .insn rrf,0xb98e0000,%2,%3,0,0"
+ : "=m" (*pmdp)
+ : "m" (*pmdp), "a" (sto),
+ "a" ((address & HPAGE_MASK))
+ );
+ }
+ pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
+}
+
+static inline void huge_ptep_invalidate(struct mm_struct *mm,
+ unsigned long address, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *) ptep;
+
+ if (!MACHINE_HAS_IDTE) {
+ __pmd_csp(pmdp);
+ if (mm->context.noexec) {
+ pmdp = get_shadow_table(pmdp);
+ __pmd_csp(pmdp);
+ }
+ return;
+ }
+
+ __pmd_idte(address, pmdp);
+ if (mm->context.noexec) {
+ pmdp = get_shadow_table(pmdp);
+ __pmd_idte(address, pmdp);
+ }
+ return;
+}
+
+#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
+({ \
+ int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \
+ if (__changed) { \
+ huge_ptep_invalidate((__vma)->vm_mm, __addr, __ptep); \
+ set_huge_pte_at((__vma)->vm_mm, __addr, __ptep, __entry); \
+ } \
+ __changed; \
+})
+
+#define huge_ptep_set_wrprotect(__mm, __addr, __ptep) \
+({ \
+ pte_t __pte = huge_ptep_get(__ptep); \
+ if (pte_write(__pte)) { \
+ if (atomic_read(&(__mm)->mm_users) > 1 || \
+ (__mm) != current->active_mm) \
+ huge_ptep_invalidate(__mm, __addr, __ptep); \
+ set_huge_pte_at(__mm, __addr, __ptep, \
+ huge_pte_wrprotect(__pte)); \
+ } \
+})
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
+{
+ huge_ptep_invalidate(vma->vm_mm, address, ptep);
+}
+
+#endif /* _ASM_S390_HUGETLB_H */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index fe7f92b..f0f4579 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -19,17 +19,34 @@
#define PAGE_DEFAULT_ACC 0
#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4)
+#define HPAGE_SHIFT 20
+#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+#define ARCH_HAS_HUGE_PTE_TYPE
+#define ARCH_HAS_PREPARE_HUGEPAGE
+#define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH
+
#include <asm/setup.h>
#ifndef __ASSEMBLY__
static inline void clear_page(void *page)
{
- register unsigned long reg1 asm ("1") = 0;
- register void *reg2 asm ("2") = page;
- register unsigned long reg3 asm ("3") = 4096;
- asm volatile(
- " mvcl 2,0"
- : "+d" (reg2), "+d" (reg3) : "d" (reg1) : "memory", "cc");
+ if (MACHINE_HAS_PFMF) {
+ asm volatile(
+ " .insn rre,0xb9af0000,%0,%1"
+ : : "d" (0x10000), "a" (page) : "memory", "cc");
+ } else {
+ register unsigned long reg1 asm ("1") = 0;
+ register void *reg2 asm ("2") = page;
+ register unsigned long reg3 asm ("3") = 4096;
+ asm volatile(
+ " mvcl 2,0"
+ : "+d" (reg2), "+d" (reg3) : "d" (reg1)
+ : "memory", "cc");
+ }
}
static inline void copy_page(void *to, void *from)
@@ -108,26 +125,6 @@ page_get_storage_key(unsigned long addr)
return skey;
}
-extern unsigned long max_pfn;
-
-static inline int pfn_valid(unsigned long pfn)
-{
- unsigned long dummy;
- int ccode;
-
- if (pfn >= max_pfn)
- return 0;
-
- asm volatile(
- " lra %0,0(%2)\n"
- " ipm %1\n"
- " srl %1,28\n"
- : "=d" (dummy), "=d" (ccode)
- : "a" (pfn << PAGE_SHIFT)
- : "cc");
- return !ccode;
-}
-
#endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index f8347ce..c7f4f8e 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -129,7 +129,7 @@ extern char empty_zero_page[PAGE_SIZE];
#define VMEM_MAX_PAGES ((VMEM_MAP_END - VMALLOC_END) / sizeof(struct page))
#define VMEM_MAX_PFN min(VMALLOC_START >> PAGE_SHIFT, VMEM_MAX_PAGES)
#define VMEM_MAX_PHYS ((VMEM_MAX_PFN << PAGE_SHIFT) & ~((16 << 20) - 1))
-#define VMEM_MAP ((struct page *) VMALLOC_END)
+#define vmemmap ((struct page *) VMALLOC_END)
/*
* A 31 bit pagetable entry of S390 has following format:
@@ -234,6 +234,15 @@ extern char empty_zero_page[PAGE_SIZE];
#define _PAGE_TYPE_EX_RW 0x002
/*
+ * Only four types for huge pages, using the invalid bit and protection bit
+ * of a segment table entry.
+ */
+#define _HPAGE_TYPE_EMPTY 0x020 /* _SEGMENT_ENTRY_INV */
+#define _HPAGE_TYPE_NONE 0x220
+#define _HPAGE_TYPE_RO 0x200 /* _SEGMENT_ENTRY_RO */
+#define _HPAGE_TYPE_RW 0x000
+
+/*
* PTE type bits are rather complicated. handle_pte_fault uses pte_present,
* pte_none and pte_file to find out the pte type WITHOUT holding the page
* table lock. ptep_clear_flush on the other hand uses ptep_clear_flush to
@@ -325,6 +334,9 @@ extern char empty_zero_page[PAGE_SIZE];
#define _SEGMENT_ENTRY (0)
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
+#define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */
+#define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */
+
#endif /* __s390x__ */
/*
@@ -1063,8 +1075,8 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define kern_addr_valid(addr) (1)
-extern int add_shared_memory(unsigned long start, unsigned long size);
-extern int remove_shared_memory(unsigned long start, unsigned long size);
+extern int vmem_add_mapping(unsigned long start, unsigned long size);
+extern int vmem_remove_mapping(unsigned long start, unsigned long size);
extern int s390_enable_sie(void);
/*
@@ -1072,9 +1084,6 @@ extern int s390_enable_sie(void);
*/
#define pgtable_cache_init() do { } while (0)
-#define __HAVE_ARCH_MEMMAP_INIT
-extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
-
#include <asm-generic/pgtable.h>
#endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 8eaf343..a00f79d 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -172,16 +172,7 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
*/
extern void task_show_regs(struct seq_file *m, struct task_struct *task);
-extern void show_registers(struct pt_regs *regs);
extern void show_code(struct pt_regs *regs);
-extern void show_trace(struct task_struct *task, unsigned long *sp);
-#ifdef CONFIG_64BIT
-extern void show_last_breaking_event(struct pt_regs *regs);
-#else
-static inline void show_last_breaking_event(struct pt_regs *regs)
-{
-}
-#endif
unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) \
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 61f6952..441d7c2 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -463,8 +463,6 @@ struct user_regs_struct
};
#ifdef __KERNEL__
-#define __ARCH_SYS_PTRACE 1
-
/*
* These are defined as per linux/ptrace.h, which see.
*/
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
index aaf4b51..ba69674 100644
--- a/include/asm-s390/setup.h
+++ b/include/asm-s390/setup.h
@@ -59,23 +59,42 @@ extern unsigned int s390_noexec;
*/
extern unsigned long machine_flags;
-#define MACHINE_IS_VM (machine_flags & 1)
-#define MACHINE_IS_P390 (machine_flags & 4)
-#define MACHINE_HAS_MVPG (machine_flags & 16)
-#define MACHINE_IS_KVM (machine_flags & 64)
-#define MACHINE_HAS_IDTE (machine_flags & 128)
-#define MACHINE_HAS_DIAG9C (machine_flags & 256)
+#define MACHINE_FLAG_VM (1UL << 0)
+#define MACHINE_FLAG_IEEE (1UL << 1)
+#define MACHINE_FLAG_P390 (1UL << 2)
+#define MACHINE_FLAG_CSP (1UL << 3)
+#define MACHINE_FLAG_MVPG (1UL << 4)
+#define MACHINE_FLAG_DIAG44 (1UL << 5)
+#define MACHINE_FLAG_IDTE (1UL << 6)
+#define MACHINE_FLAG_DIAG9C (1UL << 7)
+#define MACHINE_FLAG_MVCOS (1UL << 8)
+#define MACHINE_FLAG_KVM (1UL << 9)
+#define MACHINE_FLAG_HPAGE (1UL << 10)
+#define MACHINE_FLAG_PFMF (1UL << 11)
+
+#define MACHINE_IS_VM (machine_flags & MACHINE_FLAG_VM)
+#define MACHINE_IS_KVM (machine_flags & MACHINE_FLAG_KVM)
+#define MACHINE_IS_P390 (machine_flags & MACHINE_FLAG_P390)
+#define MACHINE_HAS_DIAG9C (machine_flags & MACHINE_FLAG_DIAG9C)
#ifndef __s390x__
-#define MACHINE_HAS_IEEE (machine_flags & 2)
-#define MACHINE_HAS_CSP (machine_flags & 8)
+#define MACHINE_HAS_IEEE (machine_flags & MACHINE_FLAG_IEEE)
+#define MACHINE_HAS_CSP (machine_flags & MACHINE_FLAG_CSP)
+#define MACHINE_HAS_IDTE (0)
#define MACHINE_HAS_DIAG44 (1)
+#define MACHINE_HAS_MVPG (machine_flags & MACHINE_FLAG_MVPG)
#define MACHINE_HAS_MVCOS (0)
+#define MACHINE_HAS_HPAGE (0)
+#define MACHINE_HAS_PFMF (0)
#else /* __s390x__ */
#define MACHINE_HAS_IEEE (1)
#define MACHINE_HAS_CSP (1)
-#define MACHINE_HAS_DIAG44 (machine_flags & 32)
-#define MACHINE_HAS_MVCOS (machine_flags & 512)
+#define MACHINE_HAS_IDTE (machine_flags & MACHINE_FLAG_IDTE)
+#define MACHINE_HAS_DIAG44 (machine_flags & MACHINE_FLAG_DIAG44)
+#define MACHINE_HAS_MVPG (1)
+#define MACHINE_HAS_MVCOS (machine_flags & MACHINE_FLAG_MVCOS)
+#define MACHINE_HAS_HPAGE (machine_flags & MACHINE_FLAG_HPAGE)
+#define MACHINE_HAS_PFMF (machine_flags & MACHINE_FLAG_PFMF)
#endif /* __s390x__ */
#define MACHINE_HAS_SCLP (!MACHINE_IS_P390)
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 6f3821a..ae89cf2 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -19,6 +19,7 @@
#include <asm/lowcore.h>
#include <asm/sigp.h>
#include <asm/ptrace.h>
+#include <asm/system.h>
/*
s390 specific smp.c headers
@@ -53,10 +54,7 @@ extern void machine_power_off_smp(void);
static inline __u16 hard_smp_processor_id(void)
{
- __u16 cpu_address;
-
- asm volatile("stap %0" : "=m" (cpu_address));
- return cpu_address;
+ return stap();
}
/*
@@ -108,5 +106,11 @@ static inline void smp_send_stop(void)
#define smp_cpu_not_running(cpu) 1
#endif
+#ifdef CONFIG_HOTPLUG_CPU
+extern int smp_rescan_cpus(void);
+#else
+static inline int smp_rescan_cpus(void) { return 0; }
+#endif
+
extern union save_area *zfcpdump_save_areas[NR_CPUS + 1];
#endif
diff --git a/include/asm-s390/sparsemem.h b/include/asm-s390/sparsemem.h
new file mode 100644
index 0000000..06dfdab
--- /dev/null
+++ b/include/asm-s390/sparsemem.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_S390_SPARSEMEM_H
+#define _ASM_S390_SPARSEMEM_H
+
+#define SECTION_SIZE_BITS 25
+
+#ifdef CONFIG_64BIT
+
+#define MAX_PHYSADDR_BITS 42
+#define MAX_PHYSMEM_BITS 42
+
+#else
+
+#define MAX_PHYSADDR_BITS 31
+#define MAX_PHYSMEM_BITS 31
+
+#endif /* CONFIG_64BIT */
+
+#endif /* _ASM_S390_SPARSEMEM_H */
diff --git a/include/asm-s390/sysinfo.h b/include/asm-s390/sysinfo.h
index abe10ae..79d0134 100644
--- a/include/asm-s390/sysinfo.h
+++ b/include/asm-s390/sysinfo.h
@@ -11,6 +11,9 @@
* Christian Borntraeger <borntraeger@de.ibm.com>
*/
+#ifndef __ASM_S390_SYSINFO_H
+#define __ASM_S390_SYSINFO_H
+
struct sysinfo_1_1_1 {
char reserved_0[32];
char manufacturer[16];
@@ -114,3 +117,5 @@ static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
: "cc", "memory");
return r0;
}
+
+#endif /* __ASM_S390_SYSINFO_H */
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 92098df..c819ae2 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -16,6 +16,7 @@
#include <asm/ptrace.h>
#include <asm/setup.h>
#include <asm/processor.h>
+#include <asm/lowcore.h>
#ifdef __KERNEL__
@@ -422,6 +423,23 @@ extern void smp_ctl_clear_bit(int cr, int bit);
#endif /* CONFIG_SMP */
+static inline unsigned int stfl(void)
+{
+ asm volatile(
+ " .insn s,0xb2b10000,0(0)\n" /* stfl */
+ "0:\n"
+ EX_TABLE(0b,0b));
+ return S390_lowcore.stfl_fac_list;
+}
+
+static inline unsigned short stap(void)
+{
+ unsigned short cpu_address;
+
+ asm volatile("stap %0" : "=m" (cpu_address));
+ return cpu_address;
+}
+
extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 9e57a93..d60394b 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -2,6 +2,7 @@
#define _S390_TLBFLUSH_H
#include <linux/mm.h>
+#include <linux/sched.h>
#include <asm/processor.h>
#include <asm/pgalloc.h>
diff --git a/include/asm-s390/topology.h b/include/asm-s390/topology.h
index 8e97b06..d96c916 100644
--- a/include/asm-s390/topology.h
+++ b/include/asm-s390/topology.h
@@ -7,6 +7,10 @@
cpumask_t cpu_coregroup_map(unsigned int cpu);
+extern cpumask_t cpu_core_map[NR_CPUS];
+
+#define topology_core_siblings(cpu) (cpu_core_map[cpu])
+
int topology_set_cpu_management(int fc);
void topology_schedule_update(void);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-05-30 8:41 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-05-30 8:41 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/Kconfig | 3 ++
arch/s390/appldata/appldata_base.c | 8 ++++++
arch/s390/defconfig | 11 ++++++--
arch/s390/kernel/dis.c | 2 +-
arch/s390/kernel/smp.c | 2 +-
arch/s390/mm/init.c | 49 +++++++++++++++++-------------------
arch/s390/mm/vmem.c | 18 +++++++++---
drivers/s390/block/dasd.c | 28 ++++++++++----------
drivers/s390/char/raw3270.c | 9 +++---
drivers/s390/char/sclp_config.c | 2 +-
drivers/s390/char/sclp_vt220.c | 27 +++++--------------
drivers/s390/char/tape.h | 3 ++
drivers/s390/char/tape_block.c | 4 +-
drivers/s390/char/tape_core.c | 16 +++++------
include/asm-s390/types.h | 6 ++++
15 files changed, 101 insertions(+), 87 deletions(-)
Christian Borntraeger (1):
[S390] s390 types: make dma_addr_t 64 bit capable
Gerald Schaefer (1):
[S390] appldata: prevent cpu hotplug when walking cpu_online_map.
Hans-Joachim Picht (1):
[S390] fix sparsemem related compile error with allnoconfig on s390
Heiko Carstens (3):
[S390] Fix section mismatch warnings.
[S390] showmem: Only walk spanned pages.
[S390] sclp_vt220: fix scheduling while atomic bug.
Martin Schwidefsky (4):
[S390] 3270: fix race with stack local wait_queue_head_t.
[S390] tape: fix race with stack local wait_queue_head_t.
[S390] disassembler: fix idte instruction format.
[S390] Update default configuration.
Michael Holzheu (1):
[S390] tape: Fix race condition in tape block device driver
Stefan Haberland (1):
[S390] dasd: use a generic wait_queue for sleep_on
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 1d03508..93acb3c 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -308,6 +308,9 @@ config ARCH_SPARSEMEM_ENABLE
config ARCH_SPARSEMEM_DEFAULT
def_bool y
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
source "mm/Kconfig"
comment "I/O subsystem configuration"
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 655d525..ad40729 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -130,6 +130,7 @@ static void appldata_work_fn(struct work_struct *work)
P_DEBUG(" -= Work Queue =-\n");
i = 0;
+ get_online_cpus();
spin_lock(&appldata_ops_lock);
list_for_each(lh, &appldata_ops_list) {
ops = list_entry(lh, struct appldata_ops, list);
@@ -140,6 +141,7 @@ static void appldata_work_fn(struct work_struct *work)
}
}
spin_unlock(&appldata_ops_lock);
+ put_online_cpus();
}
/*
@@ -266,12 +268,14 @@ appldata_timer_handler(ctl_table *ctl, int write, struct file *filp,
len = *lenp;
if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
return -EFAULT;
+ get_online_cpus();
spin_lock(&appldata_timer_lock);
if (buf[0] == '1')
__appldata_vtimer_setup(APPLDATA_ADD_TIMER);
else if (buf[0] == '0')
__appldata_vtimer_setup(APPLDATA_DEL_TIMER);
spin_unlock(&appldata_timer_lock);
+ put_online_cpus();
out:
*lenp = len;
*ppos += len;
@@ -314,10 +318,12 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp,
return -EINVAL;
}
+ get_online_cpus();
spin_lock(&appldata_timer_lock);
appldata_interval = interval;
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
spin_unlock(&appldata_timer_lock);
+ put_online_cpus();
P_INFO("Monitoring CPU interval set to %u milliseconds.\n",
interval);
@@ -556,8 +562,10 @@ static int __init appldata_init(void)
return -ENOMEM;
}
+ get_online_cpus();
for_each_online_cpu(i)
appldata_online_cpu(i);
+ put_online_cpus();
/* Register cpu hotplug notifier */
register_hotcpu_notifier(&appldata_nb);
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index aa341d0..c5cdb97 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Wed Apr 30 11:07:45 2008
+# Linux kernel version: 2.6.26-rc4
+# Fri May 30 09:49:33 2008
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -103,6 +103,7 @@ CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
@@ -173,6 +174,7 @@ CONFIG_PREEMPT=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -210,6 +212,7 @@ CONFIG_FORCE_MAX_ZONEORDER=9
CONFIG_PFAULT=y
# CONFIG_SHARED_KERNEL is not set
# CONFIG_CMM is not set
+# CONFIG_PAGE_STATES is not set
CONFIG_VIRT_TIMER=y
CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_APPLDATA_BASE is not set
@@ -620,6 +623,7 @@ CONFIG_S390_VMUR=m
#
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+CONFIG_ACCESSIBILITY=y
#
# File systems
@@ -754,11 +758,12 @@ CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
-CONFIG_HEADERS_CHECK=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_RT_MUTEXES is not set
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index c14a336..d2f270c 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -208,7 +208,7 @@ static const unsigned char formats[][7] = {
[INSTR_RRF_F0FF] = { 0xff, F_16,F_24,F_28,0,0,0 }, /* e.g. madbr */
[INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 },/* e.g. didbr */
[INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 },/* e.g. .insn */
- [INSTR_RRF_R0RR] = { 0xff, R_24,R_28,R_16,0,0,0 }, /* e.g. idte */
+ [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 }, /* e.g. idte */
[INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, /* e.g. fixr */
[INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, /* e.g. cfebr */
[INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, /* e.g. sske */
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1f42289..42b1d12 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -1089,7 +1089,7 @@ out:
#ifdef CONFIG_HOTPLUG_CPU
-int smp_rescan_cpus(void)
+int __ref smp_rescan_cpus(void)
{
cpumask_t newcpus;
int cpu;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 29f3a63..0559864 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -44,37 +44,34 @@ char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
void show_mem(void)
{
- int i, total = 0, reserved = 0;
- int shared = 0, cached = 0;
+ unsigned long i, total = 0, reserved = 0;
+ unsigned long shared = 0, cached = 0;
+ unsigned long flags;
struct page *page;
+ pg_data_t *pgdat;
printk("Mem-info:\n");
show_free_areas();
- i = max_mapnr;
- while (i-- > 0) {
- if (!pfn_valid(i))
- continue;
- page = pfn_to_page(i);
- total++;
- if (PageReserved(page))
- reserved++;
- else if (PageSwapCache(page))
- cached++;
- else if (page_count(page))
- shared += page_count(page) - 1;
+ for_each_online_pgdat(pgdat) {
+ pgdat_resize_lock(pgdat, &flags);
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ if (!pfn_valid(pgdat->node_start_pfn + i))
+ continue;
+ page = pfn_to_page(pgdat->node_start_pfn + i);
+ total++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (page_count(page))
+ shared += page_count(page) - 1;
+ }
+ pgdat_resize_unlock(pgdat, &flags);
}
- printk("%d pages of RAM\n", total);
- printk("%d reserved pages\n", reserved);
- printk("%d pages shared\n", shared);
- printk("%d pages swap cached\n", cached);
-
- printk("%lu pages dirty\n", global_page_state(NR_FILE_DIRTY));
- printk("%lu pages writeback\n", global_page_state(NR_WRITEBACK));
- printk("%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
- printk("%lu pages slab\n",
- global_page_state(NR_SLAB_RECLAIMABLE) +
- global_page_state(NR_SLAB_UNRECLAIMABLE));
- printk("%lu pages pagetables\n", global_page_state(NR_PAGETABLE));
+ printk("%ld pages of RAM\n", total);
+ printk("%ld reserved pages\n", reserved);
+ printk("%ld pages shared\n", shared);
+ printk("%ld pages swap cached\n", cached);
}
/*
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index ea28048..f591188 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -27,12 +27,19 @@ struct memory_segment {
static LIST_HEAD(mem_segs);
-static pud_t *vmem_pud_alloc(void)
+static void __ref *vmem_alloc_pages(unsigned int order)
+{
+ if (slab_is_available())
+ return (void *)__get_free_pages(GFP_KERNEL, order);
+ return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
+}
+
+static inline pud_t *vmem_pud_alloc(void)
{
pud_t *pud = NULL;
#ifdef CONFIG_64BIT
- pud = vmemmap_alloc_block(PAGE_SIZE * 4, 0);
+ pud = vmem_alloc_pages(2);
if (!pud)
return NULL;
clear_table((unsigned long *) pud, _REGION3_ENTRY_EMPTY, PAGE_SIZE * 4);
@@ -40,12 +47,12 @@ static pud_t *vmem_pud_alloc(void)
return pud;
}
-static pmd_t *vmem_pmd_alloc(void)
+static inline pmd_t *vmem_pmd_alloc(void)
{
pmd_t *pmd = NULL;
#ifdef CONFIG_64BIT
- pmd = vmemmap_alloc_block(PAGE_SIZE * 4, 0);
+ pmd = vmem_alloc_pages(2);
if (!pmd)
return NULL;
clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE * 4);
@@ -207,13 +214,14 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
if (pte_none(*pt_dir)) {
unsigned long new_page;
- new_page =__pa(vmemmap_alloc_block(PAGE_SIZE, 0));
+ new_page =__pa(vmem_alloc_pages(0));
if (!new_page)
goto out;
pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
*pt_dir = pte;
}
}
+ memset(start, 0, nr * sizeof(struct page));
ret = 0;
out:
flush_tlb_kernel_range(start_addr, end_addr);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8ba3f13..1a40256 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -63,6 +63,7 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
*/
static wait_queue_head_t dasd_init_waitq;
static wait_queue_head_t dasd_flush_wq;
+static wait_queue_head_t generic_waitq;
/*
* Allocate memory for a new device structure.
@@ -1151,11 +1152,15 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
struct list_head *l, *n;
struct dasd_ccw_req *cqr;
struct dasd_block *block;
+ void (*callback)(struct dasd_ccw_req *, void *data);
+ void *callback_data;
list_for_each_safe(l, n, final_queue) {
cqr = list_entry(l, struct dasd_ccw_req, devlist);
list_del_init(&cqr->devlist);
block = cqr->block;
+ callback = cqr->callback;
+ callback_data = cqr->callback_data;
if (block)
spin_lock_bh(&block->queue_lock);
switch (cqr->status) {
@@ -1176,7 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
BUG();
}
if (cqr->callback != NULL)
- (cqr->callback)(cqr, cqr->callback_data);
+ (callback)(cqr, callback_data);
if (block)
spin_unlock_bh(&block->queue_lock);
}
@@ -1406,17 +1411,15 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
*/
int dasd_sleep_on(struct dasd_ccw_req *cqr)
{
- wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
device = cqr->startdev;
- init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &wait_q;
+ cqr->callback_data = (void *) &generic_waitq;
dasd_add_request_tail(cqr);
- wait_event(wait_q, _wait_for_wakeup(cqr));
+ wait_event(generic_waitq, _wait_for_wakeup(cqr));
/* Request status is either done or failed. */
rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
@@ -1429,20 +1432,18 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
*/
int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
{
- wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
device = cqr->startdev;
- init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &wait_q;
+ cqr->callback_data = (void *) &generic_waitq;
dasd_add_request_tail(cqr);
- rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr));
+ rc = wait_event_interruptible(generic_waitq, _wait_for_wakeup(cqr));
if (rc == -ERESTARTSYS) {
dasd_cancel_req(cqr);
/* wait (non-interruptible) for final status */
- wait_event(wait_q, _wait_for_wakeup(cqr));
+ wait_event(generic_waitq, _wait_for_wakeup(cqr));
}
rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
return rc;
@@ -1466,7 +1467,6 @@ static inline int _dasd_term_running_cqr(struct dasd_device *device)
int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
{
- wait_queue_head_t wait_q;
struct dasd_device *device;
int rc;
@@ -1478,9 +1478,8 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
return rc;
}
- init_waitqueue_head (&wait_q);
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &wait_q;
+ cqr->callback_data = (void *) &generic_waitq;
cqr->status = DASD_CQR_QUEUED;
list_add(&cqr->devlist, &device->ccw_queue);
@@ -1489,7 +1488,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
spin_unlock_irq(get_ccwdev_lock(device->cdev));
- wait_event(wait_q, _wait_for_wakeup(cqr));
+ wait_event(generic_waitq, _wait_for_wakeup(cqr));
/* Request status is either done or failed. */
rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
@@ -2430,6 +2429,7 @@ static int __init dasd_init(void)
init_waitqueue_head(&dasd_init_waitq);
init_waitqueue_head(&dasd_flush_wq);
+ init_waitqueue_head(&generic_waitq);
/* register 'common' DASD debug area, used for all DBF_XXX calls */
dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long));
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 0d98f1f..848ef7e 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -549,7 +549,6 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
struct raw3270_request *rq)
{
unsigned long flags;
- wait_queue_head_t wq;
int rc;
#ifdef CONFIG_TN3270_CONSOLE
@@ -566,20 +565,20 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,
return rq->rc;
}
#endif
- init_waitqueue_head(&wq);
rq->callback = raw3270_wake_init;
- rq->callback_data = &wq;
+ rq->callback_data = &raw3270_wait_queue;
spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
rc = __raw3270_start(rp, view, rq);
spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
if (rc)
return rc;
/* Now wait for the completion. */
- rc = wait_event_interruptible(wq, raw3270_request_final(rq));
+ rc = wait_event_interruptible(raw3270_wait_queue,
+ raw3270_request_final(rq));
if (rc == -ERESTARTSYS) { /* Interrupted by a signal. */
raw3270_halt_io(view->dev, rq);
/* No wait for the halt to complete. */
- wait_event(wq, raw3270_request_final(rq));
+ wait_event(raw3270_wait_queue, raw3270_request_final(rq));
return -ERESTARTSYS;
}
return rq->rc;
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 9e784d5..ad05a87 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -40,7 +40,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
put_online_cpus();
}
-static void sclp_cpu_change_notify(struct work_struct *work)
+static void __ref sclp_cpu_change_notify(struct work_struct *work)
{
smp_rescan_cpus();
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 35707c0..62576af 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -71,9 +71,6 @@ static struct list_head sclp_vt220_outqueue;
/* Number of requests in outqueue */
static int sclp_vt220_outqueue_count;
-/* Wait queue used to delay write requests while we've run out of buffers */
-static wait_queue_head_t sclp_vt220_waitq;
-
/* Timer used for delaying write requests to merge subsequent messages into
* a single buffer */
static struct timer_list sclp_vt220_timer;
@@ -133,7 +130,6 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
} while (request && __sclp_vt220_emit(request));
if (request == NULL && sclp_vt220_flush_later)
sclp_vt220_emit_current();
- wake_up(&sclp_vt220_waitq);
/* Check if the tty needs a wake up call */
if (sclp_vt220_tty != NULL) {
tty_wakeup(sclp_vt220_tty);
@@ -383,7 +379,7 @@ sclp_vt220_timeout(unsigned long data)
*/
static int
__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
- int convertlf, int may_schedule)
+ int convertlf, int may_fail)
{
unsigned long flags;
void *page;
@@ -395,15 +391,14 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
overall_written = 0;
spin_lock_irqsave(&sclp_vt220_lock, flags);
do {
- /* Create a sclp output buffer if none exists yet */
+ /* Create an sclp output buffer if none exists yet */
if (sclp_vt220_current_request == NULL) {
while (list_empty(&sclp_vt220_empty)) {
spin_unlock_irqrestore(&sclp_vt220_lock, flags);
- if (in_interrupt() || !may_schedule)
- sclp_sync_wait();
+ if (may_fail)
+ goto out;
else
- wait_event(sclp_vt220_waitq,
- !list_empty(&sclp_vt220_empty));
+ sclp_sync_wait();
spin_lock_irqsave(&sclp_vt220_lock, flags);
}
page = (void *) sclp_vt220_empty.next;
@@ -437,6 +432,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
add_timer(&sclp_vt220_timer);
}
spin_unlock_irqrestore(&sclp_vt220_lock, flags);
+out:
return overall_written;
}
@@ -520,19 +516,11 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
* character to the tty device. If the kernel uses this routine,
* it must call the flush_chars() routine (if defined) when it is
* done stuffing characters into the driver.
- *
- * NOTE: include/linux/tty_driver.h specifies that a character should be
- * ignored if there is no room in the queue. This driver implements a different
- * semantic in that it will block when there is no more room left.
- *
- * FIXME: putchar can currently be called from BH and other non blocking
- * handlers so this semantic isn't a good idea.
*/
static int
sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
{
- __sclp_vt220_write(&ch, 1, 0, 0, 1);
- return 1;
+ return __sclp_vt220_write(&ch, 1, 0, 0, 1);
}
/*
@@ -653,7 +641,6 @@ static int __init __sclp_vt220_init(void)
spin_lock_init(&sclp_vt220_lock);
INIT_LIST_HEAD(&sclp_vt220_empty);
INIT_LIST_HEAD(&sclp_vt220_outqueue);
- init_waitqueue_head(&sclp_vt220_waitq);
init_timer(&sclp_vt220_timer);
sclp_vt220_current_request = NULL;
sclp_vt220_buffered_chars = 0;
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index dddf8d6..d0d565a 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -231,6 +231,9 @@ struct tape_device {
/* Request queue. */
struct list_head req_queue;
+ /* Request wait queue. */
+ wait_queue_head_t wait_queue;
+
/* Each tape device has (currently) two minor numbers. */
int first_minor;
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index ddc4a11..95da72b 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -179,11 +179,11 @@ tapeblock_requeue(struct work_struct *work) {
tapeblock_end_request(req, -EIO);
continue;
}
+ blkdev_dequeue_request(req);
+ nr_queued++;
spin_unlock_irq(&device->blk_data.request_queue_lock);
rc = tapeblock_start_request(device, req);
spin_lock_irq(&device->blk_data.request_queue_lock);
- blkdev_dequeue_request(req);
- nr_queued++;
}
spin_unlock_irq(&device->blk_data.request_queue_lock);
atomic_set(&device->blk_data.requeue_scheduled, 0);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 76e44eb..c20e3c5 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -449,6 +449,7 @@ tape_alloc_device(void)
INIT_LIST_HEAD(&device->req_queue);
INIT_LIST_HEAD(&device->node);
init_waitqueue_head(&device->state_change_wq);
+ init_waitqueue_head(&device->wait_queue);
device->tape_state = TS_INIT;
device->medium_state = MS_UNKNOWN;
*device->modeset_byte = 0;
@@ -954,21 +955,19 @@ __tape_wake_up(struct tape_request *request, void *data)
int
tape_do_io(struct tape_device *device, struct tape_request *request)
{
- wait_queue_head_t wq;
int rc;
- init_waitqueue_head(&wq);
spin_lock_irq(get_ccwdev_lock(device->cdev));
/* Setup callback */
request->callback = __tape_wake_up;
- request->callback_data = &wq;
+ request->callback_data = &device->wait_queue;
/* Add request to request queue and try to start it. */
rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc)
return rc;
/* Request added to the queue. Wait for its completion. */
- wait_event(wq, (request->callback == NULL));
+ wait_event(device->wait_queue, (request->callback == NULL));
/* Get rc from request */
return request->rc;
}
@@ -989,20 +988,19 @@ int
tape_do_io_interruptible(struct tape_device *device,
struct tape_request *request)
{
- wait_queue_head_t wq;
int rc;
- init_waitqueue_head(&wq);
spin_lock_irq(get_ccwdev_lock(device->cdev));
/* Setup callback */
request->callback = __tape_wake_up_interruptible;
- request->callback_data = &wq;
+ request->callback_data = &device->wait_queue;
rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc)
return rc;
/* Request added to the queue. Wait for its completion. */
- rc = wait_event_interruptible(wq, (request->callback == NULL));
+ rc = wait_event_interruptible(device->wait_queue,
+ (request->callback == NULL));
if (rc != -ERESTARTSYS)
/* Request finished normally. */
return request->rc;
@@ -1015,7 +1013,7 @@ tape_do_io_interruptible(struct tape_device *device,
/* Wait for the interrupt that acknowledges the halt. */
do {
rc = wait_event_interruptible(
- wq,
+ device->wait_queue,
(request->callback == NULL)
);
} while (rc == -ERESTARTSYS);
diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h
index 0e959e2..41c5476 100644
--- a/include/asm-s390/types.h
+++ b/include/asm-s390/types.h
@@ -40,7 +40,13 @@ typedef __signed__ long saddr_t;
#ifndef __ASSEMBLY__
+typedef u64 dma64_addr_t;
+#ifdef __s390x__
+/* DMA addresses come in 32-bit and 64-bit flavours. */
+typedef u64 dma_addr_t;
+#else
typedef u32 dma_addr_t;
+#endif
#ifndef __s390x__
typedef union {
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-06-10 8:21 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-06-10 8:21 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
arch/s390/Kconfig | 1 +
arch/s390/kernel/smp.c | 2 +-
arch/s390/mm/vmem.c | 2 +-
drivers/s390/char/sclp_vt220.c | 1 +
drivers/s390/char/tape_3590.c | 2 +-
drivers/s390/cio/blacklist.c | 6 +++---
drivers/s390/cio/cio.c | 20 +++++++++++---------
include/asm-s390/system.h | 8 ++++----
8 files changed, 23 insertions(+), 19 deletions(-)
Carsten Otte (1):
[S390] vt220 console, initialize list head before use
Cornelia Huck (2):
[S390] cio: Fix sparse warnings in blacklist.c.
[S390] cio: Fix inverted isc priorities.
Heiko Carstens (2):
[S390] sparsemem: use SPARSEMEM_STATIC if !64BIT.
[S390] vmemmap: fix off-by-one bug.
Julia Lawall (1):
[S390] tape_3590.c: introduce missing kfree
Martin Schwidefsky (1):
[S390] Fix __ctl_load/__ctl_store inline assembly constraints
Segher Boessenkool (1):
[S390] Fix build failure in __cpu_up()
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 93acb3c..107e492 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -304,6 +304,7 @@ config ARCH_SPARSEMEM_ENABLE
def_bool y
select SPARSEMEM_VMEMMAP_ENABLE
select SPARSEMEM_VMEMMAP
+ select SPARSEMEM_STATIC if !64BIT
config ARCH_SPARSEMEM_DEFAULT
def_bool y
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 42b1d12..5d4fa4b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -711,7 +711,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
memset(sf, 0, sizeof(struct stack_frame));
sf->gprs[9] = (unsigned long) sf;
cpu_lowcore->save_area[15] = (unsigned long) sf;
- __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
+ __ctl_store(cpu_lowcore->cregs_save_area, 0, 15);
asm volatile(
" stam 0,15,0(%0)"
: : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index f591188..e4868bf 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -236,7 +236,7 @@ static int insert_memory_segment(struct memory_segment *seg)
{
struct memory_segment *tmp;
- if (seg->start + seg->size >= VMEM_MAX_PHYS ||
+ if (seg->start + seg->size > VMEM_MAX_PHYS ||
seg->start + seg->size < seg->start)
return -ERANGE;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 62576af..3e577f6 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -773,6 +773,7 @@ sclp_vt220_con_init(void)
{
int rc;
+ INIT_LIST_HEAD(&sclp_vt220_register.list);
if (!CONSOLE_IS_SCLP)
return 0;
rc = __sclp_vt220_init();
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 8246ef3..42ce791 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1598,7 +1598,7 @@ tape_3590_setup_device(struct tape_device *device)
rc = tape_3590_read_dev_chars(device, rdc_data);
if (rc) {
DBF_LH(3, "Read device characteristics failed!\n");
- goto fail_kmalloc;
+ goto fail_rdc_data;
}
rc = tape_std_assign(device);
if (rc)
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index a4a5f2e..0bfcbbe 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -97,8 +97,8 @@ static int pure_hex(char **cp, unsigned int *val, int min_digit,
return 0;
}
-static int parse_busid(char *str, int *cssid, int *ssid, int *devno,
- int msgtrigger)
+static int parse_busid(char *str, unsigned int *cssid, unsigned int *ssid,
+ unsigned int *devno, int msgtrigger)
{
char *str_work;
int val, rc, ret;
@@ -148,7 +148,7 @@ out:
static int blacklist_parse_parameters(char *str, range_action action,
int msgtrigger)
{
- int from_cssid, to_cssid, from_ssid, to_ssid, from, to;
+ unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to;
int rc, totalrc;
char *parm;
range_action ra;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 82c6a2d..b32d7eb 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -576,12 +576,14 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
err = -ENODEV;
goto out;
}
- if (cio_is_console(sch->schid))
+ if (cio_is_console(sch->schid)) {
sch->opm = 0xff;
- else
+ sch->isc = 1;
+ } else {
sch->opm = chp_get_sch_opm(sch);
+ sch->isc = 3;
+ }
sch->lpm = sch->schib.pmcw.pam & sch->opm;
- sch->isc = 3;
CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X "
"- PIM = %02X, PAM = %02X, POM = %02X\n",
@@ -704,9 +706,9 @@ void wait_cons_dev(void)
if (!console_subchannel_in_use)
return;
- /* disable all but isc 7 (console device) */
+ /* disable all but isc 1 (console device) */
__ctl_store (save_cr6, 6, 6);
- cr6 = 0x01000000;
+ cr6 = 0x40000000;
__ctl_load (cr6, 6, 6);
do {
@@ -788,11 +790,11 @@ cio_probe_console(void)
}
/*
- * enable console I/O-interrupt subclass 7
+ * enable console I/O-interrupt subclass 1
*/
- ctl_set_bit(6, 24);
- console_subchannel.isc = 7;
- console_subchannel.schib.pmcw.isc = 7;
+ ctl_set_bit(6, 30);
+ console_subchannel.isc = 1;
+ console_subchannel.schib.pmcw.isc = 1;
console_subchannel.schib.pmcw.intparm =
(u32)(addr_t)&console_subchannel;
ret = cio_modify(&console_subchannel);
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index e0d4500..819e7d9 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -315,14 +315,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
asm volatile( \
" lctlg %1,%2,0(%0)\n" \
: : "a" (&array), "i" (low), "i" (high), \
- "m" (*(addrtype *)(array))); \
+ "m" (*(addrtype *)(&array))); \
})
#define __ctl_store(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \
asm volatile( \
" stctg %2,%3,0(%1)\n" \
- : "=m" (*(addrtype *)(array)) \
+ : "=m" (*(addrtype *)(&array)) \
: "a" (&array), "i" (low), "i" (high)); \
})
@@ -333,14 +333,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
asm volatile( \
" lctl %1,%2,0(%0)\n" \
: : "a" (&array), "i" (low), "i" (high), \
- "m" (*(addrtype *)(array))); \
+ "m" (*(addrtype *)(&array))); \
})
#define __ctl_store(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \
asm volatile( \
" stctl %2,%3,0(%1)\n" \
- : "=m" (*(addrtype *)(array)) \
+ : "=m" (*(addrtype *)(&array)) \
: "a" (&array), "i" (low), "i" (high)); \
})
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Please pull git390 'for-linus' branch
@ 2008-07-08 10:20 Martin Schwidefsky
0 siblings, 0 replies; 18+ messages in thread
From: Martin Schwidefsky @ 2008-07-08 10:20 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, linux-s390, npiggin, hugh
Please pull from 'for-linus' branch of
git://git390.osdl.marist.edu/pub/scm/linux-2.6.git for-linus
to receive the following updates:
include/asm-s390/pgtable.h | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
Nick Piggin (1):
[S390] protect _PAGE_SPECIAL bit against mprotect
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index c7f4f8e..bd0ea19 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -223,6 +223,9 @@ extern char empty_zero_page[PAGE_SIZE];
#define _PAGE_SPECIAL 0x004 /* SW associated with special page */
#define __HAVE_ARCH_PTE_SPECIAL
+/* Set of bits not changed in pte_modify */
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL)
+
/* Six different types of pages. */
#define _PAGE_TYPE_EMPTY 0x400
#define _PAGE_TYPE_NONE 0x401
@@ -681,7 +684,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
*/
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
- pte_val(pte) &= PAGE_MASK;
+ pte_val(pte) &= _PAGE_CHG_MASK;
pte_val(pte) |= pgprot_val(newprot);
return pte;
}
^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2008-07-08 10:20 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-19 14:46 Please pull git390 'for-linus' branch Martin Schwidefsky
-- strict thread matches above, loose matches on Subject: below --
2008-07-08 10:20 Martin Schwidefsky
2008-06-10 8:21 Martin Schwidefsky
2008-05-30 8:41 Martin Schwidefsky
2008-04-30 12:06 Martin Schwidefsky
2008-03-20 16:13 Martin Schwidefsky
2008-01-26 13:23 Martin Schwidefsky
2007-12-17 15:42 Martin Schwidefsky
2007-11-20 11:38 Martin Schwidefsky
2007-10-22 10:54 Martin Schwidefsky
2007-10-12 14:22 Martin Schwidefsky
2007-08-22 12:44 Martin Schwidefsky
2007-07-27 11:40 Martin Schwidefsky
2007-06-19 8:50 Martin Schwidefsky
2007-05-31 15:40 Martin Schwidefsky
2007-05-04 16:59 Martin Schwidefsky
2007-04-04 16:39 Martin Schwidefsky
2007-03-19 13:16 Martin Schwidefsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).