mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 09:31:14 +00:00
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().
This commit is contained in:
commit
53ce2dc271
20 changed files with 372 additions and 193 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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
|
||||||
|
|
||||||
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)
|
||||||
|
|
102
arch/s390/kernel/diag.c
Normal file
102
arch/s390/kernel/diag.c
Normal file
|
@ -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);
|
|
@ -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)
|
||||||
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);
|
||||||
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 @@
|
||||||
|
|
||||||
#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);
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <asm/cio.h>
|
#include <asm/cio.h>
|
||||||
#include <asm/ccwdev.h>
|
#include <asm/ccwdev.h>
|
||||||
#include <asm/debug.h>
|
#include <asm/debug.h>
|
||||||
|
#include <asm/diag.h>
|
||||||
|
|
||||||
#include "vmur.h"
|
#include "vmur.h"
|
||||||
|
|
||||||
|
@ -68,8 +69,26 @@ static struct ccw_driver ur_driver = {
|
||||||
.set_offline = ur_set_offline,
|
.set_offline = ur_set_offline,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(vmur_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocation, freeing, getting and putting of urdev structures
|
* 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)
|
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);
|
urd = kzalloc(sizeof(struct urdev), GFP_KERNEL);
|
||||||
if (!urd)
|
if (!urd)
|
||||||
return NULL;
|
return NULL;
|
||||||
urd->cdev = cdev;
|
|
||||||
urd->reclen = cdev->id.driver_info;
|
urd->reclen = cdev->id.driver_info;
|
||||||
ccw_device_get_id(cdev, &urd->dev_id);
|
ccw_device_get_id(cdev, &urd->dev_id);
|
||||||
mutex_init(&urd->io_mutex);
|
mutex_init(&urd->io_mutex);
|
||||||
mutex_init(&urd->open_mutex);
|
mutex_init(&urd->open_mutex);
|
||||||
|
atomic_set(&urd->ref_count, 1);
|
||||||
|
urd->cdev = cdev;
|
||||||
|
get_device(&cdev->dev);
|
||||||
return urd;
|
return urd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void urdev_free(struct urdev *urd)
|
static void urdev_free(struct urdev *urd)
|
||||||
{
|
{
|
||||||
|
TRACE("urdev_free: %p\n", urd);
|
||||||
|
if (urd->cdev)
|
||||||
|
put_device(&urd->cdev->dev);
|
||||||
kfree(urd);
|
kfree(urd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void urdev_get(struct urdev *urd)
|
||||||
* This is how the character device driver gets a reference to a
|
{
|
||||||
* ur device. When this call returns successfully, a reference has
|
atomic_inc(&urd->ref_count);
|
||||||
* 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 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)
|
static struct urdev *urdev_get_from_devno(u16 devno)
|
||||||
{
|
{
|
||||||
char bus_id[16];
|
char bus_id[16];
|
||||||
struct ccw_device *cdev;
|
struct ccw_device *cdev;
|
||||||
|
struct urdev *urd;
|
||||||
|
|
||||||
sprintf(bus_id, "0.0.%04x", devno);
|
sprintf(bus_id, "0.0.%04x", devno);
|
||||||
cdev = get_ccwdev_by_busid(&ur_driver, bus_id);
|
cdev = get_ccwdev_by_busid(&ur_driver, bus_id);
|
||||||
if (!cdev)
|
if (!cdev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
urd = urdev_get_from_cdev(cdev);
|
||||||
return cdev->dev.driver_data;
|
put_device(&cdev->dev);
|
||||||
|
return urd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void urdev_put(struct urdev *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;
|
return;
|
||||||
}
|
}
|
||||||
urd = cdev->dev.driver_data;
|
urd = cdev->dev.driver_data;
|
||||||
|
BUG_ON(!urd);
|
||||||
/* On special conditions irb is an error pointer */
|
/* On special conditions irb is an error pointer */
|
||||||
if (IS_ERR(irb))
|
if (IS_ERR(irb))
|
||||||
urd->io_request_rc = PTR_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,
|
static ssize_t ur_attr_reclen_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
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);
|
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);
|
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
|
* diagnose code 0x14 subcode 0x0028 - position spool file to designated
|
||||||
* record
|
* record
|
||||||
|
@ -415,7 +435,7 @@ static int diag_position_to_record(int devno, int record)
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
cc = do_diag_14(record, devno, 0x28);
|
cc = diag14(record, devno, 0x28);
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
case 0:
|
case 0:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -440,7 +460,7 @@ static int diag_read_file(int devno, char *buf)
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
cc = do_diag_14((unsigned long) buf, devno, 0x00);
|
cc = diag14((unsigned long) buf, devno, 0x00);
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
case 0:
|
case 0:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -533,7 +553,7 @@ static int diag_read_next_file_info(struct file_control_block *buf, int spid)
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
cc = do_diag_14((unsigned long) buf, spid, 0xfff);
|
cc = diag14((unsigned long) buf, spid, 0xfff);
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
case 0:
|
case 0:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -750,64 +770,63 @@ static struct file_operations ur_fops = {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ccw_device infrastructure:
|
* ccw_device infrastructure:
|
||||||
* ur_probe gets its own ref to the device (i.e. get_device),
|
* ur_probe creates the struct urdev (with refcount = 1), the device
|
||||||
* creates the struct urdev, the device attributes, sets up
|
* attributes, sets up the interrupt handler and validates the virtual
|
||||||
* the interrupt handler and validates the virtual unit record device.
|
* unit record device.
|
||||||
* ur_remove removes the device attributes, frees the struct urdev
|
* ur_remove removes the device attributes and drops the reference to
|
||||||
* and drops (put_device) the ref to the device we got in ur_probe.
|
* 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)
|
static int ur_probe(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct urdev *urd;
|
struct urdev *urd;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
TRACE("ur_probe: cdev=%p state=%d\n", cdev, *(int *) cdev->private);
|
TRACE("ur_probe: cdev=%p\n", cdev);
|
||||||
|
|
||||||
if (!get_device(&cdev->dev))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
|
mutex_lock(&vmur_mutex);
|
||||||
urd = urdev_alloc(cdev);
|
urd = urdev_alloc(cdev);
|
||||||
if (!urd) {
|
if (!urd) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto fail;
|
goto fail_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ur_create_attributes(&cdev->dev);
|
rc = ur_create_attributes(&cdev->dev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto fail;
|
goto fail_urdev_put;
|
||||||
}
|
}
|
||||||
cdev->dev.driver_data = urd;
|
|
||||||
cdev->handler = ur_int_handler;
|
cdev->handler = ur_int_handler;
|
||||||
|
|
||||||
/* validate virtual unit record device */
|
/* validate virtual unit record device */
|
||||||
urd->class = get_urd_class(urd);
|
urd->class = get_urd_class(urd);
|
||||||
if (urd->class < 0) {
|
if (urd->class < 0) {
|
||||||
rc = urd->class;
|
rc = urd->class;
|
||||||
goto fail;
|
goto fail_remove_attr;
|
||||||
}
|
}
|
||||||
if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) {
|
if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) {
|
||||||
rc = -ENOTSUPP;
|
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;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail_remove_attr:
|
||||||
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);
|
|
||||||
ur_remove_attributes(&cdev->dev);
|
ur_remove_attributes(&cdev->dev);
|
||||||
urdev_free(urd);
|
fail_urdev_put:
|
||||||
put_device(&cdev->dev);
|
urdev_put(urd);
|
||||||
|
fail_unlock:
|
||||||
|
mutex_unlock(&vmur_mutex);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ur_set_online(struct ccw_device *cdev)
|
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;
|
int minor, major, rc;
|
||||||
char node_id[16];
|
char node_id[16];
|
||||||
|
|
||||||
TRACE("ur_set_online: cdev=%p state=%d\n", cdev,
|
TRACE("ur_set_online: cdev=%p\n", cdev);
|
||||||
*(int *) cdev->private);
|
|
||||||
|
|
||||||
if (!try_module_get(ur_driver.owner))
|
mutex_lock(&vmur_mutex);
|
||||||
return -EINVAL;
|
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;
|
minor = urd->dev_id.devno;
|
||||||
major = MAJOR(ur_first_dev_maj_min);
|
major = MAJOR(ur_first_dev_maj_min);
|
||||||
|
|
||||||
urd->char_device = cdev_alloc();
|
urd->char_device = cdev_alloc();
|
||||||
if (!urd->char_device) {
|
if (!urd->char_device) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto fail_module_put;
|
goto fail_urdev_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdev_init(urd->char_device, &ur_fops);
|
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);
|
TRACE("ur_set_online: device_create rc=%d\n", rc);
|
||||||
goto fail_free_cdev;
|
goto fail_free_cdev;
|
||||||
}
|
}
|
||||||
|
urdev_put(urd);
|
||||||
|
mutex_unlock(&vmur_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_free_cdev:
|
fail_free_cdev:
|
||||||
cdev_del(urd->char_device);
|
cdev_del(urd->char_device);
|
||||||
fail_module_put:
|
urd->char_device = NULL;
|
||||||
module_put(ur_driver.owner);
|
fail_urdev_put:
|
||||||
|
urdev_put(urd);
|
||||||
|
fail_unlock:
|
||||||
|
mutex_unlock(&vmur_mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ur_set_offline_force(struct ccw_device *cdev, int force)
|
||||||
|
{
|
||||||
|
struct urdev *urd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
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);
|
||||||
|
urd->char_device = NULL;
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
fail_urdev_put:
|
||||||
|
urdev_put(urd);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ur_set_offline(struct ccw_device *cdev)
|
static int ur_set_offline(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct urdev *urd;
|
int rc;
|
||||||
|
|
||||||
TRACE("ur_set_offline: cdev=%p cdev->private=%p state=%d\n",
|
mutex_lock(&vmur_mutex);
|
||||||
cdev, cdev->private, *(int *) cdev->private);
|
rc = ur_set_offline_force(cdev, 0);
|
||||||
urd = (struct urdev *) cdev->dev.driver_data;
|
mutex_unlock(&vmur_mutex);
|
||||||
device_destroy(vmur_class, urd->char_device->dev);
|
return rc;
|
||||||
cdev_del(urd->char_device);
|
}
|
||||||
module_put(ur_driver.owner);
|
|
||||||
|
|
||||||
return 0;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)
|
||||||
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)
|
||||||
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,
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(diag210);
|
|
||||||
|
|
|
@ -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)
|
||||||
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 {
|
||||||
|
|
||||||
#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 {
|
||||||
|
|
||||||
#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 {
|
||||||
/* 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,
|
||||||
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);
|
||||||
|
|
39
include/asm-s390/diag.h
Normal file
39
include/asm-s390/diag.h
Normal file
|
@ -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 */
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue