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] remove __io_virt and mmiowb.
  [S390] cio: use ARRAY_SIZE in device_id.c
  [S390] cio: Fixup interface for setting options on ccw devices.
  [S390] smp_call_function/smp_call_function_on locking.
This commit is contained in:
Linus Torvalds 2007-02-12 09:57:44 -08:00
commit ebaf0c6032
6 changed files with 45 additions and 15 deletions

View file

@ -57,7 +57,7 @@ static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig);
/* /*
5B * Structure and data for smp_call_function(). This is designed to minimise * Structure and data for smp_call_function(). This is designed to minimise
* static memory requirements. It also looks cleaner. * static memory requirements. It also looks cleaner.
*/ */
static DEFINE_SPINLOCK(call_lock); static DEFINE_SPINLOCK(call_lock);
@ -104,7 +104,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
* remote CPUs are nearly ready to execute <<func>> or are or have executed. * remote CPUs are nearly ready to execute <<func>> or are or have executed.
* *
* You must not call this function with disabled interrupts or from a * You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler. * hardware interrupt handler.
*/ */
{ {
struct call_data_struct data; struct call_data_struct data;
@ -113,8 +113,8 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (cpus <= 0) if (cpus <= 0)
return 0; return 0;
/* Can deadlock when called with interrupts disabled */ /* Can deadlock when interrupts are disabled or if in wrong context */
WARN_ON(irqs_disabled()); WARN_ON(irqs_disabled() || in_irq());
data.func = func; data.func = func;
data.info = info; data.info = info;
@ -123,7 +123,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (wait) if (wait)
atomic_set(&data.finished, 0); atomic_set(&data.finished, 0);
spin_lock(&call_lock); spin_lock_bh(&call_lock);
call_data = &data; call_data = &data;
/* Send a message to all other CPUs and wait for them to respond */ /* Send a message to all other CPUs and wait for them to respond */
smp_ext_bitcall_others(ec_call_function); smp_ext_bitcall_others(ec_call_function);
@ -135,7 +135,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (wait) if (wait)
while (atomic_read(&data.finished) != cpus) while (atomic_read(&data.finished) != cpus)
cpu_relax(); cpu_relax();
spin_unlock(&call_lock); spin_unlock_bh(&call_lock);
return 0; return 0;
} }
@ -159,6 +159,9 @@ int smp_call_function_on(void (*func) (void *info), void *info,
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return -EINVAL; return -EINVAL;
/* Can deadlock when interrupts are disabled or if in wrong context */
WARN_ON(irqs_disabled() || in_irq());
/* disable preemption for local function call */ /* disable preemption for local function call */
curr_cpu = get_cpu(); curr_cpu = get_cpu();

View file

@ -11,6 +11,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/delay.h> #include <asm/delay.h>
@ -138,7 +139,7 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
ps->cu_model = 0x60; ps->cu_model = 0x60;
return; return;
} }
for (i = 0; i < sizeof(vm_devices) / sizeof(vm_devices[0]); i++) for (i = 0; i < ARRAY_SIZE(vm_devices); i++)
if (diag_data.vrdcvcla == vm_devices[i].vrdcvcla && if (diag_data.vrdcvcla == vm_devices[i].vrdcvcla &&
diag_data.vrdcvtyp == vm_devices[i].vrdcvtyp) { diag_data.vrdcvtyp == vm_devices[i].vrdcvtyp) {
ps->cu_type = vm_devices[i].cu_type; ps->cu_type = vm_devices[i].cu_type;

View file

@ -23,8 +23,7 @@
#include "chsc.h" #include "chsc.h"
#include "device.h" #include "device.h"
int int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
{ {
/* /*
* The flag usage is mutal exclusive ... * The flag usage is mutal exclusive ...
@ -39,6 +38,33 @@ ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
return 0; return 0;
} }
int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
{
/*
* The flag usage is mutal exclusive ...
*/
if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
(flags & CCWDEV_REPORT_ALL)) ||
((flags & CCWDEV_EARLY_NOTIFICATION) &&
cdev->private->options.repall) ||
((flags & CCWDEV_REPORT_ALL) &&
cdev->private->options.fast))
return -EINVAL;
cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
return 0;
}
void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
{
cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
}
int int
ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
{ {
@ -601,7 +627,9 @@ _ccw_device_get_device_number(struct ccw_device *cdev)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccw_device_set_options_mask);
EXPORT_SYMBOL(ccw_device_set_options); EXPORT_SYMBOL(ccw_device_set_options);
EXPORT_SYMBOL(ccw_device_clear_options);
EXPORT_SYMBOL(ccw_device_clear); EXPORT_SYMBOL(ccw_device_clear);
EXPORT_SYMBOL(ccw_device_halt); EXPORT_SYMBOL(ccw_device_halt);
EXPORT_SYMBOL(ccw_device_resume); EXPORT_SYMBOL(ccw_device_resume);

View file

@ -3194,7 +3194,7 @@ qdio_establish(struct qdio_initialize *init_data)
spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags); spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags);
ccw_device_set_options(cdev, 0); ccw_device_set_options_mask(cdev, 0);
result=ccw_device_start_timeout(cdev,&irq_ptr->ccw, result=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
QDIO_DOING_ESTABLISH,0, 0, QDIO_DOING_ESTABLISH,0, 0,
QDIO_ESTABLISH_TIMEOUT); QDIO_ESTABLISH_TIMEOUT);

View file

@ -110,7 +110,9 @@ extern void ccw_driver_unregister (struct ccw_driver *driver);
struct ccw1; struct ccw1;
extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long);
extern int ccw_device_set_options(struct ccw_device *, unsigned long); extern int ccw_device_set_options(struct ccw_device *, unsigned long);
extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
/* Allow for i/o completion notification after primary interrupt status. */ /* Allow for i/o completion notification after primary interrupt status. */
#define CCWDEV_EARLY_NOTIFICATION 0x0001 #define CCWDEV_EARLY_NOTIFICATION 0x0001

View file

@ -17,8 +17,6 @@
#define IO_SPACE_LIMIT 0xffffffff #define IO_SPACE_LIMIT 0xffffffff
#define __io_virt(x) ((void *)(PAGE_OFFSET | (unsigned long)(x)))
/* /*
* Change virtual addresses to physical addresses and vv. * Change virtual addresses to physical addresses and vv.
* These are pretty trivial * These are pretty trivial
@ -37,11 +35,9 @@ static inline unsigned long virt_to_phys(volatile void * address)
static inline void * phys_to_virt(unsigned long address) static inline void * phys_to_virt(unsigned long address)
{ {
return __io_virt(address); return (void *) address;
} }
#define mmiowb() do { } while (0)
/* /*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem * Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access * access