Commit 53ce2dc2 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
  [S390] Change atomic_read/set to inline functions with barrier semantics.
  [S390] kprobes: fix instruction length calculation
  [S390] hypfs: inode corruption due to missing locking
  [S390] disassembler: fix b2 opcodes like srst, bsg, and others
  [S390] vmur: fix reference counting for vmur device structure
  [S390] vmur: fix diag14 exceptions with addresses > 2GB.
  [S390] qdio: Refresh buffer states for IQDIO Asynchronous output queue
  [S390] qdio: fix EQBS handling on CCQ96
  [S390] cio: change confusing message in cmf.
  [S390] cio: dont forget to set last slot to NULL in ccw_uevent().
parents 8b14cb99 c51b9621
...@@ -60,17 +60,28 @@ static void hypfs_add_dentry(struct dentry *dentry) ...@@ -60,17 +60,28 @@ static void hypfs_add_dentry(struct dentry *dentry)
hypfs_last_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) static void hypfs_remove(struct dentry *dentry)
{ {
struct dentry *parent; struct dentry *parent;
parent = dentry->d_parent; parent = dentry->d_parent;
if (S_ISDIR(dentry->d_inode->i_mode)) if (!parent || !parent->d_inode)
simple_rmdir(parent->d_inode, dentry); return;
else mutex_lock(&parent->d_inode->i_mutex);
simple_unlink(parent->d_inode, dentry); 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); d_delete(dentry);
dput(dentry); dput(dentry);
mutex_unlock(&parent->d_inode->i_mutex);
} }
static void hypfs_delete_tree(struct dentry *root) 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) ...@@ -315,6 +326,7 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
} }
hypfs_update_update(sb); hypfs_update_update(sb);
sb->s_root = root_dentry; sb->s_root = root_dentry;
printk(KERN_INFO "hypfs: Hypervisor filesystem mounted\n");
return 0; return 0;
err_tree: err_tree:
...@@ -356,13 +368,17 @@ static struct dentry *hypfs_create_file(struct super_block *sb, ...@@ -356,13 +368,17 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
qname.name = name; qname.name = name;
qname.len = strlen(name); qname.len = strlen(name);
qname.hash = full_name_hash(name, qname.len); qname.hash = full_name_hash(name, qname.len);
mutex_lock(&parent->d_inode->i_mutex);
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_one_len(name, parent, strlen(name));
if (IS_ERR(dentry)) if (IS_ERR(dentry)) {
return ERR_PTR(-ENOMEM); dentry = ERR_PTR(-ENOMEM);
goto fail;
}
inode = hypfs_make_inode(sb, mode); inode = hypfs_make_inode(sb, mode);
if (!inode) { if (!inode) {
dput(dentry); dput(dentry);
return ERR_PTR(-ENOMEM); dentry = ERR_PTR(-ENOMEM);
goto fail;
} }
if (mode & S_IFREG) { if (mode & S_IFREG) {
inode->i_fop = &hypfs_file_ops; inode->i_fop = &hypfs_file_ops;
...@@ -379,6 +395,8 @@ static struct dentry *hypfs_create_file(struct super_block *sb, ...@@ -379,6 +395,8 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
inode->i_private = data; inode->i_private = data;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
dget(dentry); dget(dentry);
fail:
mutex_unlock(&parent->d_inode->i_mutex);
return dentry; return dentry;
} }
...@@ -391,7 +409,6 @@ struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, ...@@ -391,7 +409,6 @@ struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return dentry; return dentry;
hypfs_add_dentry(dentry); hypfs_add_dentry(dentry);
parent->d_inode->i_nlink++;
return dentry; return dentry;
} }
......
...@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional ...@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o base.o early.o \ 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 \ 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),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
......
/*
* 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);
...@@ -577,7 +577,7 @@ static struct insn opcode_b2[] = { ...@@ -577,7 +577,7 @@ static struct insn opcode_b2[] = {
{ "esta", 0x4a, INSTR_RRE_RR }, { "esta", 0x4a, INSTR_RRE_RR },
{ "lura", 0x4b, INSTR_RRE_RR }, { "lura", 0x4b, INSTR_RRE_RR },
{ "tar", 0x4c, INSTR_RRE_AR }, { "tar", 0x4c, INSTR_RRE_AR },
{ "cpya", INSTR_RRE_AA }, { "cpya", 0x4d, INSTR_RRE_AA },
{ "sar", 0x4e, INSTR_RRE_AR }, { "sar", 0x4e, INSTR_RRE_AR },
{ "ear", 0x4f, INSTR_RRE_RA }, { "ear", 0x4f, INSTR_RRE_RA },
{ "csp", 0x50, INSTR_RRE_RR }, { "csp", 0x50, INSTR_RRE_RR },
......
...@@ -85,7 +85,7 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) ...@@ -85,7 +85,7 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
ainsn->reg = (*ainsn->insn & 0xf0) >> 4; ainsn->reg = (*ainsn->insn & 0xf0) >> 4;
/* save the instruction length (pop 5-5) in bytes */ /* save the instruction length (pop 5-5) in bytes */
switch (*(__u8 *) (ainsn->insn) >> 4) { switch (*(__u8 *) (ainsn->insn) >> 6) {
case 0: case 0:
ainsn->ilen = 2; ainsn->ilen = 2;
break; break;
......
...@@ -25,7 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap); ...@@ -25,7 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap);
EXPORT_SYMBOL(_ni_bitmap); EXPORT_SYMBOL(_ni_bitmap);
EXPORT_SYMBOL(_zb_findmap); EXPORT_SYMBOL(_zb_findmap);
EXPORT_SYMBOL(_sb_findmap); EXPORT_SYMBOL(_sb_findmap);
EXPORT_SYMBOL(diag10);
/* /*
* semaphore ops * semaphore ops
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/diag.h>
static char *sender = "VMRMSVM"; static char *sender = "VMRMSVM";
module_param(sender, charp, 0400); module_param(sender, charp, 0400);
......
...@@ -42,23 +42,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); ...@@ -42,23 +42,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
char empty_zero_page[PAGE_SIZE] __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) void show_mem(void)
{ {
int i, total = 0, reserved = 0; int i, total = 0, reserved = 0;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
#include <asm/todclk.h> #include <asm/todclk.h>
#include <asm/vtoc.h> #include <asm/vtoc.h>
#include <asm/diag.h>
#include "dasd_int.h" #include "dasd_int.h"
#include "dasd_diag.h" #include "dasd_diag.h"
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/diag.h>
#include "raw3270.h" #include "raw3270.h"
......
This diff is collapsed.
...@@ -70,6 +70,7 @@ struct urdev { ...@@ -70,6 +70,7 @@ struct urdev {
size_t reclen; /* Record length for *write* CCWs */ size_t reclen; /* Record length for *write* CCWs */
int class; /* VM device class */ int class; /* VM device class */
int io_request_rc; /* return code from I/O request */ int io_request_rc; /* return code from I/O request */
atomic_t ref_count; /* reference counter */
}; };
/* /*
......
...@@ -594,6 +594,9 @@ alloc_cmb (struct ccw_device *cdev) ...@@ -594,6 +594,9 @@ alloc_cmb (struct ccw_device *cdev)
free_pages((unsigned long)mem, get_order(size)); free_pages((unsigned long)mem, get_order(size));
} else if (!mem) { } else if (!mem) {
/* no luck */ /* no luck */
printk(KERN_WARNING "cio: failed to allocate area "
"for measuring %d subchannels\n",
cmb_area.num_channels);
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} else { } else {
...@@ -1279,13 +1282,6 @@ init_cmf(void) ...@@ -1279,13 +1282,6 @@ init_cmf(void)
case CMF_BASIC: case CMF_BASIC:
format_string = "basic"; format_string = "basic";
cmbops = &cmbops_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; break;
case CMF_EXTENDED: case CMF_EXTENDED:
format_string = "extended"; format_string = "extended";
......
...@@ -117,7 +117,10 @@ static int ccw_uevent(struct device *dev, char **envp, int num_envp, ...@@ -117,7 +117,10 @@ static int ccw_uevent(struct device *dev, char **envp, int num_envp,
snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); snprint_alias(modalias_buf, sizeof(modalias_buf), id, "");
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
"MODALIAS=%s", modalias_buf); "MODALIAS=%s", modalias_buf);
return ret; if (ret)
return ret;
envp[i] = NULL;
return 0;
} }
struct bus_type ccw_bus_type; struct bus_type ccw_bus_type;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/diag.h>
#include "cio.h" #include "cio.h"
#include "cio_debug.h" #include "cio_debug.h"
...@@ -24,51 +25,6 @@ ...@@ -24,51 +25,6 @@
#include "device.h" #include "device.h"
#include "ioasm.h" #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 : * Input :
* devno - device number * devno - device number
...@@ -349,5 +305,3 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -349,5 +305,3 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
break; break;
} }
} }
EXPORT_SYMBOL(diag210);
...@@ -195,6 +195,8 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state, ...@@ -195,6 +195,8 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
again: again:
ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq); rc = qdio_check_ccq(q, ccq);
if ((ccq == 96) && (tmp_cnt != *cnt))
rc = 0;
if (rc == 1) { if (rc == 1) {
QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); QDIO_DBF_TEXT5(1,trace,"eqAGAIN");
goto again; goto again;
...@@ -740,7 +742,8 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) ...@@ -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), first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used),
(QDIO_MAX_BUFFERS_PER_Q-1)); (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; SYNC_MEMORY;
check_next: check_next:
......
...@@ -67,8 +67,17 @@ typedef struct { ...@@ -67,8 +67,17 @@ typedef struct {
#endif /* __GNUC__ */ #endif /* __GNUC__ */
#define atomic_read(v) ((v)->counter) static inline int atomic_read(const atomic_t *v)
#define atomic_set(v,i) (((v)->counter) = (i)) {
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) static __inline__ int atomic_add_return(int i, atomic_t * v)
{ {
...@@ -182,8 +191,17 @@ typedef struct { ...@@ -182,8 +191,17 @@ typedef struct {
#endif /* __GNUC__ */ #endif /* __GNUC__ */
#define atomic64_read(v) ((v)->counter) static inline long long atomic64_read(const atomic64_t *v)
#define atomic64_set(v,i) (((v)->counter) = (i)) {
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) static __inline__ long long atomic64_add_return(long long i, atomic64_t * v)
{ {
......
...@@ -258,19 +258,6 @@ struct ciw { ...@@ -258,19 +258,6 @@ struct ciw {
/* Sick revalidation of device. */ /* Sick revalidation of device. */
#define CIO_REVALIDATE 0x0008 #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 { struct ccw_dev_id {
u8 ssid; u8 ssid;
u16 devno; u16 devno;
...@@ -285,8 +272,6 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, ...@@ -285,8 +272,6 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1,
return 0; return 0;
} }
extern int diag210(struct diag210 *addr);
extern void wait_cons_dev(void); extern void wait_cons_dev(void);
extern void css_schedule_reprobe(void); extern void css_schedule_reprobe(void);
......
/*
* 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 */
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#define check_pgt_cache() do {} while (0) #define check_pgt_cache() do {} while (0)
extern void diag10(unsigned long addr);
/* /*
* Page allocation orders. * Page allocation orders.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment