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] Fix sclp_vt220 error handling.
  [S390] cio: Reorganize initialization.
  [S390] cio: Make CIO_* macros safe if dbfs are not available.
  [S390] cio: Clean up messages.
  [S390] Fix IRQ tracing.
  [S390] vmur: fix diag14_read.
  [S390] Wire up sys_fallocate.
  [S390] add types.h include to s390_ext.h
  [S390] cio: Remove deprecated rdc/rcd.
  [S390] Get rid of new section mismatch warnings.
  [S390] sclp: kill unused SCLP config option.
  [S390] cio: Remove remains of _ccw_device_get_device_number().
  [S390] cio: css_sch_device_register() can be made static.
  [S390] Improve __smp_call_function_map.
  [S390] Convert to smp_call_function_single.
This commit is contained in:
Linus Torvalds 2007-07-28 19:33:23 -07:00
commit 9873aed5a9
34 changed files with 236 additions and 463 deletions

View File

@ -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 What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
When: September 2007 When: September 2007
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific

View File

@ -173,7 +173,7 @@ int appldata_diag(char record_nr, u16 function, unsigned long buffer,
/* /*
* appldata_mod_vtimer_wrap() * 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. * accepts only one parameter.
*/ */
static void __appldata_mod_vtimer_wrap(void *p) { static void __appldata_mod_vtimer_wrap(void *p) {
@ -208,9 +208,9 @@ __appldata_vtimer_setup(int cmd)
num_online_cpus()) * TOD_MICRO; num_online_cpus()) * TOD_MICRO;
for_each_online_cpu(i) { for_each_online_cpu(i) {
per_cpu(appldata_timer, i).expires = per_cpu_interval; per_cpu(appldata_timer, i).expires = per_cpu_interval;
smp_call_function_on(add_virt_timer_periodic, smp_call_function_single(i, add_virt_timer_periodic,
&per_cpu(appldata_timer, i), &per_cpu(appldata_timer, i),
0, 1, i); 0, 1);
} }
appldata_timer_active = 1; appldata_timer_active = 1;
P_INFO("Monitoring timer started.\n"); P_INFO("Monitoring timer started.\n");
@ -236,8 +236,8 @@ __appldata_vtimer_setup(int cmd)
} args; } args;
args.timer = &per_cpu(appldata_timer, i); args.timer = &per_cpu(appldata_timer, i);
args.expires = per_cpu_interval; args.expires = per_cpu_interval;
smp_call_function_on(__appldata_mod_vtimer_wrap, smp_call_function_single(i, __appldata_mod_vtimer_wrap,
&args, 0, 1, i); &args, 0, 1);
} }
} }
} }

View File

@ -1710,3 +1710,13 @@ compat_sys_timerfd_wrapper:
sys_eventfd_wrapper: sys_eventfd_wrapper:
llgfr %r2,%r2 # unsigned int llgfr %r2,%r2 # unsigned int
jg sys_eventfd 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

View File

@ -624,9 +624,11 @@ io_work_loop:
# _TIF_MCCK_PENDING is set, call handler # _TIF_MCCK_PENDING is set, call handler
# #
io_mcck_pending: io_mcck_pending:
TRACE_IRQS_OFF
l %r1,BASED(.Ls390_handle_mcck) l %r1,BASED(.Ls390_handle_mcck)
la %r14,BASED(io_work_loop) basr %r14,%r1 # TIF bit will be cleared by handler
br %r1 # TIF bit will be cleared by handler TRACE_IRQS_ON
b BASED(io_work_loop)
# #
# _TIF_NEED_RESCHED is set, call schedule # _TIF_NEED_RESCHED is set, call schedule

View File

@ -611,8 +611,10 @@ io_work_loop:
# _TIF_MCCK_PENDING is set, call handler # _TIF_MCCK_PENDING is set, call handler
# #
io_mcck_pending: io_mcck_pending:
larl %r14,io_work_loop TRACE_IRQS_OFF
jg s390_handle_mcck # TIF bit will be cleared by handler 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 # _TIF_NEED_RESCHED is set, call schedule

View File

@ -35,6 +35,7 @@
#define ARCH_OFFSET 0 #define ARCH_OFFSET 0
#endif #endif
.section ".text.head","ax"
#ifndef CONFIG_IPL #ifndef CONFIG_IPL
.org 0 .org 0
.long 0x00080000,0x80000000+startup # Just a restart PSW .long 0x00080000,0x80000000+startup # Just a restart PSW

View File

@ -120,7 +120,7 @@ static void __smp_call_function_map(void (*func) (void *info), void *info,
if (wait) if (wait)
data.finished = CPU_MASK_NONE; data.finished = CPU_MASK_NONE;
spin_lock_bh(&call_lock); spin_lock(&call_lock);
call_data = &data; call_data = &data;
for_each_cpu_mask(cpu, map) 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 */ /* Wait for response */
while (!cpus_equal(map, data.started)) while (!cpus_equal(map, data.started))
cpu_relax(); cpu_relax();
if (wait) if (wait)
while (!cpus_equal(map, data.finished)) while (!cpus_equal(map, data.finished))
cpu_relax(); cpu_relax();
spin_unlock(&call_lock);
spin_unlock_bh(&call_lock);
out: out:
local_irq_disable(); if (local) {
if (local) local_irq_disable();
func(info); 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); 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 * @func: the function to run; this must be fast and non-blocking
* @info: an arbitrary pointer to pass to the function * @info: an arbitrary pointer to pass to the function
* @nonatomic: unused * @nonatomic: unused
* @wait: if true, wait (atomically) until function has completed on other CPUs * @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. * Run a function on one processor.
* *
* You must not call this function with disabled interrupts, from a * You must not call this function with disabled interrupts, from a
* hardware interrupt handler or from a bottom half. * hardware interrupt handler or from a bottom half.
*/ */
int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic, int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
int wait, int cpu) int nonatomic, int wait)
{ {
cpumask_t map = CPU_MASK_NONE;
preempt_disable(); preempt_disable();
cpu_set(cpu, map); __smp_call_function_map(func, info, nonatomic, wait,
__smp_call_function_map(func, info, nonatomic, wait, map); cpumask_of_cpu(cpu));
preempt_enable(); preempt_enable();
return 0; return 0;
} }
EXPORT_SYMBOL(smp_call_function_on); EXPORT_SYMBOL(smp_call_function_single);
static void do_send_stop(void) static void do_send_stop(void)
{ {

View File

@ -265,3 +265,23 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args)
return -EFAULT; return -EFAULT;
return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); 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

View File

@ -322,7 +322,7 @@ NI_SYSCALL /* 310 sys_move_pages */
SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper) SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper) SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_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_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper) SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper) SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)

View File

@ -21,6 +21,7 @@ SECTIONS
. = 0x00000000; . = 0x00000000;
_text = .; /* Text and read-only data */ _text = .; /* Text and read-only data */
.text : { .text : {
*(.text.head)
TEXT_TEXT TEXT_TEXT
SCHED_TEXT SCHED_TEXT
LOCK_TEXT LOCK_TEXT

View File

@ -415,7 +415,7 @@ EXPORT_SYMBOL(add_virt_timer_periodic);
/* /*
* If we change a pending timer the function must be called on the CPU * 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 * 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. * we do the same. The timer will be added on the current CPU as a oneshot timer.

View File

@ -29,8 +29,8 @@ struct memory_segment {
static LIST_HEAD(mem_segs); static LIST_HEAD(mem_segs);
void memmap_init(unsigned long size, int nid, unsigned long zone, void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn) unsigned long start_pfn)
{ {
struct page *start, *end; struct page *start, *end;
struct page *map_start, *map_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()) if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order); return (void *)__get_free_pages(GFP_KERNEL, order);

View File

@ -44,15 +44,9 @@ config CCW_CONSOLE
depends on TN3215_CONSOLE || TN3270_CONSOLE depends on TN3215_CONSOLE || TN3270_CONSOLE
default y 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 config SCLP_TTY
bool "Support for SCLP line mode terminal" bool "Support for SCLP line mode terminal"
depends on SCLP depends on S390
help help
Include support for IBM SCLP line-mode terminals. Include support for IBM SCLP line-mode terminals.
@ -65,7 +59,7 @@ config SCLP_CONSOLE
config SCLP_VT220_TTY config SCLP_VT220_TTY
bool "Support for SCLP VT220-compatible terminal" bool "Support for SCLP VT220-compatible terminal"
depends on SCLP depends on S390
help help
Include support for an IBM SCLP VT220-compatible terminal. Include support for an IBM SCLP VT220-compatible terminal.
@ -78,7 +72,7 @@ config SCLP_VT220_CONSOLE
config SCLP_CPI config SCLP_CPI
tristate "Control-Program Identification" tristate "Control-Program Identification"
depends on SCLP depends on S390
help help
This option enables the hardware console interface for system This option enables the hardware console interface for system
identification. This is commonly used for workload management and identification. This is commonly used for workload management and

View File

@ -147,8 +147,7 @@ raw3270_request_alloc(size_t size)
* Allocate a new 3270 ccw request from bootmem. Only works very * Allocate a new 3270 ccw request from bootmem. Only works very
* early in the boot process. Only con3270.c should be using this. * early in the boot process. Only con3270.c should be using this.
*/ */
struct raw3270_request * struct raw3270_request __init *raw3270_request_alloc_bootmem(size_t size)
raw3270_request_alloc_bootmem(size_t size)
{ {
struct raw3270_request *rq; 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. * Setup 3270 device configured as console.
*/ */
struct raw3270 * struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
raw3270_setup_console(struct ccw_device *cdev)
{ {
struct raw3270 *rp; struct raw3270 *rp;
char *ascebc; char *ascebc;

View File

@ -621,11 +621,24 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
/* /*
* Initialize all relevant components and register driver with system. * Initialize all relevant components and register driver with system.
*/ */
static int static void __init __sclp_vt220_cleanup(void)
__sclp_vt220_init(int early) {
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; void *page;
int i; int i;
int num_pages;
if (sclp_vt220_initialized) if (sclp_vt220_initialized)
return 0; return 0;
@ -642,13 +655,16 @@ __sclp_vt220_init(int early)
sclp_vt220_flush_later = 0; sclp_vt220_flush_later = 0;
/* Allocate pages for output buffering */ /* Allocate pages for output buffering */
for (i = 0; i < (early ? MAX_CONSOLE_PAGES : MAX_KMEM_PAGES); i++) { num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
if (early) for (i = 0; i < num_pages; i++) {
page = alloc_bootmem_low_pages(PAGE_SIZE); if (slab_is_available())
else
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 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; return -ENOMEM;
}
list_add_tail((struct list_head *) page, &sclp_vt220_empty); list_add_tail((struct list_head *) page, &sclp_vt220_empty);
} }
return 0; return 0;
@ -662,14 +678,13 @@ static const struct tty_operations sclp_vt220_ops = {
.flush_chars = sclp_vt220_flush_chars, .flush_chars = sclp_vt220_flush_chars,
.write_room = sclp_vt220_write_room, .write_room = sclp_vt220_write_room,
.chars_in_buffer = sclp_vt220_chars_in_buffer, .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. * Register driver with SCLP and Linux and initialize internal tty structures.
*/ */
static int __init static int __init sclp_vt220_tty_init(void)
sclp_vt220_tty_init(void)
{ {
struct tty_driver *driver; struct tty_driver *driver;
int rc; int rc;
@ -679,18 +694,15 @@ sclp_vt220_tty_init(void)
driver = alloc_tty_driver(1); driver = alloc_tty_driver(1);
if (!driver) if (!driver)
return -ENOMEM; return -ENOMEM;
rc = __sclp_vt220_init(0); rc = __sclp_vt220_init();
if (rc) { if (rc)
put_tty_driver(driver); goto out_driver;
return rc;
}
rc = sclp_register(&sclp_vt220_register); rc = sclp_register(&sclp_vt220_register);
if (rc) { if (rc) {
printk(KERN_ERR SCLP_VT220_PRINT_HEADER printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - " "could not register tty - "
"sclp_register returned %d\n", rc); "sclp_register returned %d\n", rc);
put_tty_driver(driver); goto out_init;
return rc;
} }
driver->owner = THIS_MODULE; driver->owner = THIS_MODULE;
@ -709,14 +721,20 @@ sclp_vt220_tty_init(void)
printk(KERN_ERR SCLP_VT220_PRINT_HEADER printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - " "could not register tty - "
"tty_register_driver returned %d\n", rc); "tty_register_driver returned %d\n", rc);
put_tty_driver(driver); goto out_sclp;
return rc;
} }
sclp_vt220_driver = driver; sclp_vt220_driver = driver;
return 0; 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 #ifdef CONFIG_SCLP_VT220_CONSOLE
@ -762,7 +780,7 @@ sclp_vt220_con_init(void)
if (!CONSOLE_IS_SCLP) if (!CONSOLE_IS_SCLP)
return 0; return 0;
rc = __sclp_vt220_init(1); rc = __sclp_vt220_init();
if (rc) if (rc)
return rc; return rc;
/* Attach linux console */ /* Attach linux console */

View File

@ -486,7 +486,7 @@ static ssize_t diag14_read(struct file *file, char __user *ubuf, size_t count,
} }
if (rc) if (rc)
goto fail; goto fail;
if (reclen) if (reclen && (copied == 0) && (*offs < PAGE_SIZE))
*((u16 *) &buf[FILE_RECLEN_OFFSET]) = reclen; *((u16 *) &buf[FILE_RECLEN_OFFSET]) = reclen;
len = min(count - copied, PAGE_SIZE - res); len = min(count - copied, PAGE_SIZE - res);
if (copy_to_user(ubuf + copied, buf + res, len)) { if (copy_to_user(ubuf + copied, buf + res, len)) {

View File

@ -51,7 +51,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to,
to = from; to = from;
if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) { 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", "0.%x.%04x to 0.%x.%04x, skipping\n",
ssid, from, ssid, to); ssid, from, ssid, to);
return; return;
@ -119,7 +119,7 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno)
return 0; return 0;
confused: confused:
strsep(str, ",\n"); 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; return 1;
} }
@ -166,22 +166,19 @@ blacklist_parse_parameters (char *str, range_action action)
continue; continue;
} }
if (*str == '-') { if (*str == '-') {
printk(KERN_WARNING "invalid cio_ignore " printk(KERN_WARNING "cio: invalid cio_ignore "
"parameter '%s'\n", "parameter '%s'\n",
strsep(&str, ",\n")); strsep(&str, ",\n"));
continue; continue;
} }
if ((from_id0 != to_id0) || if ((from_id0 != to_id0) ||
(from_ssid != to_ssid)) { (from_ssid != to_ssid)) {
printk(KERN_WARNING "invalid cio_ignore range " printk(KERN_WARNING "cio: invalid cio_ignore "
"%x.%x.%04x-%x.%x.%04x\n", "range %x.%x.%04x-%x.%x.%04x\n",
from_id0, from_ssid, from, from_id0, from_ssid, from,
to_id0, to_ssid, to); to_id0, to_ssid, to);
continue; 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); blacklist_range (ra, from, to, to_ssid);
} }
} }
@ -239,7 +236,7 @@ blacklist_parse_proc_parameters (char *buf)
*/ */
blacklist_parse_parameters (buf + 4, add); blacklist_parse_parameters (buf + 4, add);
} else { } 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>," KERN_WARNING "try using 'free all|<devno-range>,"
"<devno-range>,...'\n" "<devno-range>,...'\n"
KERN_WARNING "or 'add <devno-range>," KERN_WARNING "or 'add <devno-range>,"

View File

@ -359,7 +359,6 @@ ccwgroup_probe (struct device *dev)
if ((ret = device_create_file(dev, &dev_attr_online))) if ((ret = device_create_file(dev, &dev_attr_online)))
return ret; return ret;
pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id);
ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV; ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
if (ret) if (ret)
device_remove_file(dev, &dev_attr_online); device_remove_file(dev, &dev_attr_online);
@ -376,8 +375,6 @@ ccwgroup_remove (struct device *dev)
gdev = to_ccwgroupdev(dev); gdev = to_ccwgroupdev(dev);
gdrv = to_ccwgroupdrv(dev->driver); gdrv = to_ccwgroupdrv(dev->driver);
pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id);
device_remove_file(dev, &dev_attr_online); device_remove_file(dev, &dev_attr_online);
if (gdrv && gdrv->remove) if (gdrv && gdrv->remove)

View File

@ -121,14 +121,8 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
CIO_TRACE_EVENT( 2, dbf_text); CIO_TRACE_EVENT( 2, dbf_text);
status = chp_get_status(chpid); 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) { 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); chpid.cssid, chpid.id);
return -EINVAL; return -EINVAL;
} }
@ -421,21 +415,14 @@ int chp_new(struct chp_id chpid)
if (ret) if (ret)
goto out_free; goto out_free;
} else { } else {
static int msg_done;
if (!msg_done) {
printk(KERN_WARNING "cio: Channel measurements not "
"available, continuing.\n");
msg_done = 1;
}
chp->cmg = -1; chp->cmg = -1;
} }
/* make it known to the system */ /* make it known to the system */
ret = device_register(&chp->dev); ret = device_register(&chp->dev);
if (ret) { if (ret) {
printk(KERN_WARNING "%s: could not register %x.%02x\n", CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n",
__func__, chpid.cssid, chpid.id); chpid.cssid, chpid.id, ret);
goto out_free; goto out_free;
} }
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);

View File

@ -990,16 +990,20 @@ out:
return ret; return ret;
} }
static int __init int __init chsc_alloc_sei_area(void)
chsc_alloc_sei_area(void)
{ {
sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!sei_page) if (!sei_page)
printk(KERN_WARNING"Can't allocate page for processing of " \ CIO_MSG_EVENT(0, "Can't allocate page for processing of "
"chsc machine checks!\n"); "chsc machine checks!\n");
return (sei_page ? 0 : -ENOMEM); return (sei_page ? 0 : -ENOMEM);
} }
void __init chsc_free_sei_area(void)
{
kfree(sei_page);
}
int __init int __init
chsc_enable_facility(int operation_code) chsc_enable_facility(int operation_code)
{ {
@ -1051,8 +1055,6 @@ chsc_enable_facility(int operation_code)
return ret; return ret;
} }
subsys_initcall(chsc_alloc_sei_area);
struct css_general_char css_general_characteristics; struct css_general_char css_general_characteristics;
struct css_chsc_char css_chsc_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); scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!scsc_area) { if (!scsc_area) {
printk(KERN_WARNING"cio: Was not able to determine available" \ CIO_MSG_EVENT(0, "Was not able to determine available"
"CHSCs due to no memory.\n"); "CHSCs due to no memory.\n");
return -ENOMEM; return -ENOMEM;
} }
@ -1083,15 +1085,15 @@ chsc_determine_css_characteristics(void)
result = chsc(scsc_area); result = chsc(scsc_area);
if (result) { if (result) {
printk(KERN_WARNING"cio: Was not able to determine " \ CIO_MSG_EVENT(0, "Was not able to determine available CHSCs, "
"available CHSCs, cc=%i.\n", result); "cc=%i.\n", result);
result = -EIO; result = -EIO;
goto exit; goto exit;
} }
if (scsc_area->response.code != 1) { if (scsc_area->response.code != 1) {
printk(KERN_WARNING"cio: Was not able to determine " \ CIO_MSG_EVENT(0, "Was not able to determine "
"available CHSCs.\n"); "available CHSCs.\n");
result = -EIO; result = -EIO;
goto exit; goto exit;
} }

View File

@ -79,6 +79,8 @@ extern int chsc_get_ssd_info(struct subchannel_id schid,
struct chsc_ssd_info *ssd); struct chsc_ssd_info *ssd);
extern int chsc_determine_css_characteristics(void); extern int chsc_determine_css_characteristics(void);
extern int css_characteristics_avail; 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); extern int chsc_enable_facility(int);
struct channel_subsystem; struct channel_subsystem;

View File

@ -47,8 +47,8 @@ cio_setup (char *parm)
else if (!strcmp (parm, "no")) else if (!strcmp (parm, "no"))
cio_show_msg = 0; cio_show_msg = 0;
else else
printk (KERN_ERR "cio_setup : invalid cio_msg parameter '%s'", printk(KERN_ERR "cio: cio_setup: "
parm); "invalid cio_msg parameter '%s'", parm);
return 1; return 1;
} }
@ -80,7 +80,6 @@ cio_debug_init (void)
goto out_unregister; goto out_unregister;
debug_register_view (cio_debug_crw_id, &debug_sprintf_view); debug_register_view (cio_debug_crw_id, &debug_sprintf_view);
debug_set_level (cio_debug_crw_id, 2); debug_set_level (cio_debug_crw_id, 2);
pr_debug("debugging initialized\n");
return 0; return 0;
out_unregister: out_unregister:
@ -90,7 +89,7 @@ out_unregister:
debug_unregister (cio_debug_trace_id); debug_unregister (cio_debug_trace_id);
if (cio_debug_crw_id) if (cio_debug_crw_id)
debug_unregister (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; return -1;
} }
@ -568,7 +567,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
*/ */
if (sch->st != 0) { if (sch->st != 0) {
CIO_DEBUG(KERN_INFO, 0, CIO_DEBUG(KERN_INFO, 0,
"Subchannel 0.%x.%04x reports " "cio: Subchannel 0.%x.%04x reports "
"non-I/O subchannel type %04X\n", "non-I/O subchannel type %04X\n",
sch->schid.ssid, sch->schid.sch_no, sch->st); sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */ /* 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; sch->lpm = sch->schib.pmcw.pam & sch->opm;
CIO_DEBUG(KERN_INFO, 0, 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", " - PIM = %02X, PAM = %02X, POM = %02X\n",
sch->schib.pmcw.dev, sch->schid.ssid, sch->schib.pmcw.dev, sch->schid.ssid,
sch->schid.sch_no, sch->schib.pmcw.pim, 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 /* unlike in 2.4, we cannot autoprobe here, since
* the channel subsystem is not fully initialized. * the channel subsystem is not fully initialized.
* With some luck, the HWC console can take over */ * 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 -1;
} }
return console_irq; return console_irq;

View File

@ -23,6 +23,8 @@ extern debug_info_t *cio_debug_crw_id;
static inline void static inline void
CIO_HEX_EVENT(int level, void *data, int length) CIO_HEX_EVENT(int level, void *data, int length)
{ {
if (unlikely(!cio_debug_trace_id))
return;
while (length > 0) { while (length > 0) {
debug_event(cio_debug_trace_id, level, data, length); debug_event(cio_debug_trace_id, level, data, length);
length -= cio_debug_trace_id->buf_size; length -= cio_debug_trace_id->buf_size;

View File

@ -1185,12 +1185,12 @@ static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *att
case '0': case '0':
ret = disable_cmf(cdev); ret = disable_cmf(cdev);
if (ret) if (ret)
printk(KERN_INFO "disable_cmf failed (%d)\n", ret); dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
break; break;
case '1': case '1':
ret = enable_cmf(cdev); ret = enable_cmf(cdev);
if (ret && ret != -EBUSY) if (ret && ret != -EBUSY)
printk(KERN_INFO "enable_cmf failed (%d)\n", ret); dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret);
break; break;
} }
@ -1280,10 +1280,10 @@ init_cmf(void)
format_string = "basic"; format_string = "basic";
cmbops = &cmbops_basic; cmbops = &cmbops_basic;
if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) { if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) {
printk(KERN_ERR "Basic channel measurement facility" printk(KERN_ERR "cio: Basic channel measurement "
" can only use 1 to 4096 devices\n" "facility can only use 1 to 4096 devices\n"
KERN_ERR "when the cmf driver is built" KERN_ERR "when the cmf driver is built"
" as a loadable module\n"); " as a loadable module\n");
return 1; return 1;
} }
break; break;
@ -1292,13 +1292,13 @@ init_cmf(void)
cmbops = &cmbops_extended; cmbops = &cmbops_extended;
break; break;
default: default:
printk(KERN_ERR "Invalid format %d for channel " printk(KERN_ERR "cio: Invalid format %d for channel "
"measurement facility\n", format); "measurement facility\n", format);
return 1; return 1;
} }
printk(KERN_INFO "Channel measurement facility using %s format (%s)\n", printk(KERN_INFO "cio: Channel measurement facility using %s "
format_string, detect_string); "format (%s)\n", format_string, detect_string);
return 0; return 0;
} }

View File

@ -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; int ret;
@ -184,8 +184,8 @@ static int css_register_subchannel(struct subchannel *sch)
/* make it known to the system */ /* make it known to the system */
ret = css_sch_device_register(sch); ret = css_sch_device_register(sch);
if (ret) { if (ret) {
printk (KERN_WARNING "%s: could not register %s\n", CIO_MSG_EVENT(0, "Could not register sch 0.%x.%04x: %d\n",
__func__, sch->dev.bus_id); sch->schid.ssid, sch->schid.sch_no, ret);
return ret; return ret;
} }
return ret; return ret;
@ -371,15 +371,12 @@ static int __init slow_subchannel_init(void)
spin_lock_init(&slow_subchannel_lock); spin_lock_init(&slow_subchannel_lock);
slow_subchannel_set = idset_sch_new(); slow_subchannel_set = idset_sch_new();
if (!slow_subchannel_set) { if (!slow_subchannel_set) {
printk(KERN_WARNING "cio: could not allocate slow subchannel " CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n");
"set\n");
return -ENOMEM; return -ENOMEM;
} }
return 0; return 0;
} }
subsys_initcall(slow_subchannel_init);
static void css_slow_path_func(struct work_struct *unused) static void css_slow_path_func(struct work_struct *unused)
{ {
struct subchannel_id schid; struct subchannel_id schid;
@ -425,8 +422,8 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data)
struct subchannel *sch; struct subchannel *sch;
int ret; int ret;
CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n", CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n",
schid.ssid, schid.sch_no); schid.ssid, schid.sch_no);
if (need_reprobe) if (need_reprobe)
return -EAGAIN; return -EAGAIN;
@ -642,9 +639,20 @@ init_channel_subsystem (void)
{ {
int ret, i; 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; 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))) if ((ret = bus_register(&css_bus_type)))
goto out; goto out;
@ -710,6 +718,10 @@ out_unregister:
out_bus: out_bus:
bus_unregister(&css_bus_type); bus_unregister(&css_bus_type);
out: out:
chsc_free_sei_area();
kfree(slow_subchannel_set);
printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n",
ret);
return ret; return ret;
} }

View File

@ -139,7 +139,6 @@ struct css_driver {
*/ */
extern struct bus_type css_bus_type; extern struct bus_type css_bus_type;
extern int css_sch_device_register(struct subchannel *);
extern void css_sch_device_unregister(struct subchannel *); extern void css_sch_device_unregister(struct subchannel *);
extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done; extern int css_init_done;

View File

@ -338,15 +338,20 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
rc = device_schedule_callback(&cdev->dev, rc = device_schedule_callback(&cdev->dev,
ccw_device_remove_orphan_cb); ccw_device_remove_orphan_cb);
if (rc) 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; return;
} }
/* Deregister subchannel, which will kill the ccw device. */ /* Deregister subchannel, which will kill the ccw device. */
rc = device_schedule_callback(cdev->dev.parent, rc = device_schedule_callback(cdev->dev.parent,
ccw_device_remove_sch_cb); ccw_device_remove_sch_cb);
if (rc) if (rc)
dev_info(&cdev->dev, CIO_MSG_EVENT(2, "Couldn't unregister disconnected device "
"Couldn't unregister disconnected device\n"); "0.%x.%04x\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
} }
int int
@ -379,8 +384,10 @@ ccw_device_set_offline(struct ccw_device *cdev)
if (ret == 0) if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else { else {
pr_debug("ccw_device_offline returned %d, device %s\n", CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
ret, cdev->dev.bus_id); "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
cdev->online = 1; cdev->online = 1;
} }
return ret; return ret;
@ -402,8 +409,10 @@ ccw_device_set_online(struct ccw_device *cdev)
if (ret == 0) if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else { else {
pr_debug("ccw_device_online returned %d, device %s\n", CIO_MSG_EVENT(2, "ccw_device_online returned %d, "
ret, cdev->dev.bus_id); "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
return ret; return ret;
} }
if (cdev->private->state != DEV_STATE_ONLINE) if (cdev->private->state != DEV_STATE_ONLINE)
@ -417,9 +426,11 @@ ccw_device_set_online(struct ccw_device *cdev)
spin_unlock_irq(cdev->ccwlock); spin_unlock_irq(cdev->ccwlock);
if (ret == 0) if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else else
pr_debug("ccw_device_offline returned %d, device %s\n", CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
ret, cdev->dev.bus_id); "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
return (ret == 0) ? -ENODEV : ret; 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) { if (cdev->id.cu_type == 0) {
ret = ccw_device_recognition(cdev); ret = ccw_device_recognition(cdev);
if (ret) { if (ret) {
printk(KERN_WARNING"Couldn't start recognition " CIO_MSG_EVENT(0, "Couldn't start recognition "
"for device %s (ret=%d)\n", "for device 0.%x.%04x (ret=%d)\n",
cdev->dev.bus_id, ret); cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, ret);
return ret; return ret;
} }
wait_event(cdev->private->wait_q, 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) { if (force && cdev->private->state == DEV_STATE_BOXED) {
ret = ccw_device_stlck(cdev); ret = ccw_device_stlck(cdev);
if (ret) { if (ret) {
printk(KERN_WARNING"ccw_device_stlck for device %s " dev_warn(&cdev->dev,
"returned %d!\n", cdev->dev.bus_id, ret); "ccw_device_stlck returned %d!\n", ret);
return; return;
} }
if (cdev->id.cu_type == 0) if (cdev->id.cu_type == 0)
@ -893,8 +905,10 @@ io_subchannel_register(struct work_struct *work)
ret = device_reprobe(&cdev->dev); ret = device_reprobe(&cdev->dev);
if (ret) if (ret)
/* We can't do much here. */ /* We can't do much here. */
dev_info(&cdev->dev, "device_reprobe() returned" CIO_MSG_EVENT(2, "device_reprobe() returned"
" %d\n", ret); " %d for 0.%x.%04x\n", ret,
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
} }
goto out; goto out;
} }
@ -907,8 +921,9 @@ io_subchannel_register(struct work_struct *work)
/* make it known to the system */ /* make it known to the system */
ret = ccw_device_register(cdev); ret = ccw_device_register(cdev);
if (ret) { if (ret) {
printk (KERN_WARNING "%s: could not register %s\n", CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n",
__func__, cdev->dev.bus_id); cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, ret);
put_device(&cdev->dev); put_device(&cdev->dev);
spin_lock_irqsave(sch->lock, flags); spin_lock_irqsave(sch->lock, flags);
sch->dev.driver_data = NULL; sch->dev.driver_data = NULL;
@ -1361,7 +1376,6 @@ ccw_device_remove (struct device *dev)
struct ccw_driver *cdrv = cdev->drv; struct ccw_driver *cdrv = cdev->drv;
int ret; int ret;
pr_debug("removing device %s\n", cdev->dev.bus_id);
if (cdrv->remove) if (cdrv->remove)
cdrv->remove(cdev); cdrv->remove(cdev);
if (cdev->online) { if (cdev->online) {
@ -1374,8 +1388,10 @@ ccw_device_remove (struct device *dev)
dev_fsm_final_state(cdev)); dev_fsm_final_state(cdev));
else else
//FIXME: we can't fail! //FIXME: we can't fail!
pr_debug("ccw_device_offline returned %d, device %s\n", CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
ret, cdev->dev.bus_id); "device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
} }
ccw_device_set_timeout(cdev, 0); ccw_device_set_timeout(cdev, 0);
cdev->drv = NULL; cdev->drv = NULL;

View File

@ -268,7 +268,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
switch (state) { switch (state) {
case DEV_STATE_NOT_OPER: case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2, 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, "0.%x.%04x\n", cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no); sch->schid.ssid, sch->schid.sch_no);
break; break;
@ -293,7 +293,8 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
return; return;
} }
/* Issue device info message. */ /* 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 = " "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
"%04X/%02X\n", "%04X/%02X\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.ssid,
@ -303,7 +304,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
break; break;
case DEV_STATE_BOXED: case DEV_STATE_BOXED:
CIO_DEBUG(KERN_WARNING, 2, 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, "0.%x.%04x\n", cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no); sch->schid.ssid, sch->schid.sch_no);
break; break;
@ -388,7 +389,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED) if (state == DEV_STATE_BOXED)
CIO_DEBUG(KERN_WARNING, 2, 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); cdev->private->dev_id.devno, sch->schid.sch_no);
if (cdev->private->flags.donotify) { 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. */ /* Basic sense hasn't started. Try again. */
ccw_device_do_sense(cdev, irb); ccw_device_do_sense(cdev, irb);
else { else {
printk(KERN_INFO "Huh? %s(%s): unsolicited " CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited "
"interrupt...\n", "interrupt during w4sense...\n",
__FUNCTION__, cdev->dev.bus_id); cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
if (cdev->handler) if (cdev->handler)
cdev->handler (cdev, 0, irb); cdev->handler (cdev, 0, irb);
} }
@ -1215,8 +1217,8 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event)
static void static void
ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
{ {
printk(KERN_EMERG "dev_jumptable[%i][%i] == NULL\n", CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n",
cdev->private->state, dev_event); cdev->private->state, dev_event);
BUG(); BUG();
} }

View File

@ -288,253 +288,6 @@ ccw_device_get_path_mask(struct ccw_device *cdev)
return sch->lpm; 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. * 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; 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"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccw_device_set_options_mask); 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_start_key);
EXPORT_SYMBOL(ccw_device_get_ciw); EXPORT_SYMBOL(ccw_device_get_ciw);
EXPORT_SYMBOL(ccw_device_get_path_mask); 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_subchannel_number);
EXPORT_SYMBOL(_ccw_device_get_device_number);
EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc); EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
EXPORT_SYMBOL_GPL(read_conf_data_lpm);

View File

@ -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_halt(struct ccw_device *, unsigned long);
extern int ccw_device_clear(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_online(struct ccw_device *cdev);
extern int ccw_device_set_offline(struct ccw_device *cdev); extern int ccw_device_set_offline(struct ccw_device *cdev);

View File

@ -10,6 +10,8 @@
* Martin Schwidefsky (schwidefsky@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com)
*/ */
#include <linux/types.h>
typedef void (*ext_int_handler_t)(__u16 code); typedef void (*ext_int_handler_t)(__u16 code);
/* /*

View File

@ -36,8 +36,7 @@ extern void machine_halt_smp(void);
extern void machine_power_off_smp(void); extern void machine_power_off_smp(void);
extern void smp_setup_cpu_possible_map(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 */ #define NO_PROC_ID 0xFF /* No processor magic marker */
/* /*
@ -96,14 +95,6 @@ extern int __cpu_up (unsigned int cpu);
#endif #endif
#ifndef CONFIG_SMP #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) static inline void smp_send_stop(void)
{ {
/* Disable all interrupts/machine checks */ /* Disable all interrupts/machine checks */

View File

@ -251,7 +251,7 @@
#define __NR_getcpu 311 #define __NR_getcpu 311
#define __NR_epoll_pwait 312 #define __NR_epoll_pwait 312
#define __NR_utimes 313 #define __NR_utimes 313
/* Number 314 is reserved for new sys_fallocate */ #define __NR_fallocate 314
#define __NR_utimensat 315 #define __NR_utimensat 315
#define __NR_signalfd 316 #define __NR_signalfd 316
#define __NR_timerfd 317 #define __NR_timerfd 317

View File

@ -479,7 +479,8 @@ static void iucv_setmask_mp(void)
/* Enable all cpus with a declared buffer. */ /* Enable all cpus with a declared buffer. */
if (cpu_isset(cpu, iucv_buffer_cpumask) && if (cpu_isset(cpu, iucv_buffer_cpumask) &&
!cpu_isset(cpu, iucv_irq_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(); preempt_enable();
} }
@ -497,7 +498,7 @@ static void iucv_setmask_up(void)
cpumask = iucv_irq_cpumask; cpumask = iucv_irq_cpumask;
cpu_clear(first_cpu(iucv_irq_cpumask), cpumask); cpu_clear(first_cpu(iucv_irq_cpumask), cpumask);
for_each_cpu_mask(cpu, 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; rc = -EIO;
preempt_disable(); preempt_disable();
for_each_online_cpu(cpu) 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(); preempt_enable();
if (cpus_empty(iucv_buffer_cpumask)) if (cpus_empty(iucv_buffer_cpumask))
/* No cpu could declare an iucv buffer. */ /* 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_ONLINE_FROZEN:
case CPU_DOWN_FAILED: case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN: 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; break;
case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN: case CPU_DOWN_PREPARE_FROZEN:
@ -587,10 +588,10 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
if (cpus_empty(cpumask)) if (cpus_empty(cpumask))
/* Can't offline last IUCV enabled cpu. */ /* Can't offline last IUCV enabled cpu. */
return NOTIFY_BAD; 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)) if (cpus_empty(iucv_irq_cpumask))
smp_call_function_on(iucv_allow_cpu, NULL, 0, 1, smp_call_function_single(first_cpu(iucv_buffer_cpumask),
first_cpu(iucv_buffer_cpumask)); iucv_allow_cpu, NULL, 0, 1);
break; break;
} }
return NOTIFY_OK; return NOTIFY_OK;