Auto merge with /home/aegl/GIT/linus

This commit is contained in:
Tony Luck 2005-06-21 16:21:20 -07:00
commit 29516d75a0
399 changed files with 8424 additions and 4069 deletions

View file

@ -338,7 +338,6 @@ X!Earch/i386/kernel/mca.c
X!Iinclude/linux/device.h
-->
!Edrivers/base/driver.c
!Edrivers/base/class_simple.c
!Edrivers/base/core.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c

View file

@ -76,6 +76,14 @@ driver_data: Driver-specific data.
platform_data: Platform data specific to the device.
Example: for devices on custom boards, as typical of embedded
and SOC based hardware, Linux often uses platform_data to point
to board-specific structures describing devices and how they
are wired. That can include what ports are available, chip
variants, which GPIO pins act in what additional roles, and so
on. This shrinks the "Board Support Packages" (BSPs) and
minimizes board-specific #ifdefs in drivers.
current_state: Current power state of the device.
saved_state: Pointer to saved state of the device. This is usable by

View file

@ -5,21 +5,17 @@ struct device_driver {
char * name;
struct bus_type * bus;
rwlock_t lock;
atomic_t refcount;
list_t bus_list;
struct completion unloaded;
struct kobject kobj;
list_t devices;
struct driver_dir_entry dir;
struct module *owner;
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
int (*resume) (struct device * dev, u32 level);
void (*release) (struct device_driver * drv);
};
@ -51,7 +47,6 @@ being converted completely to the new model.
static struct device_driver eepro100_driver = {
.name = "eepro100",
.bus = &pci_bus_type,
.devclass = &ethernet_devclass, /* when it's implemented */
.probe = eepro100_probe,
.remove = eepro100_remove,
@ -85,7 +80,6 @@ static struct pci_driver eepro100_driver = {
.driver = {
.name = "eepro100",
.bus = &pci_bus_type,
.devclass = &ethernet_devclass, /* when it's implemented */
.probe = eepro100_probe,
.remove = eepro100_remove,
.suspend = eepro100_suspend,
@ -166,27 +160,32 @@ Callbacks
int (*probe) (struct device * dev);
probe is called to verify the existence of a certain type of
hardware. This is called during the driver binding process, after the
bus has verified that the device ID of a device matches one of the
device IDs supported by the driver.
The probe() entry is called in task context, with the bus's rwsem locked
and the driver partially bound to the device. Drivers commonly use
container_of() to convert "dev" to a bus-specific type, both in probe()
and other routines. That type often provides device resource data, such
as pci_dev.resource[] or platform_device.resources, which is used in
addition to dev->platform_data to initialize the driver.
This callback only verifies that there actually is supported hardware
present. It may allocate a driver-specific structure, but it should
not do any initialization of the hardware itself. The device-specific
structure may be stored in the device's driver_data field.
This callback holds the driver-specific logic to bind the driver to a
given device. That includes verifying that the device is present, that
it's a version the driver can handle, that driver data structures can
be allocated and initialized, and that any hardware can be initialized.
Drivers often store a pointer to their state with dev_set_drvdata().
When the driver has successfully bound itself to that device, then probe()
returns zero and the driver model code will finish its part of binding
the driver to that device.
int (*init) (struct device * dev);
init is called during the binding stage. It is called after probe has
successfully returned and the device has been registered with its
class. It is responsible for initializing the hardware.
A driver's probe() may return a negative errno value to indicate that
the driver did not bind to this device, in which case it should have
released all reasources it allocated.
int (*remove) (struct device * dev);
remove is called to dissociate a driver with a device. This may be
remove is called to unbind a driver from a device. This may be
called if a device is physically removed from the system, if the
driver module is being unloaded, or during a reboot sequence.
driver module is being unloaded, during a reboot sequence, or
in other cases.
It is up to the driver to determine if the device is present or
not. It should free any resources allocated specifically for the

View file

@ -214,7 +214,7 @@ Other notes:
A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device * dev, char * buf)
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%s\n",dev->name);
}

View file

@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK
config GENERIC_ISA_DMA
bool
config GENERIC_IOMAP
bool
default y
config FIQ
bool
@ -202,6 +198,11 @@ config ARCH_H720X
help
This enables support for systems based on the Hynix HMS720x
config ARCH_AAEC2000
bool "Agilent AAEC-2000 based"
help
This enables support for systems based on the Agilent AAEC-2000
endchoice
source "arch/arm/mach-clps711x/Kconfig"
@ -234,6 +235,8 @@ source "arch/arm/mach-h720x/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
source "arch/arm/mach-aaec2000/Kconfig"
# Definitions to make life easier
config ARCH_ACORN
bool
@ -277,7 +280,7 @@ config ISA_DMA_API
default y
config PCI
bool "PCI support" if ARCH_INTEGRATOR_AP
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside

View file

@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_IMX) := imx
machine-$(CONFIG_ARCH_H720X) := h720x
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.

View file

@ -169,7 +169,7 @@ static void amba_device_release(struct device *dev)
}
#define amba_attr(name,fmt,arg...) \
static ssize_t show_##name(struct device *_dev, char *buf) \
static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf) \
{ \
struct amba_device *dev = to_amba_device(_dev); \
return sprintf(buf, fmt, arg); \

View file

@ -30,6 +30,8 @@
#include <linux/dmapool.h>
#include <linux/list.h>
#include <asm/cacheflush.h>
#undef DEBUG
#undef STATS
@ -302,12 +304,24 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
DO_STATS ( device_info->bounce_count++ );
if ((dir == DMA_FROM_DEVICE) ||
(dir == DMA_BIDIRECTIONAL)) {
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
unsigned long ptr;
dev_dbg(dev,
"%s: copy back safe %p to unsafe %p size %d\n",
__func__, buf->safe, buf->ptr, size);
memcpy(buf->ptr, buf->safe, size);
/*
* DMA buffers must have the same cache properties
* as if they were really used for DMA - which means
* data must be written back to RAM. Note that
* we don't use dmac_flush_range() here for the
* bidirectional case because we know the cache
* lines will be coherent with the data written.
*/
ptr = (unsigned long)buf->ptr;
dmac_clean_range(ptr, ptr + size);
}
free_safe_buffer(device_info, buf);
}

View file

@ -22,7 +22,7 @@
* them early in the boot process, then pass them to the appropriate drivers.
* Not all devices use all paramaters but the format is common to all.
*/
#ifdef ARCH_SA1100
#ifdef CONFIG_ARCH_SA1100
#define PARAM_BASE 0xe8ffc000
#else
#define PARAM_BASE 0xa0000a00

View file

@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type

View file

@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type

View file

@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type

View file

@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type

View file

@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type

View file

@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
# Object file lists.
obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \
obj-y := compat.o dma.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o

View file

@ -1,46 +0,0 @@
/*
* linux/arch/arm/kernel/arch.c
*
* Architecture specific fixups.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/types.h>
#include <asm/elf.h>
#include <asm/page.h>
#include <asm/setup.h>
#include <asm/mach/arch.h>
unsigned int vram_size;
#ifdef CONFIG_ARCH_ACORN
unsigned int memc_ctrl_reg;
unsigned int number_mfm_drives;
static int __init parse_tag_acorn(const struct tag *tag)
{
memc_ctrl_reg = tag->u.acorn.memc_control_reg;
number_mfm_drives = tag->u.acorn.adfsdrives;
switch (tag->u.acorn.vram_pages) {
case 512:
vram_size += PAGE_SIZE * 256;
case 256:
vram_size += PAGE_SIZE * 256;
default:
break;
}
#if 0
if (vram_size) {
desc->video_start = 0x02000000;
desc->video_end = 0x02000000 + vram_size;
}
#endif
return 0;
}
__tagtable(ATAG_ACORN, parse_tag_acorn);
#endif

View file

@ -866,19 +866,19 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
return ec;
}
static ssize_t ecard_show_irq(struct device *dev, char *buf)
static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->irq);
}
static ssize_t ecard_show_dma(struct device *dev, char *buf)
static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma);
}
static ssize_t ecard_show_resources(struct device *dev, char *buf)
static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
char *str = buf;
@ -893,19 +893,19 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
return str - buf;
}
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer);
}
static ssize_t ecard_show_device(struct device *dev, char *buf)
static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product);
}
static ssize_t ecard_show_type(struct device *dev, char *buf)
static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");

View file

@ -145,7 +145,8 @@ int __init __cpu_up(unsigned int cpu)
pgd_free(pgd);
if (ret) {
printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
/*
* FIXME: We need to clean up the new idle thread. --rmk
*/

View file

@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
DItype
__ashldi3 (DItype u, word_type b)
s64 __ashldi3(s64 u, int b)
{
DIunion w;
word_type bm;
DIunion uu;
DIunion w;
int bm;
DIunion uu;
if (b == 0)
return u;
if (b == 0)
return u;
uu.ll = u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.low = 0;
w.s.high = (USItype)uu.s.low << -bm;
}
else
{
USItype carries = (USItype)uu.s.low >> bm;
w.s.low = (USItype)uu.s.low << b;
w.s.high = ((USItype)uu.s.high << b) | carries;
}
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
if (bm <= 0) {
w.s.low = 0;
w.s.high = (u32) uu.s.low << -bm;
} else {
u32 carries = (u32) uu.s.low >> bm;
w.s.low = (u32) uu.s.low << b;
w.s.high = ((u32) uu.s.high << b) | carries;
}
return w.ll;
return w.ll;
}

View file

@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
DItype
__ashrdi3 (DItype u, word_type b)
s64 __ashrdi3(s64 u, int b)
{
DIunion w;
word_type bm;
DIunion uu;
DIunion w;
int bm;
DIunion uu;
if (b == 0)
return u;
if (b == 0)
return u;
uu.ll = u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
if (bm <= 0) {
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
} else {
u32 carries = (u32) uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((u32) uu.s.low >> b) | carries;
}
return w.ll;
return w.ll;
}

View file

@ -1,25 +1,22 @@
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
/* I Molton 29/07/01 */
#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#include <linux/types.h>
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT)
#ifdef __ARMEB__
struct DIstruct {SItype high, low;};
struct DIstruct {
s32 high, low;
};
#else
struct DIstruct {SItype low, high;};
struct DIstruct {
s32 low, high;
};
#endif
typedef union
{
struct DIstruct s;
DItype ll;
typedef union {
struct DIstruct s;
s64 ll;
} DIunion;

View file

@ -26,18 +26,18 @@
#define __BITS4 (SI_TYPE_SIZE / 4)
#define __ll_B (1L << (SI_TYPE_SIZE / 2))
#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
#define __ll_highpart(t) ((USItype) (t) / __ll_B)
#define __ll_lowpart(t) ((u32) (t) % __ll_B)
#define __ll_highpart(t) ((u32) (t) / __ll_B)
/* Define auxiliary asm macros.
1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
multiplies two USItype integers MULTIPLER and MULTIPLICAND,
and generates a two-part USItype product in HIGH_PROD and
multiplies two u32 integers MULTIPLER and MULTIPLICAND,
and generates a two-part u32 product in HIGH_PROD and
LOW_PROD.
2) __umulsidi3(a,b) multiplies two USItype integers A and B,
and returns a UDItype product. This is just a variant of umul_ppmm.
2) __umulsidi3(a,b) multiplies two u32 integers A and B,
and returns a u64 product. This is just a variant of umul_ppmm.
3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
denominator) divides a two-word unsigned integer, composed by the
@ -77,23 +77,23 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("adds %1, %4, %5 \n\
adc %0, %2, %3" \
: "=r" ((USItype) (sh)), \
"=&r" ((USItype) (sl)) \
: "%r" ((USItype) (ah)), \
"rI" ((USItype) (bh)), \
"%r" ((USItype) (al)), \
"rI" ((USItype) (bl)))
: "=r" ((u32) (sh)), \
"=&r" ((u32) (sl)) \
: "%r" ((u32) (ah)), \
"rI" ((u32) (bh)), \
"%r" ((u32) (al)), \
"rI" ((u32) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subs %1, %4, %5 \n\
sbc %0, %2, %3" \
: "=r" ((USItype) (sh)), \
"=&r" ((USItype) (sl)) \
: "r" ((USItype) (ah)), \
"rI" ((USItype) (bh)), \
"r" ((USItype) (al)), \
"rI" ((USItype) (bl)))
: "=r" ((u32) (sh)), \
"=&r" ((u32) (sl)) \
: "r" ((u32) (ah)), \
"rI" ((u32) (bh)), \
"r" ((u32) (al)), \
"rI" ((u32) (bl)))
#define umul_ppmm(xh, xl, a, b) \
{register USItype __t0, __t1, __t2; \
{register u32 __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm \n\
mov %2, %5, lsr #16 \n\
mov %0, %6, lsr #16 \n\
@ -107,14 +107,14 @@
addcs %0, %0, #65536 \n\
adds %1, %1, %3, lsl #16 \n\
adc %0, %0, %3, lsr #16" \
: "=&r" ((USItype) (xh)), \
"=r" ((USItype) (xl)), \
: "=&r" ((u32) (xh)), \
"=r" ((u32) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
: "r" ((USItype) (a)), \
"r" ((USItype) (b)));}
: "r" ((u32) (a)), \
"r" ((u32) (b)));}
#define UMUL_TIME 20
#define UDIV_TIME 100
#endif /* __arm__ */
#endif /* __arm__ */
#define __umulsidi3(u, v) \
({DIunion __w; \
@ -123,14 +123,14 @@
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
do { \
USItype __d1, __d0, __q1, __q0; \
USItype __r1, __r0, __m; \
u32 __d1, __d0, __q1, __q0; \
u32 __r1, __r0, __m; \
__d1 = __ll_highpart (d); \
__d0 = __ll_lowpart (d); \
\
__r1 = (n1) % __d1; \
__q1 = (n1) / __d1; \
__m = (USItype) __q1 * __d0; \
__m = (u32) __q1 * __d0; \
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
if (__r1 < __m) \
{ \
@ -143,7 +143,7 @@
\
__r0 = __r1 % __d1; \
__q0 = __r1 / __d1; \
__m = (USItype) __q0 * __d0; \
__m = (u32) __q0 * __d0; \
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
if (__r0 < __m) \
{ \
@ -154,7 +154,7 @@
} \
__r0 -= __m; \
\
(q) = (USItype) __q1 * __ll_B | __q0; \
(q) = (u32) __q1 * __ll_B | __q0; \
(r) = __r0; \
} while (0)
@ -163,14 +163,14 @@
#define count_leading_zeros(count, x) \
do { \
USItype __xr = (x); \
USItype __a; \
u32 __xr = (x); \
u32 __a; \
\
if (SI_TYPE_SIZE <= 32) \
{ \
__a = __xr < ((USItype)1<<2*__BITS4) \
? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
: (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
__a = __xr < ((u32)1<<2*__BITS4) \
? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4) \
: (__xr < ((u32)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
} \
else \
{ \

View file

@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
DItype
__lshrdi3 (DItype u, word_type b)
s64 __lshrdi3(s64 u, int b)
{
DIunion w;
word_type bm;
DIunion uu;
DIunion w;
int bm;
DIunion uu;
if (b == 0)
return u;
if (b == 0)
return u;
uu.ll = u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = 0;
w.s.low = (USItype)uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = (USItype)uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
if (bm <= 0) {
w.s.high = 0;
w.s.low = (u32) uu.s.high >> -bm;
} else {
u32 carries = (u32) uu.s.high << bm;
w.s.high = (u32) uu.s.high >> b;
w.s.low = ((u32) uu.s.low >> b) | carries;
}
return w.ll;
return w.ll;
}

View file

@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
#define umul_ppmm(xh, xl, a, b) \
{register USItype __t0, __t1, __t2; \
{register u32 __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm \n\
mov %2, %5, lsr #16 \n\
mov %0, %6, lsr #16 \n\
@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA. */
addcs %0, %0, #65536 \n\
adds %1, %1, %3, lsl #16 \n\
adc %0, %0, %3, lsr #16" \
: "=&r" ((USItype) (xh)), \
"=r" ((USItype) (xl)), \
: "=&r" ((u32) (xh)), \
"=r" ((u32) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
: "r" ((USItype) (a)), \
"r" ((USItype) (b)));}
: "r" ((u32) (a)), \
"r" ((u32) (b)));}
#define __umulsidi3(u, v) \
({DIunion __w; \
umul_ppmm (__w.s.high, __w.s.low, u, v); \
__w.ll; })
DItype
__muldi3 (DItype u, DItype v)
s64 __muldi3(s64 u, s64 v)
{
DIunion w;
DIunion uu, vv;
DIunion w;
DIunion uu, vv;
uu.ll = u,
vv.ll = v;
uu.ll = u, vv.ll = v;
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ (USItype) uu.s.high * (USItype) vv.s.low);
w.ll = __umulsidi3(uu.s.low, vv.s.low);
w.s.high += ((u32) uu.s.low * (u32) vv.s.high
+ (u32) uu.s.high * (u32) vv.s.low);
return w.ll;
return w.ll;
}

View file

@ -31,21 +31,19 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
word_type
__ucmpdi2 (DItype a, DItype b)
int __ucmpdi2(s64 a, s64 b)
{
DIunion au, bu;
DIunion au, bu;
au.ll = a, bu.ll = b;
au.ll = a, bu.ll = b;
if ((USItype) au.s.high < (USItype) bu.s.high)
return 0;
else if ((USItype) au.s.high > (USItype) bu.s.high)
return 2;
if ((USItype) au.s.low < (USItype) bu.s.low)
return 0;
else if ((USItype) au.s.low > (USItype) bu.s.low)
return 2;
return 1;
if ((u32) au.s.high < (u32) bu.s.high)
return 0;
else if ((u32) au.s.high > (u32) bu.s.high)
return 2;
if ((u32) au.s.low < (u32) bu.s.low)
return 0;
else if ((u32) au.s.low > (u32) bu.s.low)
return 2;
return 1;
}

View file

@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
#include "longlong.h"
static const UQItype __clz_tab[] =
{
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
static const u8 __clz_tab[] = {
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
};
UDItype
__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
{
DIunion ww;
DIunion nn, dd;
DIunion rr;
USItype d0, d1, n0, n1, n2;
USItype q0, q1;
USItype b, bm;
DIunion ww;
DIunion nn, dd;
DIunion rr;
u32 d0, d1, n0, n1, n2;
u32 q0, q1;
u32 b, bm;
nn.ll = n;
dd.ll = d;
nn.ll = n;
dd.ll = d;
d0 = dd.s.low;
d1 = dd.s.high;
n0 = nn.s.low;
n1 = nn.s.high;
d0 = dd.s.low;
d1 = dd.s.high;
n0 = nn.s.low;
n1 = nn.s.high;
if (d1 == 0)
{
if (d0 > n1)
{
/* 0q = nn / 0D */
if (d1 == 0) {
if (d0 > n1) {
/* 0q = nn / 0D */
count_leading_zeros (bm, d0);
count_leading_zeros(bm, d0);
if (bm != 0)
{
/* Normalize, i.e. make the most significant bit of the
denominator set. */
if (bm != 0) {
/* Normalize, i.e. make the most significant bit of the
denominator set. */
d0 = d0 << bm;
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
n0 = n0 << bm;
}
d0 = d0 << bm;
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
n0 = n0 << bm;
}
udiv_qrnnd (q0, n0, n1, n0, d0);
q1 = 0;
udiv_qrnnd(q0, n0, n1, n0, d0);
q1 = 0;
/* Remainder in n0 >> bm. */
}
else
{
/* qq = NN / 0d */
/* Remainder in n0 >> bm. */
} else {
/* qq = NN / 0d */
if (d0 == 0)
d0 = 1 / d0; /* Divide intentionally by zero. */
if (d0 == 0)
d0 = 1 / d0; /* Divide intentionally by zero. */
count_leading_zeros (bm, d0);
count_leading_zeros(bm, d0);
if (bm == 0)
{
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
conclude (the most significant bit of n1 is set) /\ (the
leading quotient digit q1 = 1).
if (bm == 0) {
/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
conclude (the most significant bit of n1 is set) /\ (the
leading quotient digit q1 = 1).
This special case is necessary, not an optimization.
(Shifts counts of SI_TYPE_SIZE are undefined.) */
This special case is necessary, not an optimization.
(Shifts counts of SI_TYPE_SIZE are undefined.) */
n1 -= d0;
q1 = 1;
}
else
{
/* Normalize. */
n1 -= d0;
q1 = 1;
} else {
/* Normalize. */
b = SI_TYPE_SIZE - bm;
b = SI_TYPE_SIZE - bm;
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
udiv_qrnnd (q1, n1, n2, n1, d0);
}
udiv_qrnnd(q1, n1, n2, n1, d0);
}
/* n1 != d0... */
/* n1 != d0... */
udiv_qrnnd (q0, n0, n1, n0, d0);
udiv_qrnnd(q0, n0, n1, n0, d0);
/* Remainder in n0 >> bm. */
}
/* Remainder in n0 >> bm. */
}
if (rp != 0)
{
rr.s.low = n0 >> bm;
rr.s.high = 0;
*rp = rr.ll;
}
}
else
{
if (d1 > n1)
{
/* 00 = nn / DD */
if (rp != 0) {
rr.s.low = n0 >> bm;
rr.s.high = 0;
*rp = rr.ll;
}
} else {
if (d1 > n1) {
/* 00 = nn / DD */
q0 = 0;
q1 = 0;
q0 = 0;
q1 = 0;
/* Remainder in n1n0. */
if (rp != 0)
{
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
}
else
{
/* 0q = NN / dd */
/* Remainder in n1n0. */
if (rp != 0) {
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
} else {
/* 0q = NN / dd */
count_leading_zeros (bm, d1);
if (bm == 0)
{
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
conclude (the most significant bit of n1 is set) /\ (the
quotient digit q0 = 0 or 1).
count_leading_zeros(bm, d1);
if (bm == 0) {
/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
conclude (the most significant bit of n1 is set) /\ (the
quotient digit q0 = 0 or 1).
This special case is necessary, not an optimization. */
This special case is necessary, not an optimization. */
/* The condition on the next line takes advantage of that
n1 >= d1 (true due to program flow). */
if (n1 > d1 || n0 >= d0)
{
q0 = 1;
sub_ddmmss (n1, n0, n1, n0, d1, d0);
}
else
q0 = 0;
/* The condition on the next line takes advantage of that
n1 >= d1 (true due to program flow). */
if (n1 > d1 || n0 >= d0) {
q0 = 1;
sub_ddmmss(n1, n0, n1, n0, d1, d0);
} else
q0 = 0;
q1 = 0;
q1 = 0;
if (rp != 0)
{
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
}
else
{
USItype m1, m0;
/* Normalize. */
if (rp != 0) {
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
} else {
u32 m1, m0;
/* Normalize. */
b = SI_TYPE_SIZE - bm;
b = SI_TYPE_SIZE - bm;
d1 = (d1 << bm) | (d0 >> b);
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
d1 = (d1 << bm) | (d0 >> b);
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
udiv_qrnnd (q0, n1, n2, n1, d1);
umul_ppmm (m1, m0, q0, d0);
udiv_qrnnd(q0, n1, n2, n1, d1);
umul_ppmm(m1, m0, q0, d0);
if (m1 > n1 || (m1 == n1 && m0 > n0))
{
q0--;
sub_ddmmss (m1, m0, m1, m0, d1, d0);
}
if (m1 > n1 || (m1 == n1 && m0 > n0)) {
q0--;
sub_ddmmss(m1, m0, m1, m0, d1, d0);
}
q1 = 0;
q1 = 0;
/* Remainder in (n1n0 - m1m0) >> bm. */
if (rp != 0)
{
sub_ddmmss (n1, n0, n1, n0, m1, m0);
rr.s.low = (n1 << b) | (n0 >> bm);
rr.s.high = n1 >> bm;
*rp = rr.ll;
}
}
}
}
/* Remainder in (n1n0 - m1m0) >> bm. */
if (rp != 0) {
sub_ddmmss(n1, n0, n1, n0, m1, m0);
rr.s.low = (n1 << b) | (n0 >> bm);
rr.s.high = n1 >> bm;
*rp = rr.ll;
}
}
}
}
ww.s.low = q0;
ww.s.high = q1;
return ww.ll;
ww.s.low = q0;
ww.s.high = q1;
return ww.ll;
}
UDItype
__udivdi3 (UDItype n, UDItype d)
u64 __udivdi3(u64 n, u64 d)
{
return __udivmoddi4 (n, d, (UDItype *) 0);
return __udivmoddi4(n, d, (u64 *) 0);
}
UDItype
__umoddi3 (UDItype u, UDItype v)
u64 __umoddi3(u64 u, u64 v)
{
UDItype w;
u64 w;
(void) __udivmoddi4 (u ,v, &w);
(void)__udivmoddi4(u, v, &w);
return w;
return w;
}

View file

@ -0,0 +1,11 @@
if ARCH_AAEC2000
menu "Agilent AAEC-2000 Implementations"
config MACH_AAED2000
bool "Agilent AAED-2000 Development Platform"
select CPU_ARM920T
endmenu
endif

View file

@ -0,0 +1,9 @@
#
# Makefile for the linux kernel.
#
# Common support (must be linked before board specific support)
obj-y += core.o
# Specific board support
obj-$(CONFIG_MACH_AAED2000) += aaed2000.o

View file

@ -0,0 +1,48 @@
/*
* linux/arch/arm/mach-aaec2000/aaed2000.c
*
* Support for the Agilent AAED-2000 Development Platform.
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include "core.h"
static void __init aaed2000_init_irq(void)
{
aaec2000_init_irq();
}
static void __init aaed2000_map_io(void)
{
aaec2000_map_io();
}
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
MAINTAINER("Nicolas Bellido Y Ortega")
BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
MAPIO(aaed2000_map_io)
INITIRQ(aaed2000_init_irq)
.timer = &aaec2000_timer,
MACHINE_END

View file

@ -0,0 +1,157 @@
/*
* linux/arch/arm/mach-aaec2000/core.c
*
* Code common to all AAEC-2000 machines
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/signal.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
/*
* Common I/O mapping:
*
* Static virtual address mappings are as follow:
*
* 0xf8000000-0xf8001ffff: Devices connected to APB bus
* 0xf8002000-0xf8003ffff: Devices connected to AHB bus
*
* Below 0xe8000000 is reserved for vm allocation.
*
* The machine specific code must provide the extra mapping beside the
* default mapping provided here.
*/
static struct map_desc standard_io_desc[] __initdata = {
/* virtual physical length type */
{ VIO_APB_BASE, PIO_APB_BASE, IO_APB_LENGTH, MT_DEVICE },
{ VIO_AHB_BASE, PIO_AHB_BASE, IO_AHB_LENGTH, MT_DEVICE }
};
void __init aaec2000_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
}
/*
* Interrupt handling routines
*/
static void aaec2000_int_ack(unsigned int irq)
{
IRQ_INTSR = 1 << irq;
}
static void aaec2000_int_mask(unsigned int irq)
{
IRQ_INTENC |= (1 << irq);
}
static void aaec2000_int_unmask(unsigned int irq)
{
IRQ_INTENS |= (1 << irq);
}
static struct irqchip aaec2000_irq_chip = {
.ack = aaec2000_int_ack,
.mask = aaec2000_int_mask,
.unmask = aaec2000_int_unmask,
};
void __init aaec2000_init_irq(void)
{
unsigned int i;
for (i = 0; i < NR_IRQS; i++) {
set_irq_handler(i, do_level_IRQ);
set_irq_chip(i, &aaec2000_irq_chip);
set_irq_flags(i, IRQF_VALID);
}
/* Disable all interrupts */
IRQ_INTENC = 0xffffffff;
/* Clear any pending interrupts */
IRQ_INTSR = IRQ_INTSR;
}
/*
* Time keeping
*/
/* IRQs are disabled before entering here from do_gettimeofday() */
static unsigned long aaec2000_gettimeoffset(void)
{
unsigned long ticks_to_match, elapsed, usec;
/* Get ticks before next timer match */
ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
/* We need elapsed ticks since last match */
elapsed = LATCH - ticks_to_match;
/* Now, convert them to usec */
usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
return usec;
}
/* We enter here with IRQs enabled */
static irqreturn_t
aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/* TODO: Check timer accuracy */
write_seqlock(&xtime_lock);
timer_tick(regs);
TIMER1_CLEAR = 1;
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction aaec2000_timer_irq = {
.name = "AAEC-2000 Timer Tick",
.flags = SA_INTERRUPT,
.handler = aaec2000_timer_interrupt
};
static void __init aaec2000_timer_init(void)
{
/* Disable timer 1 */
TIMER1_CTRL = 0;
/* We have somehow to generate a 100Hz clock.
* We then use the 508KHz timer in periodic mode.
*/
TIMER1_LOAD = LATCH;
TIMER1_CLEAR = 1; /* Clear interrupt */
setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
TIMER1_CTRL = TIMER_CTRL_ENABLE |
TIMER_CTRL_PERIODIC |
TIMER_CTRL_CLKSEL_508K;
}
struct sys_timer aaec2000_timer = {
.init = aaec2000_timer_init,
.offset = aaec2000_gettimeoffset,
};

View file

@ -0,0 +1,16 @@
/*
* linux/arch/arm/mach-aaec2000/core.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
struct sys_timer;
extern struct sys_timer aaec2000_timer;
extern void __init aaec2000_map_io(void);
extern void __init aaec2000_init_irq(void);

View file

@ -227,7 +227,6 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* primary CPU
*/
if (hard_smp_processor_id() == 0) {
nmi_tick();
timer_tick(regs);
#ifdef CONFIG_SMP
smp_send_timer();

View file

@ -162,12 +162,13 @@ void __init ixp2000_map_io(void)
static unsigned ticks_per_jiffy;
static unsigned ticks_per_usec;
static unsigned next_jiffy_time;
static volatile unsigned long *missing_jiffy_timer_csr;
unsigned long ixp2000_gettimeoffset (void)
{
unsigned long offset;
offset = next_jiffy_time - *IXP2000_T4_CSR;
offset = next_jiffy_time - *missing_jiffy_timer_csr;
return offset / ticks_per_usec;
}
@ -179,7 +180,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* clear timer 1 */
ixp2000_reg_write(IXP2000_T1_CLR, 1);
while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
timer_tick(regs);
next_jiffy_time -= ticks_per_jiffy;
}
@ -197,20 +198,37 @@ static struct irqaction ixp2000_timer_irq = {
void __init ixp2000_init_time(unsigned long tick_rate)
{
ixp2000_reg_write(IXP2000_T1_CLR, 0);
ixp2000_reg_write(IXP2000_T4_CLR, 0);
ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
ticks_per_usec = tick_rate / 1000000;
/*
* We use timer 1 as our timer interrupt.
*/
ixp2000_reg_write(IXP2000_T1_CLR, 0);
ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
/*
* We use T4 as a monotonic counter to track missed jiffies
* We use a second timer as a monotonic counter for tracking
* missed jiffies. The IXP2000 has four timers, but if we're
* on an A-step IXP2800, timer 2 and 3 don't work, so on those
* chips we use timer 4. Timer 4 is the only timer that can
* be used for the watchdog, so we use timer 2 if we're on a
* non-buggy chip.
*/
ixp2000_reg_write(IXP2000_T4_CLD, -1);
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
ixp2000_reg_write(IXP2000_T4_CLR, 0);
ixp2000_reg_write(IXP2000_T4_CLD, -1);
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
missing_jiffy_timer_csr = IXP2000_T4_CSR;
} else {
ixp2000_reg_write(IXP2000_T2_CLR, 0);
ixp2000_reg_write(IXP2000_T2_CLD, -1);
ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
missing_jiffy_timer_csr = IXP2000_T2_CSR;
}
next_jiffy_time = 0xffffffff;
/* register for interrupt */

View file

@ -5,3 +5,4 @@
obj-y := core.o clock.o
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o
obj-$(CONFIG_PCI) += pci.o

View file

@ -196,11 +196,15 @@ static struct map_desc versatile_io_desc[] __initdata = {
#ifdef CONFIG_DEBUG_LL
{ IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
#endif
#ifdef FIXME
{ PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
{ PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
{ PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE },
{ PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE },
#ifdef CONFIG_PCI
{ IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
{ VERSATILE_PCI_VIRT_BASE, VERSATILE_PCI_BASE, VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
{ VERSATILE_PCI_CFG_VIRT_BASE, VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
#if 0
{ VERSATILE_PCI_VIRT_MEM_BASE0, VERSATILE_PCI_MEM_BASE0, SZ_16M, MT_DEVICE },
{ VERSATILE_PCI_VIRT_MEM_BASE1, VERSATILE_PCI_MEM_BASE1, SZ_16M, MT_DEVICE },
{ VERSATILE_PCI_VIRT_MEM_BASE2, VERSATILE_PCI_MEM_BASE2, SZ_16M, MT_DEVICE },
#endif
#endif
};

View file

@ -0,0 +1,360 @@
/*
* linux/arch/arm/mach-versatile/pci.c
*
* (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
* You can redistribute and/or modify this software under the terms of version 2
* of the GNU General Public License as published by the Free Software Foundation.
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
*
* ARM Versatile PCI driver.
*
* 14/04/2005 Initial version, colin.king@philips.com
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
/*
* these spaces are mapped using the following base registers:
*
* Usage Local Bus Memory Base/Map registers used
*
* Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0, non prefetch
* Mem 60000000 - 6FFFFFFF LB_BASE1/LB_MAP1, prefetch
* IO 44000000 - 4FFFFFFF LB_BASE2/LB_MAP2, IO
* Cfg 42000000 - 42FFFFFF PCI config
*
*/
#define SYS_PCICTL IO_ADDRESS(VERSATILE_SYS_PCICTL)
#define PCI_IMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
#define PCI_IMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
#define PCI_IMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
#define PCI_SMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
#define PCI_SMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
#define PCI_SMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
#define PCI_SELFID IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
#define DEVICE_ID_OFFSET 0x00
#define CSR_OFFSET 0x04
#define CLASS_ID_OFFSET 0x08
#define VP_PCI_DEVICE_ID 0x030010ee
#define VP_PCI_CLASS_ID 0x0b400000
static unsigned long pci_slot_ignore = 0;
static int __init versatile_pci_slot_ignore(char *str)
{
int retval;
int slot;
while ((retval = get_option(&str,&slot))) {
if ((slot < 0) || (slot > 31)) {
printk("Illegal slot value: %d\n",slot);
} else {
pci_slot_ignore |= (1 << slot);
}
}
return 1;
}
__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
static unsigned long __pci_addr(struct pci_bus *bus,
unsigned int devfn, int offset)
{
unsigned int busnr = bus->number;
/*
* Trap out illegal values
*/
if (offset > 255)
BUG();
if (busnr > 255)
BUG();
if (devfn > 255)
BUG();
return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
(PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
}
static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
unsigned long addr = __pci_addr(bus, devfn, where);
u32 v;
int slot = PCI_SLOT(devfn);
if (pci_slot_ignore & (1 << slot)) {
/* Ignore this slot */
switch (size) {
case 1:
v = 0xff;
break;
case 2:
v = 0xffff;
break;
default:
v = 0xffffffff;
}
} else {
switch (size) {
case 1:
addr &= ~3;
v = __raw_readb(addr);
break;
case 2:
v = __raw_readl(addr & ~3);
if (addr & 2) v >>= 16;
v &= 0xffff;
break;
default:
addr &= ~3;
v = __raw_readl(addr);
break;
}
}
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
unsigned long addr = __pci_addr(bus, devfn, where);
int slot = PCI_SLOT(devfn);
if (pci_slot_ignore & (1 << slot)) {
return PCIBIOS_SUCCESSFUL;
}
switch (size) {
case 1:
__raw_writeb((u8)val, addr);
break;
case 2:
__raw_writew((u16)val, addr);
break;
case 4:
__raw_writel(val, addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops pci_versatile_ops = {
.read = versatile_read_config,
.write = versatile_write_config,
};
static struct resource io_mem = {
.name = "PCI I/O space",
.start = VERSATILE_PCI_MEM_BASE0,
.end = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
.flags = IORESOURCE_IO,
};
static struct resource non_mem = {
.name = "PCI non-prefetchable",
.start = VERSATILE_PCI_MEM_BASE1,
.end = VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
.flags = IORESOURCE_MEM,
};
static struct resource pre_mem = {
.name = "PCI prefetchable",
.start = VERSATILE_PCI_MEM_BASE2,
.end = VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
};
static int __init pci_versatile_setup_resources(struct resource **resource)
{
int ret = 0;
ret = request_resource(&iomem_resource, &io_mem);
if (ret) {
printk(KERN_ERR "PCI: unable to allocate I/O "
"memory region (%d)\n", ret);
goto out;
}
ret = request_resource(&iomem_resource, &non_mem);
if (ret) {
printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
"memory region (%d)\n", ret);
goto release_io_mem;
}
ret = request_resource(&iomem_resource, &pre_mem);
if (ret) {
printk(KERN_ERR "PCI: unable to allocate prefetchable "
"memory region (%d)\n", ret);
goto release_non_mem;
}
/*
* bus->resource[0] is the IO resource for this bus
* bus->resource[1] is the mem resource for this bus
* bus->resource[2] is the prefetch mem resource for this bus
*/
resource[0] = &io_mem;
resource[1] = &non_mem;
resource[2] = &pre_mem;
goto out;
release_non_mem:
release_resource(&non_mem);
release_io_mem:
release_resource(&io_mem);
out:
return ret;
}
int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
{
int ret = 0;
int i;
int myslot = -1;
unsigned long val;
if (nr == 0) {
sys->mem_offset = 0;
ret = pci_versatile_setup_resources(sys->resource);
if (ret < 0) {
printk("pci_versatile_setup: resources... oops?\n");
goto out;
}
} else {
printk("pci_versatile_setup: resources... nr == 0??\n");
goto out;
}
__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
__raw_writel(1, SYS_PCICTL);
val = __raw_readl(SYS_PCICTL);
if (!(val & 1)) {
printk("Not plugged into PCI backplane!\n");
ret = -EIO;
goto out;
}
/*
* We need to discover the PCI core first to configure itself
* before the main PCI probing is performed
*/
for (i=0; i<32; i++) {
if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
(__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
myslot = i;
__raw_writel(myslot, PCI_SELFID);
val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
val |= (1<<2);
__raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
break;
}
}
if (myslot == -1) {
printk("Cannot find PCI core!\n");
ret = -EIO;
} else {
printk("PCI core found (slot %d)\n",myslot);
/* Do not to map Versatile FPGA PCI device
into memory space as we are short of
mappable memory */
pci_slot_ignore |= (1 << myslot);
ret = 1;
}
out:
return ret;
}
struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
{
return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
}
/*
* V3_LB_BASE? - local bus address
* V3_LB_MAP? - pci bus address
*/
void __init pci_versatile_preinit(void)
{
}
void __init pci_versatile_postinit(void)
{
}
/*
* map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this.
*/
static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq;
int devslot = PCI_SLOT(dev->devfn);
/* slot, pin, irq
24 1 27
25 1 28 untested
26 1 29
27 1 30 untested
*/
irq = 27 + ((slot + pin + 2) % 3); /* Fudged */
printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
return irq;
}
static struct hw_pci versatile_pci __initdata = {
.swizzle = NULL,
.map_irq = versatile_map_irq,
.nr_controllers = 1,
.setup = pci_versatile_setup,
.scan = pci_versatile_scan_bus,
.preinit = pci_versatile_preinit,
.postinit = pci_versatile_postinit,
};
static int __init versatile_pci_init(void)
{
pci_common_init(&versatile_pci);
return 0;
}
subsys_initcall(versatile_pci_init);

View file

@ -62,7 +62,7 @@ config CPU_ARM720T
# ARM920T
config CPU_ARM920T
bool "Support ARM920T processor" if !ARCH_S3C2410
depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
default y if ARCH_S3C2410
select CPU_32v4
select CPU_ABRT_EV4T

View file

@ -30,8 +30,6 @@
static DEFINE_SPINLOCK(v6_lock);
#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
/*
* Copy the user page. No aliasing to deal with so we can just
* attack the kernel's existing mapping of these pages.
@ -55,7 +53,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
*/
void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
{
unsigned int offset = DCACHE_COLOUR(vaddr);
unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long from, to;
/*
@ -95,7 +93,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
*/
void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
{
unsigned int offset = DCACHE_COLOUR(vaddr);
unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long to = to_address + (offset << PAGE_SHIFT);
/*

View file

@ -77,9 +77,8 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
}
static void
make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
{
struct address_space *mapping = page_mapping(page);
struct mm_struct *mm = vma->vm_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
pgoff_t pgoff;
int aliases = 0;
if (!mapping)
return;
pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
/*
@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
if (aliases)
adjust_pte(vma, addr);
else
flush_cache_page(vma, addr, page_to_pfn(page));
flush_cache_page(vma, addr, pfn);
}
void __flush_dcache_page(struct address_space *mapping, struct page *page);
/*
* Take care of architecture specific things when placing a new PTE into
* a page table, or changing an existing PTE. Basically, there are two
@ -134,29 +132,22 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
{
unsigned long pfn = pte_pfn(pte);
struct address_space *mapping;
struct page *page;
if (!pfn_valid(pfn))
return;
page = pfn_to_page(pfn);
if (page_mapping(page)) {
mapping = page_mapping(page);
if (mapping) {
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
if (dirty) {
/*
* This is our first userspace mapping of this page.
* Ensure that the physical page is coherent with
* the kernel mapping.
*
* FIXME: only need to do this on VIVT and aliasing
* VIPT cache architectures. We can do that
* by choosing whether to set this bit...
*/
__cpuc_flush_dcache_page(page_address(page));
}
if (dirty)
__flush_dcache_page(mapping, page);
if (cache_is_vivt())
make_coherent(vma, addr, page, dirty);
make_coherent(mapping, vma, addr, pfn);
}
}

View file

@ -37,13 +37,8 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
#define flush_pfn_alias(pfn,vaddr) do { } while (0)
#endif
static void __flush_dcache_page(struct address_space *mapping, struct page *page)
void __flush_dcache_page(struct address_space *mapping, struct page *page)
{
struct mm_struct *mm = current->active_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
pgoff_t pgoff;
/*
* Writeback any data associated with the kernel mapping of this
* page. This ensures that data in the physical page is mutually
@ -52,24 +47,21 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
__cpuc_flush_dcache_page(page_address(page));
/*
* If there's no mapping pointer here, then this page isn't
* visible to userspace yet, so there are no cache lines
* associated with any other aliases.
*/
if (!mapping)
return;
/*
* This is a page cache page. If we have a VIPT cache, we
* only need to do one flush - which would be at the relevant
* If this is a page cache page, and we have an aliasing VIPT cache,
* we only need to do one flush - which would be at the relevant
* userspace colour, which is congruent with page->index.
*/
if (cache_is_vipt()) {
if (cache_is_vipt_aliasing())
flush_pfn_alias(page_to_pfn(page),
page->index << PAGE_CACHE_SHIFT);
return;
}
if (mapping && cache_is_vipt_aliasing())
flush_pfn_alias(page_to_pfn(page),
page->index << PAGE_CACHE_SHIFT);
}
static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
{
struct mm_struct *mm = current->active_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
pgoff_t pgoff;
/*
* There are possible user space mappings of this page:
@ -116,12 +108,12 @@ void flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
if (cache_is_vipt_nonaliasing())
return;
if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
else
else {
__flush_dcache_page(mapping, page);
if (mapping && cache_is_vivt())
__flush_dcache_aliases(mapping, page);
}
}
EXPORT_SYMBOL(flush_dcache_page);

View file

@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr)
vfree((void *) (PAGE_MASK & (unsigned long) addr));
}
EXPORT_SYMBOL(__iounmap);
#ifdef __io
void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
return __io(port);
}
EXPORT_SYMBOL(ioport_map);
void ioport_unmap(void __iomem *addr)
{
}
EXPORT_SYMBOL(ioport_unmap);
#endif
#ifdef CONFIG_PCI
#include <linux/pci.h>
#include <linux/ioport.h>
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
unsigned long start = pci_resource_start(dev, bar);
unsigned long len = pci_resource_len(dev, bar);
unsigned long flags = pci_resource_flags(dev, bar);
if (!len || !start)
return NULL;
if (maxlen && len > maxlen)
len = maxlen;
if (flags & IORESOURCE_IO)
return ioport_map(start, len);
if (flags & IORESOURCE_MEM) {
if (flags & IORESOURCE_CACHEABLE)
return ioremap(start, len);
return ioremap_nocache(start, len);
}
return NULL;
}
EXPORT_SYMBOL(pci_iomap);
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
if ((unsigned long)addr >= VMALLOC_START &&
(unsigned long)addr < VMALLOC_END)
iounmap(addr);
}
EXPORT_SYMBOL(pci_iounmap);
#endif

View file

@ -562,31 +562,31 @@ static void __init ecard_init_resources(struct expansion_card *ec)
}
}
static ssize_t ecard_show_irq(struct device *dev, char *buf)
static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->irq);
}
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer);
}
static ssize_t ecard_show_device(struct device *dev, char *buf)
static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product);
}
static ssize_t ecard_show_dma(struct device *dev, char *buf)
static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma);
}
static ssize_t ecard_show_resources(struct device *dev, char *buf)
static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
char *str = buf;

View file

@ -45,7 +45,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
static struct class_simple *cpuid_class;
static struct class *cpuid_class;
#ifdef CONFIG_SMP
@ -158,12 +158,12 @@ static struct file_operations cpuid_fops = {
.open = cpuid_open,
};
static int cpuid_class_simple_device_add(int i)
static int cpuid_class_device_create(int i)
{
int err = 0;
struct class_device *class_err;
class_err = class_simple_device_add(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
if (IS_ERR(class_err))
err = PTR_ERR(class_err);
return err;
@ -175,10 +175,10 @@ static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsign
switch (action) {
case CPU_ONLINE:
cpuid_class_simple_device_add(cpu);
cpuid_class_device_create(cpu);
break;
case CPU_DEAD:
class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@ -200,13 +200,13 @@ static int __init cpuid_init(void)
err = -EBUSY;
goto out;
}
cpuid_class = class_simple_create(THIS_MODULE, "cpuid");
cpuid_class = class_create(THIS_MODULE, "cpuid");
if (IS_ERR(cpuid_class)) {
err = PTR_ERR(cpuid_class);
goto out_chrdev;
}
for_each_online_cpu(i) {
err = cpuid_class_simple_device_add(i);
err = cpuid_class_device_create(i);
if (err != 0)
goto out_class;
}
@ -218,9 +218,9 @@ static int __init cpuid_init(void)
out_class:
i = 0;
for_each_online_cpu(i) {
class_simple_device_remove(MKDEV(CPUID_MAJOR, i));
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
}
class_simple_destroy(cpuid_class);
class_destroy(cpuid_class);
out_chrdev:
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
out:
@ -232,8 +232,8 @@ static void __exit cpuid_exit(void)
int cpu = 0;
for_each_online_cpu(cpu)
class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
class_simple_destroy(cpuid_class);
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
class_destroy(cpuid_class);
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
unregister_cpu_notifier(&cpuid_class_cpu_notifier);
}

View file

@ -44,7 +44,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
static struct class_simple *msr_class;
static struct class *msr_class;
/* Note: "err" is handled in a funny way below. Otherwise one version
of gcc or another breaks. */
@ -260,12 +260,12 @@ static struct file_operations msr_fops = {
.open = msr_open,
};
static int msr_class_simple_device_add(int i)
static int msr_class_device_create(int i)
{
int err = 0;
struct class_device *class_err;
class_err = class_simple_device_add(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
if (IS_ERR(class_err))
err = PTR_ERR(class_err);
return err;
@ -277,10 +277,10 @@ static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned
switch (action) {
case CPU_ONLINE:
msr_class_simple_device_add(cpu);
msr_class_device_create(cpu);
break;
case CPU_DEAD:
class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@ -302,13 +302,13 @@ static int __init msr_init(void)
err = -EBUSY;
goto out;
}
msr_class = class_simple_create(THIS_MODULE, "msr");
msr_class = class_create(THIS_MODULE, "msr");
if (IS_ERR(msr_class)) {
err = PTR_ERR(msr_class);
goto out_chrdev;
}
for_each_online_cpu(i) {
err = msr_class_simple_device_add(i);
err = msr_class_device_create(i);
if (err != 0)
goto out_class;
}
@ -320,8 +320,8 @@ static int __init msr_init(void)
out_class:
i = 0;
for_each_online_cpu(i)
class_simple_device_remove(MKDEV(MSR_MAJOR, i));
class_simple_destroy(msr_class);
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
class_destroy(msr_class);
out_chrdev:
unregister_chrdev(MSR_MAJOR, "cpu/msr");
out:
@ -332,8 +332,8 @@ static void __exit msr_exit(void)
{
int cpu = 0;
for_each_online_cpu(cpu)
class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
class_simple_destroy(msr_class);
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
class_destroy(msr_class);
unregister_chrdev(MSR_MAJOR, "cpu/msr");
unregister_cpu_notifier(&msr_class_cpu_notifier);
}

View file

@ -432,7 +432,7 @@ static int tiocx_reload(struct cx_dev *cx_dev)
return cx_device_reload(cx_dev);
}
static ssize_t show_cxdev_control(struct device *dev, char *buf)
static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cx_dev *cx_dev = to_cx_dev(dev);
@ -442,7 +442,7 @@ static ssize_t show_cxdev_control(struct device *dev, char *buf)
tiocx_btchar_get(cx_dev->cx_id.nasid));
}
static ssize_t store_cxdev_control(struct device *dev, const char *buf,
static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
int n;
@ -518,25 +518,22 @@ static int __init tiocx_init(void)
return 0;
}
static int cx_remove_device(struct device * dev, void * data)
{
struct cx_dev *cx_dev = to_cx_dev(dev);
device_remove_file(dev, &dev_attr_cxdev_control);
cx_device_unregister(cx_dev);
return 0;
}
static void __exit tiocx_exit(void)
{
struct device *dev;
struct device *tdev;
DBG("tiocx_exit\n");
/*
* Unregister devices.
*/
list_for_each_entry_safe(dev, tdev, &tiocx_bus_type.devices.list,
bus_list) {
if (dev) {
struct cx_dev *cx_dev = to_cx_dev(dev);
device_remove_file(dev, &dev_attr_cxdev_control);
cx_device_unregister(cx_dev);
}
}
bus_for_each_dev(&tiocx_bus_type, NULL, NULL, cx_remove_device);
bus_unregister(&tiocx_bus_type);
}

View file

@ -466,7 +466,7 @@ static int parisc_generic_match(struct device *dev, struct device_driver *drv)
}
#define pa_dev_attr(name, field, format_string) \
static ssize_t name##_show(struct device *dev, char *buf) \
static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct parisc_device *padev = to_parisc_device(dev); \
return sprintf(buf, format_string, padev->field); \

View file

@ -1003,7 +1003,7 @@ pci_create_OF_bus_map(void)
}
}
static ssize_t pci_show_devspec(struct device *dev, char *buf)
static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;

View file

@ -68,7 +68,7 @@ static int ocp_inited;
/* Sysfs support */
#define OCP_DEF_ATTR(field, format_string) \
static ssize_t \
show_##field(struct device *dev, char *buf) \
show_##field(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct ocp_device *odev = to_ocp_dev(dev); \
\

View file

@ -161,7 +161,7 @@ void of_unregister_driver(struct of_platform_driver *drv)
}
static ssize_t dev_show_devspec(struct device *dev, char *buf)
static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;

View file

@ -423,6 +423,9 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
tbl->it_largehint = tbl->it_halfpoint;
spin_lock_init(&tbl->it_lock);
/* Clear the hardware table in case firmware left allocations in it */
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
novmerge ? "disabled" : "enabled");

View file

@ -161,7 +161,7 @@ void of_unregister_driver(struct of_platform_driver *drv)
}
static ssize_t dev_show_devspec(struct device *dev, char *buf)
static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;

View file

@ -375,7 +375,7 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
* cpus are assumed to be secondary threads.
*/
if (system_state < SYSTEM_RUNNING &&
cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
cpu_has_feature(CPU_FTR_SMT) &&
!smt_enabled_at_boot && nr % 2 != 0)
return 0;
@ -419,8 +419,8 @@ void __init smp_init_pSeries(void)
#endif
/* Mark threads which are still spinning in hold loops. */
if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
for_each_present_cpu(i) {
if (cpu_has_feature(CPU_FTR_SMT)) {
for_each_present_cpu(i) {
if (i % 2 == 0)
/*
* Even-numbered logical cpus correspond to
@ -428,8 +428,9 @@ void __init smp_init_pSeries(void)
*/
cpu_set(i, of_spin_map);
}
else
} else {
of_spin_map = cpu_present_map;
}
cpu_clear(boot_cpuid, of_spin_map);

View file

@ -507,7 +507,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
}
#ifdef CONFIG_PPC_MULTIPLATFORM
static ssize_t pci_show_devspec(struct device *dev, char *buf)
static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;

View file

@ -440,7 +440,7 @@ static int rtasd(void *unused)
goto error;
}
printk(KERN_ERR "RTAS daemon started\n");
printk(KERN_INFO "RTAS daemon started\n");
DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
@ -485,7 +485,7 @@ static int __init rtas_init(void)
/* No RTAS, only warn if we are on a pSeries box */
if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
if (systemcfg->platform & PLATFORM_PSERIES)
printk(KERN_ERR "rtasd: no event-scan on system\n");
printk(KERN_INFO "rtasd: no event-scan on system\n");
return 1;
}

View file

@ -300,7 +300,7 @@ static void __devinit vio_dev_release(struct device *dev)
}
#ifdef CONFIG_PPC_PSERIES
static ssize_t viodev_show_devspec(struct device *dev, char *buf)
static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct device_node *of_node = dev->platform_data;
@ -309,7 +309,7 @@ static ssize_t viodev_show_devspec(struct device *dev, char *buf)
DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
#endif
static ssize_t viodev_show_name(struct device *dev, char *buf)
static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
}

View file

@ -65,14 +65,14 @@ static ssize_t acpi_device_attr_show(struct kobject *kobj,
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
return attribute->show ? attribute->show(device, buf) : 0;
return attribute->show ? attribute->show(device, buf) : -EIO;
}
static ssize_t acpi_device_attr_store(struct kobject *kobj,
struct attribute *attr, const char *buf, size_t len)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
return attribute->store ? attribute->store(device, buf, len) : len;
return attribute->store ? attribute->store(device, buf, len) : -EIO;
}
static struct sysfs_ops acpi_device_sysfs_ops = {

View file

@ -1,7 +1,7 @@
# Makefile for the Linux device tree
obj-y := core.o sys.o bus.o \
driver.o class.o class_simple.o platform.o \
obj-y := core.o sys.o bus.o dd.o \
driver.o class.o platform.o \
cpu.o firmware.o init.o map.o dmapool.o \
attribute_container.o transport_class.o
obj-y += power/

View file

@ -4,6 +4,8 @@ extern void bus_remove_device(struct device * dev);
extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
extern void driver_detach(struct device_driver * drv);
static inline struct class_device *to_class_dev(struct kobject *obj)
{
return container_of(obj, struct class_device, kobj);

View file

@ -17,9 +17,6 @@
#include "base.h"
#include "power/power.h"
#define to_dev(node) container_of(node, struct device, bus_list)
#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
@ -36,7 +33,7 @@ drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (drv_attr->show)
ret = drv_attr->show(drv, buf);
@ -49,7 +46,7 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (drv_attr->store)
ret = drv_attr->store(drv, buf, count);
@ -135,50 +132,11 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
static int __bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
static struct device * next_device(struct klist_iter * i)
{
struct list_head *head;
struct device *dev;
int error = 0;
if (!(bus = get_bus(bus)))
return -EINVAL;
head = &bus->devices.list;
dev = list_prepare_entry(start, head, bus_list);
list_for_each_entry_continue(dev, head, bus_list) {
get_device(dev);
error = fn(dev, data);
put_device(dev);
if (error)
break;
}
put_bus(bus);
return error;
}
static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void * data, int (*fn)(struct device_driver *, void *))
{
struct list_head *head;
struct device_driver *drv;
int error = 0;
if (!(bus = get_bus(bus)))
return -EINVAL;
head = &bus->drivers.list;
drv = list_prepare_entry(start, head, kobj.entry);
list_for_each_entry_continue(drv, head, kobj.entry) {
get_driver(drv);
error = fn(drv, data);
put_driver(drv);
if (error)
break;
}
put_bus(bus);
return error;
struct klist_node * n = klist_next(i);
return n ? container_of(n, struct device, knode_bus) : NULL;
}
/**
@ -204,12 +162,27 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *))
{
int ret;
struct klist_iter i;
struct device * dev;
int error = 0;
down_read(&bus->subsys.rwsem);
ret = __bus_for_each_dev(bus, start, data, fn);
up_read(&bus->subsys.rwsem);
return ret;
if (!bus)
return -EINVAL;
klist_iter_init_node(&bus->klist_devices, &i,
(start ? &start->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
static struct device_driver * next_driver(struct klist_iter * i)
{
struct klist_node * n = klist_next(i);
return n ? container_of(n, struct device_driver, knode_bus) : NULL;
}
/**
@ -235,179 +208,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *))
{
int ret;
struct klist_iter i;
struct device_driver * drv;
int error = 0;
down_read(&bus->subsys.rwsem);
ret = __bus_for_each_drv(bus, start, data, fn);
up_read(&bus->subsys.rwsem);
return ret;
}
if (!bus)
return -EINVAL;
/**
* device_bind_driver - bind a driver to one device.
* @dev: device.
*
* Allow manual attachment of a driver to a device.
* Caller must have already set @dev->driver.
*
* Note that this does not modify the bus reference count
* nor take the bus's rwsem. Please verify those are accounted
* for before calling this. (It is ok to call with no other effort
* from a driver's probe() method.)
*/
void device_bind_driver(struct device * dev)
{
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
list_add_tail(&dev->driver_list, &dev->driver->devices);
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
}
/**
* driver_probe_device - attempt to bind device & driver.
* @drv: driver.
* @dev: device.
*
* First, we call the bus's match function, if one present, which
* should compare the device IDs the driver supports with the
* device IDs of the device. Note we don't do this ourselves
* because we don't know the format of the ID structures, nor what
* is to be considered a match and what is not.
*
* If we find a match, we call @drv->probe(@dev) if it exists, and
* call device_bind_driver() above.
*/
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
if (drv->bus->match && !drv->bus->match(dev, drv))
return -ENODEV;
dev->driver = drv;
if (drv->probe) {
int error = drv->probe(dev);
if (error) {
dev->driver = NULL;
return error;
}
}
device_bind_driver(dev);
return 0;
}
/**
* device_attach - try to attach device to a driver.
* @dev: device.
*
* Walk the list of drivers that the bus has and call
* driver_probe_device() for each pair. If a compatible
* pair is found, break out and return.
*/
int device_attach(struct device * dev)
{
struct bus_type * bus = dev->bus;
struct list_head * entry;
int error;
if (dev->driver) {
device_bind_driver(dev);
return 1;
}
if (bus->match) {
list_for_each(entry, &bus->drivers.list) {
struct device_driver * drv = to_drv(entry);
error = driver_probe_device(drv, dev);
if (!error)
/* success, driver matched */
return 1;
if (error != -ENODEV && error != -ENXIO)
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev->bus_id, error);
}
}
return 0;
}
/**
* driver_attach - try to bind driver to devices.
* @drv: driver.
*
* Walk the list of devices that the bus has on it and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*
* Note that we ignore the -ENODEV error from driver_probe_device(),
* since it's perfectly valid for a driver not to bind to any devices.
*/
void driver_attach(struct device_driver * drv)
{
struct bus_type * bus = drv->bus;
struct list_head * entry;
int error;
if (!bus->match)
return;
list_for_each(entry, &bus->devices.list) {
struct device * dev = container_of(entry, struct device, bus_list);
if (!dev->driver) {
error = driver_probe_device(drv, dev);
if (error && (error != -ENODEV))
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev->bus_id, error);
}
}
}
/**
* device_release_driver - manually detach device from driver.
* @dev: device.
*
* Manually detach device from driver.
* Note that this is called without incrementing the bus
* reference count nor taking the bus's rwsem. Be sure that
* those are accounted for before calling this function.
*/
void device_release_driver(struct device * dev)
{
struct device_driver * drv = dev->driver;
if (drv) {
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
sysfs_remove_link(&dev->kobj, "driver");
list_del_init(&dev->driver_list);
if (drv->remove)
drv->remove(dev);
dev->driver = NULL;
}
}
/**
* driver_detach - detach driver from all devices it controls.
* @drv: driver.
*/
static void driver_detach(struct device_driver * drv)
{
while (!list_empty(&drv->devices)) {
struct device * dev = container_of(drv->devices.next, struct device, driver_list);
device_release_driver(dev);
}
klist_iter_init_node(&bus->klist_drivers, &i,
start ? &start->knode_bus : NULL);
while ((drv = next_driver(&i)) && !error)
error = fn(drv, data);
klist_iter_exit(&i);
return error;
}
static int device_add_attrs(struct bus_type * bus, struct device * dev)
@ -456,14 +269,15 @@ int bus_add_device(struct device * dev)
int error = 0;
if (bus) {
down_write(&dev->bus->subsys.rwsem);
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
list_add_tail(&dev->bus_list, &dev->bus->devices.list);
device_attach(dev);
up_write(&dev->bus->subsys.rwsem);
device_add_attrs(bus, dev);
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
error = device_attach(dev);
klist_add_tail(&bus->klist_devices, &dev->knode_bus);
if (error >= 0)
error = device_add_attrs(bus, dev);
if (!error) {
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
}
}
return error;
}
@ -483,11 +297,9 @@ void bus_remove_device(struct device * dev)
sysfs_remove_link(&dev->kobj, "bus");
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
down_write(&dev->bus->subsys.rwsem);
klist_remove(&dev->knode_bus);
pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
device_release_driver(dev);
list_del_init(&dev->bus_list);
up_write(&dev->bus->subsys.rwsem);
put_bus(dev->bus);
}
}
@ -547,9 +359,8 @@ int bus_add_driver(struct device_driver * drv)
return error;
}
down_write(&bus->subsys.rwsem);
driver_attach(drv);
up_write(&bus->subsys.rwsem);
klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
@ -571,10 +382,9 @@ void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
driver_remove_attrs(drv->bus, drv);
down_write(&drv->bus->subsys.rwsem);
klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
driver_detach(drv);
up_write(&drv->bus->subsys.rwsem);
module_remove_driver(drv);
kobject_unregister(&drv->kobj);
put_bus(drv->bus);
@ -587,7 +397,7 @@ static int bus_rescan_devices_helper(struct device *dev, void *data)
{
int *count = data;
if (!dev->driver && device_attach(dev))
if (!dev->driver && (device_attach(dev) > 0))
(*count)++;
return 0;
@ -607,9 +417,7 @@ int bus_rescan_devices(struct bus_type * bus)
{
int count = 0;
down_write(&bus->subsys.rwsem);
__bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
up_write(&bus->subsys.rwsem);
bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
return count;
}
@ -710,6 +518,9 @@ int bus_register(struct bus_type * bus)
retval = kset_register(&bus->drivers);
if (retval)
goto bus_drivers_fail;
klist_init(&bus->klist_devices);
klist_init(&bus->klist_drivers);
bus_add_attrs(bus);
pr_debug("bus type '%s' registered\n", bus->name);
@ -749,12 +560,6 @@ int __init buses_init(void)
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
EXPORT_SYMBOL_GPL(driver_probe_device);
EXPORT_SYMBOL_GPL(device_bind_driver);
EXPORT_SYMBOL_GPL(device_release_driver);
EXPORT_SYMBOL_GPL(device_attach);
EXPORT_SYMBOL_GPL(driver_attach);
EXPORT_SYMBOL_GPL(bus_add_device);
EXPORT_SYMBOL_GPL(bus_remove_device);
EXPORT_SYMBOL_GPL(bus_register);

View file

@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@ -26,7 +27,7 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct class_attribute * class_attr = to_class_attr(attr);
struct class * dc = to_class(kobj);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (class_attr->show)
ret = class_attr->show(dc, buf);
@ -39,7 +40,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct class_attribute * class_attr = to_class_attr(attr);
struct class * dc = to_class(kobj);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (class_attr->store)
ret = class_attr->store(dc, buf, count);
@ -162,6 +163,69 @@ void class_unregister(struct class * cls)
subsystem_unregister(&cls->subsys);
}
static void class_create_release(struct class *cls)
{
kfree(cls);
}
static void class_device_create_release(struct class_device *class_dev)
{
kfree(class_dev);
}
/**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
* @name: pointer to a string for the name of this class.
*
* This is used to create a struct class pointer that can then be used
* in calls to class_device_create().
*
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
struct class *class_create(struct module *owner, char *name)
{
struct class *cls;
int retval;
cls = kmalloc(sizeof(struct class), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
memset(cls, 0x00, sizeof(struct class));
cls->name = name;
cls->owner = owner;
cls->class_release = class_create_release;
cls->release = class_device_create_release;
retval = class_register(cls);
if (retval)
goto error;
return cls;
error:
kfree(cls);
return ERR_PTR(retval);
}
/**
* class_destroy - destroys a struct class structure
* @cs: pointer to the struct class that is to be destroyed
*
* Note, the pointer to be destroyed must have been created with a call
* to class_create().
*/
void class_destroy(struct class *cls)
{
if ((cls == NULL) || (IS_ERR(cls)))
return;
class_unregister(cls);
}
/* Class Device Stuff */
@ -262,7 +326,7 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
static char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct class_device *class_dev = to_class_dev(kobj);
@ -375,7 +439,6 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
return print_dev_t(buf, class_dev->devt);
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
void class_device_initialize(struct class_device *class_dev)
{
@ -412,7 +475,31 @@ int class_device_add(struct class_device *class_dev)
if ((error = kobject_add(&class_dev->kobj)))
goto register_done;
/* now take care of our own registration */
/* add the needed attributes to this device */
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
attr = kmalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
kobject_del(&class_dev->kobj);
goto register_done;
}
memset(attr, sizeof(*attr), 0x00);
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent->owner;
attr->show = show_dev;
attr->store = NULL;
class_device_create_file(class_dev, attr);
class_dev->devt_attr = attr;
}
class_device_add_attrs(class_dev);
if (class_dev->dev)
sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
/* notify any interfaces this device is now here */
if (parent) {
down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children);
@ -421,16 +508,8 @@ int class_device_add(struct class_device *class_dev)
class_intf->add(class_dev);
up(&parent->sem);
}
if (MAJOR(class_dev->devt))
class_device_create_file(class_dev, &class_device_attr_dev);
class_device_add_attrs(class_dev);
if (class_dev->dev)
sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
register_done:
if (error && parent)
class_put(parent);
@ -444,6 +523,58 @@ int class_device_register(struct class_device *class_dev)
return class_device_add(class_dev);
}
/**
* class_device_create - creates a class device and registers it with sysfs
* @cs: pointer to the struct class that this device should be registered to.
* @dev: the dev_t for the char device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
*
* This function can be used by char device classes. A struct
* class_device will be created in sysfs, registered to the specified
* class. A "dev" file will be created, showing the dev_t for the
* device. The pointer to the struct class_device will be returned from
* the call. Any further sysfs files that might be required can be
* created using this pointer.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct class_device *class_device_create(struct class *cls, dev_t devt,
struct device *device, char *fmt, ...)
{
va_list args;
struct class_device *class_dev = NULL;
int retval = -ENODEV;
if (cls == NULL || IS_ERR(cls))
goto error;
class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
if (!class_dev) {
retval = -ENOMEM;
goto error;
}
memset(class_dev, 0x00, sizeof(struct class_device));
class_dev->devt = devt;
class_dev->dev = device;
class_dev->class = cls;
va_start(args, fmt);
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
va_end(args);
retval = class_device_register(class_dev);
if (retval)
goto error;
return class_dev;
error:
kfree(class_dev);
return ERR_PTR(retval);
}
void class_device_del(struct class_device *class_dev)
{
struct class * parent = class_dev->class;
@ -460,6 +591,11 @@ void class_device_del(struct class_device *class_dev)
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
if (class_dev->devt_attr) {
class_device_remove_file(class_dev, class_dev->devt_attr);
kfree(class_dev->devt_attr);
class_dev->devt_attr = NULL;
}
class_device_remove_attrs(class_dev);
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
@ -477,6 +613,32 @@ void class_device_unregister(struct class_device *class_dev)
class_device_put(class_dev);
}
/**
* class_device_destroy - removes a class device that was created with class_device_create()
* @cls: the pointer to the struct class that this device was registered * with.
* @dev: the dev_t of the device that was previously registered.
*
* This call unregisters and cleans up a class device that was created with a
* call to class_device_create()
*/
void class_device_destroy(struct class *cls, dev_t devt)
{
struct class_device *class_dev = NULL;
struct class_device *class_dev_tmp;
down(&cls->sem);
list_for_each_entry(class_dev_tmp, &cls->children, node) {
if (class_dev_tmp->devt == devt) {
class_dev = class_dev_tmp;
break;
}
}
up(&cls->sem);
if (class_dev)
class_device_unregister(class_dev);
}
int class_device_rename(struct class_device *class_dev, char *new_name)
{
int error = 0;
@ -576,6 +738,8 @@ EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
EXPORT_SYMBOL_GPL(class_get);
EXPORT_SYMBOL_GPL(class_put);
EXPORT_SYMBOL_GPL(class_create);
EXPORT_SYMBOL_GPL(class_destroy);
EXPORT_SYMBOL_GPL(class_device_register);
EXPORT_SYMBOL_GPL(class_device_unregister);
@ -584,6 +748,8 @@ EXPORT_SYMBOL_GPL(class_device_add);
EXPORT_SYMBOL_GPL(class_device_del);
EXPORT_SYMBOL_GPL(class_device_get);
EXPORT_SYMBOL_GPL(class_device_put);
EXPORT_SYMBOL_GPL(class_device_create);
EXPORT_SYMBOL_GPL(class_device_destroy);
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
EXPORT_SYMBOL_GPL(class_device_create_bin_file);

View file

@ -1,199 +0,0 @@
/*
* class_simple.c - a "simple" interface for classes for simple char devices.
*
* Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2003-2004 IBM Corp.
*
* This file is released under the GPLv2
*
*/
#include <linux/config.h>
#include <linux/device.h>
#include <linux/err.h>
struct class_simple {
struct class class;
};
#define to_class_simple(d) container_of(d, struct class_simple, class)
struct simple_dev {
struct list_head node;
struct class_device class_dev;
};
#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
static LIST_HEAD(simple_dev_list);
static DEFINE_SPINLOCK(simple_dev_list_lock);
static void release_simple_dev(struct class_device *class_dev)
{
struct simple_dev *s_dev = to_simple_dev(class_dev);
kfree(s_dev);
}
static void class_simple_release(struct class *class)
{
struct class_simple *cs = to_class_simple(class);
kfree(cs);
}
/**
* class_simple_create - create a struct class_simple structure
* @owner: pointer to the module that is to "own" this struct class_simple
* @name: pointer to a string for the name of this class.
*
* This is used to create a struct class_simple pointer that can then be used
* in calls to class_simple_device_add(). This is used when you do not wish to
* create a full blown class support for a type of char devices.
*
* Note, the pointer created here is to be destroyed when finished by making a
* call to class_simple_destroy().
*/
struct class_simple *class_simple_create(struct module *owner, char *name)
{
struct class_simple *cs;
int retval;
cs = kmalloc(sizeof(*cs), GFP_KERNEL);
if (!cs) {
retval = -ENOMEM;
goto error;
}
memset(cs, 0x00, sizeof(*cs));
cs->class.name = name;
cs->class.class_release = class_simple_release;
cs->class.release = release_simple_dev;
retval = class_register(&cs->class);
if (retval)
goto error;
return cs;
error:
kfree(cs);
return ERR_PTR(retval);
}
EXPORT_SYMBOL(class_simple_create);
/**
* class_simple_destroy - destroys a struct class_simple structure
* @cs: pointer to the struct class_simple that is to be destroyed
*
* Note, the pointer to be destroyed must have been created with a call to
* class_simple_create().
*/
void class_simple_destroy(struct class_simple *cs)
{
if ((cs == NULL) || (IS_ERR(cs)))
return;
class_unregister(&cs->class);
}
EXPORT_SYMBOL(class_simple_destroy);
/**
* class_simple_device_add - adds a class device to sysfs for a character driver
* @cs: pointer to the struct class_simple that this device should be registered to.
* @dev: the dev_t for the device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
*
* This function can be used by simple char device classes that do not
* implement their own class device registration. A struct class_device will
* be created in sysfs, registered to the specified class. A "dev" file will
* be created, showing the dev_t for the device. The pointer to the struct
* class_device will be returned from the call. Any further sysfs files that
* might be required can be created using this pointer.
* Note: the struct class_simple passed to this function must have previously been
* created with a call to class_simple_create().
*/
struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
{
va_list args;
struct simple_dev *s_dev = NULL;
int retval;
if ((cs == NULL) || (IS_ERR(cs))) {
retval = -ENODEV;
goto error;
}
s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
if (!s_dev) {
retval = -ENOMEM;
goto error;
}
memset(s_dev, 0x00, sizeof(*s_dev));
s_dev->class_dev.devt = dev;
s_dev->class_dev.dev = device;
s_dev->class_dev.class = &cs->class;
va_start(args, fmt);
vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
va_end(args);
retval = class_device_register(&s_dev->class_dev);
if (retval)
goto error;
spin_lock(&simple_dev_list_lock);
list_add(&s_dev->node, &simple_dev_list);
spin_unlock(&simple_dev_list_lock);
return &s_dev->class_dev;
error:
kfree(s_dev);
return ERR_PTR(retval);
}
EXPORT_SYMBOL(class_simple_device_add);
/**
* class_simple_set_hotplug - set the hotplug callback in the embedded struct class
* @cs: pointer to the struct class_simple to hold the pointer
* @hotplug: function pointer to the hotplug function
*
* Implement and set a hotplug function to add environment variables specific to this
* class on the hotplug event.
*/
int class_simple_set_hotplug(struct class_simple *cs,
int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
{
if ((cs == NULL) || (IS_ERR(cs)))
return -ENODEV;
cs->class.hotplug = hotplug;
return 0;
}
EXPORT_SYMBOL(class_simple_set_hotplug);
/**
* class_simple_device_remove - removes a class device that was created with class_simple_device_add()
* @dev: the dev_t of the device that was previously registered.
*
* This call unregisters and cleans up a class device that was created with a
* call to class_device_simple_add()
*/
void class_simple_device_remove(dev_t dev)
{
struct simple_dev *s_dev = NULL;
int found = 0;
spin_lock(&simple_dev_list_lock);
list_for_each_entry(s_dev, &simple_dev_list, node) {
if (s_dev->class_dev.devt == dev) {
found = 1;
break;
}
}
if (found) {
list_del(&s_dev->node);
spin_unlock(&simple_dev_list_lock);
class_device_unregister(&s_dev->class_dev);
} else {
spin_unlock(&simple_dev_list_lock);
}
}
EXPORT_SYMBOL(class_simple_device_remove);

View file

@ -36,10 +36,10 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (dev_attr->show)
ret = dev_attr->show(dev, buf);
ret = dev_attr->show(dev, dev_attr, buf);
return ret;
}
@ -49,10 +49,10 @@ dev_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (dev_attr->store)
ret = dev_attr->store(dev, buf, count);
ret = dev_attr->store(dev, dev_attr, buf, count);
return ret;
}
@ -102,7 +102,7 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct device *dev = to_dev(kobj);
@ -207,11 +207,9 @@ void device_initialize(struct device *dev)
{
kobj_set_kset_s(dev, devices_subsys);
kobject_init(&dev->kobj);
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->driver_list);
INIT_LIST_HEAD(&dev->bus_list);
klist_init(&dev->klist_children);
INIT_LIST_HEAD(&dev->dma_pools);
init_MUTEX(&dev->sem);
}
/**
@ -250,10 +248,8 @@ int device_add(struct device *dev)
goto PMError;
if ((error = bus_add_device(dev)))
goto BusError;
down_write(&devices_subsys.rwsem);
if (parent)
list_add_tail(&dev->node, &parent->children);
up_write(&devices_subsys.rwsem);
klist_add_tail(&parent->klist_children, &dev->knode_parent);
/* notify platform of device entry */
if (platform_notify)
@ -336,10 +332,8 @@ void device_del(struct device * dev)
{
struct device * parent = dev->parent;
down_write(&devices_subsys.rwsem);
if (parent)
list_del_init(&dev->node);
up_write(&devices_subsys.rwsem);
klist_remove(&dev->knode_parent);
/* Notify the platform of the removal, in case they
* need to do anything...
@ -373,6 +367,12 @@ void device_unregister(struct device * dev)
}
static struct device * next_device(struct klist_iter * i)
{
struct klist_node * n = klist_next(i);
return n ? container_of(n, struct device, knode_parent) : NULL;
}
/**
* device_for_each_child - device child iterator.
* @dev: parent struct device.
@ -385,39 +385,20 @@ void device_unregister(struct device * dev)
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*/
int device_for_each_child(struct device * dev, void * data,
int device_for_each_child(struct device * parent, void * data,
int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device * child;
int error = 0;
down_read(&devices_subsys.rwsem);
list_for_each_entry(child, &dev->children, node) {
if((error = fn(child, data)))
break;
}
up_read(&devices_subsys.rwsem);
klist_iter_init(&parent->klist_children, &i);
while ((child = next_device(&i)) && !error)
error = fn(child, data);
klist_iter_exit(&i);
return error;
}
/**
* device_find - locate device on a bus by name.
* @name: name of the device.
* @bus: bus to scan for the device.
*
* Call kset_find_obj() to iterate over list of devices on
* a bus to find device by name. Return device if found.
*
* Note that kset_find_obj increments device's reference count.
*/
struct device *device_find(const char *name, struct bus_type *bus)
{
struct kobject *k = kset_find_obj(&bus->devices, name);
if (k)
return to_dev(k);
return NULL;
}
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
@ -433,7 +414,6 @@ EXPORT_SYMBOL_GPL(device_del);
EXPORT_SYMBOL_GPL(device_unregister);
EXPORT_SYMBOL_GPL(get_device);
EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_find);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);

248
drivers/base/dd.c Normal file
View file

@ -0,0 +1,248 @@
/*
* drivers/base/dd.c - The core device/driver interactions.
*
* This file contains the (sometimes tricky) code that controls the
* interactions between devices and drivers, which primarily includes
* driver binding and unbinding.
*
* All of this code used to exist in drivers/base/bus.c, but was
* relocated to here in the name of compartmentalization (since it wasn't
* strictly code just for the 'struct bus_type'.
*
* Copyright (c) 2002-5 Patrick Mochel
* Copyright (c) 2002-3 Open Source Development Labs
*
* This file is released under the GPLv2
*/
#include <linux/device.h>
#include <linux/module.h>
#include "base.h"
#include "power/power.h"
#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
/**
* device_bind_driver - bind a driver to one device.
* @dev: device.
*
* Allow manual attachment of a driver to a device.
* Caller must have already set @dev->driver.
*
* Note that this does not modify the bus reference count
* nor take the bus's rwsem. Please verify those are accounted
* for before calling this. (It is ok to call with no other effort
* from a driver's probe() method.)
*
* This function must be called with @dev->sem held.
*/
void device_bind_driver(struct device * dev)
{
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
}
/**
* driver_probe_device - attempt to bind device & driver.
* @drv: driver.
* @dev: device.
*
* First, we call the bus's match function, if one present, which
* should compare the device IDs the driver supports with the
* device IDs of the device. Note we don't do this ourselves
* because we don't know the format of the ID structures, nor what
* is to be considered a match and what is not.
*
*
* This function returns 1 if a match is found, an error if one
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
*
* This function must be called with @dev->sem held.
*/
static int driver_probe_device(struct device_driver * drv, struct device * dev)
{
int ret = 0;
if (drv->bus->match && !drv->bus->match(dev, drv))
goto Done;
pr_debug("%s: Matched Device %s with Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
dev->driver = drv;
if (drv->probe) {
ret = drv->probe(dev);
if (ret) {
dev->driver = NULL;
goto ProbeFailed;
}
}
device_bind_driver(dev);
ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
goto Done;
ProbeFailed:
if (ret == -ENODEV || ret == -ENXIO) {
/* Driver matched, but didn't support device
* or device not found.
* Not an error; keep going.
*/
ret = 0;
} else {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev->bus_id, ret);
}
Done:
return ret;
}
static int __device_attach(struct device_driver * drv, void * data)
{
struct device * dev = data;
return driver_probe_device(drv, dev);
}
/**
* device_attach - try to attach device to a driver.
* @dev: device.
*
* Walk the list of drivers that the bus has and call
* driver_probe_device() for each pair. If a compatible
* pair is found, break out and return.
*
* Returns 1 if the device was bound to a driver;
* 0 if no matching device was found; error code otherwise.
*/
int device_attach(struct device * dev)
{
int ret = 0;
down(&dev->sem);
if (dev->driver) {
device_bind_driver(dev);
ret = 1;
} else
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
up(&dev->sem);
return ret;
}
static int __driver_attach(struct device * dev, void * data)
{
struct device_driver * drv = data;
/*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/
down(&dev->sem);
if (!dev->driver)
driver_probe_device(drv, dev);
up(&dev->sem);
return 0;
}
/**
* driver_attach - try to bind driver to devices.
* @drv: driver.
*
* Walk the list of devices that the bus has on it and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*/
void driver_attach(struct device_driver * drv)
{
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
/**
* device_release_driver - manually detach device from driver.
* @dev: device.
*
* Manually detach device from driver.
*
* __device_release_driver() must be called with @dev->sem held.
*/
static void __device_release_driver(struct device * dev)
{
struct device_driver * drv;
drv = dev->driver;
if (drv) {
get_driver(drv);
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
if (drv->remove)
drv->remove(dev);
dev->driver = NULL;
put_driver(drv);
}
}
void device_release_driver(struct device * dev)
{
/*
* If anyone calls device_release_driver() recursively from
* within their ->remove callback for the same device, they
* will deadlock right here.
*/
down(&dev->sem);
__device_release_driver(dev);
up(&dev->sem);
}
/**
* driver_detach - detach driver from all devices it controls.
* @drv: driver.
*/
void driver_detach(struct device_driver * drv)
{
struct device * dev;
for (;;) {
spin_lock_irq(&drv->klist_devices.k_lock);
if (list_empty(&drv->klist_devices.k_list)) {
spin_unlock_irq(&drv->klist_devices.k_lock);
break;
}
dev = list_entry(drv->klist_devices.k_list.prev,
struct device, knode_driver.n_node);
get_device(dev);
spin_unlock_irq(&drv->klist_devices.k_lock);
down(&dev->sem);
if (dev->driver == drv)
__device_release_driver(dev);
up(&dev->sem);
put_device(dev);
}
}
EXPORT_SYMBOL_GPL(device_bind_driver);
EXPORT_SYMBOL_GPL(device_release_driver);
EXPORT_SYMBOL_GPL(device_attach);
EXPORT_SYMBOL_GPL(driver_attach);

View file

@ -41,7 +41,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */
static DECLARE_MUTEX (pools_lock);
static ssize_t
show_pools (struct device *dev, char *buf)
show_pools (struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned temp;
unsigned size;

View file

@ -18,6 +18,43 @@
#define to_dev(node) container_of(node, struct device, driver_list)
#define to_drv(obj) container_of(obj, struct device_driver, kobj)
static struct device * next_device(struct klist_iter * i)
{
struct klist_node * n = klist_next(i);
return n ? container_of(n, struct device, knode_driver) : NULL;
}
/**
* driver_for_each_device - Iterator for devices bound to a driver.
* @drv: Driver we're iterating.
* @data: Data to pass to the callback.
* @fn: Function to call for each device.
*
* Iterate over the @drv's list of devices calling @fn for each one.
*/
int driver_for_each_device(struct device_driver * drv, struct device * start,
void * data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device * dev;
int error = 0;
if (!drv)
return -EINVAL;
klist_iter_init_node(&drv->klist_devices, &i,
start ? &start->knode_driver : NULL);
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
EXPORT_SYMBOL_GPL(driver_for_each_device);
/**
* driver_create_file - create sysfs file for driver.
* @drv: driver.
@ -85,7 +122,7 @@ void put_driver(struct device_driver * drv)
*/
int driver_register(struct device_driver * drv)
{
INIT_LIST_HEAD(&drv->devices);
klist_init(&drv->klist_devices);
init_completion(&drv->unloaded);
return bus_add_driver(drv);
}

View file

@ -136,7 +136,7 @@ static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
*
* Initialize and register the node device.
*/
int __init register_node(struct node *node, int num, struct node *parent)
int register_node(struct node *node, int num, struct node *parent)
{
int error;
@ -153,8 +153,24 @@ int __init register_node(struct node *node, int num, struct node *parent)
return error;
}
/**
* unregister_node - unregister a node device
* @node: node going away
*
* Unregisters a node device @node. All the devices on the node must be
* unregistered before calling this function.
*/
void unregister_node(struct node *node)
{
sysdev_remove_file(&node->sysdev, &attr_cpumap);
sysdev_remove_file(&node->sysdev, &attr_meminfo);
sysdev_remove_file(&node->sysdev, &attr_numastat);
sysdev_remove_file(&node->sysdev, &attr_distance);
int __init register_node_type(void)
sysdev_unregister(&node->sysdev);
}
static int __init register_node_type(void)
{
return sysdev_class_register(&node_class);
}

View file

@ -22,6 +22,9 @@ extern int sysdev_resume(void);
int resume_device(struct device * dev)
{
int error = 0;
down(&dev->sem);
if (dev->power.pm_parent
&& dev->power.pm_parent->power.power_state) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
@ -31,9 +34,10 @@ int resume_device(struct device * dev)
}
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
return dev->bus->resume(dev);
error = dev->bus->resume(dev);
}
return 0;
up(&dev->sem);
return error;
}

View file

@ -39,6 +39,7 @@ int suspend_device(struct device * dev, pm_message_t state)
{
int error = 0;
down(&dev->sem);
if (dev->power.power_state) {
dev_dbg(dev, "PM: suspend %d-->%d\n",
dev->power.power_state, state);
@ -58,7 +59,7 @@ int suspend_device(struct device * dev, pm_message_t state)
dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
}
up(&dev->sem);
return error;
}
@ -113,8 +114,19 @@ int device_suspend(pm_message_t state)
put_device(dev);
}
up(&dpm_list_sem);
if (error)
if (error) {
/* we failed... before resuming, bring back devices from
* dpm_off_irq list back to main dpm_off list, we do want
* to call resume() on them, in case they partially suspended
* despite returning -EAGAIN
*/
while (!list_empty(&dpm_off_irq)) {
struct list_head * entry = dpm_off_irq.next;
list_del(entry);
list_add(entry, &dpm_off);
}
dpm_resume();
}
up(&dpm_sem);
return error;
}

View file

@ -24,12 +24,12 @@
* low-power state.
*/
static ssize_t state_show(struct device * dev, char * buf)
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
return sprintf(buf, "%u\n", dev->power.power_state);
}
static ssize_t state_store(struct device * dev, const char * buf, size_t n)
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
u32 state;
char * rest;

View file

@ -37,7 +37,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
if (sysdev_attr->show)
return sysdev_attr->show(sysdev, buffer);
return 0;
return -EIO;
}
@ -50,7 +50,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr,
if (sysdev_attr->store)
return sysdev_attr->store(sysdev, buffer, count);
return 0;
return -EIO;
}
static struct sysfs_ops sysfs_ops = {

View file

@ -36,7 +36,7 @@ static int emsgs_head_idx, emsgs_tail_idx;
static struct semaphore emsgs_sema;
static spinlock_t emsgs_lock;
static int nblocked_emsgs_readers;
static struct class_simple *aoe_class;
static struct class *aoe_class;
static struct aoe_chardev chardevs[] = {
{ MINOR_ERR, "err" },
{ MINOR_DISCOVER, "discover" },
@ -218,13 +218,13 @@ aoechr_init(void)
}
sema_init(&emsgs_sema, 0);
spin_lock_init(&emsgs_lock);
aoe_class = class_simple_create(THIS_MODULE, "aoe");
aoe_class = class_create(THIS_MODULE, "aoe");
if (IS_ERR(aoe_class)) {
unregister_chrdev(AOE_MAJOR, "aoechr");
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
class_simple_device_add(aoe_class,
class_device_create(aoe_class,
MKDEV(AOE_MAJOR, chardevs[i].minor),
NULL, chardevs[i].name);
@ -237,8 +237,8 @@ aoechr_exit(void)
int i;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
class_simple_device_remove(MKDEV(AOE_MAJOR, chardevs[i].minor));
class_simple_destroy(aoe_class);
class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
class_destroy(aoe_class);
unregister_chrdev(AOE_MAJOR, "aoechr");
}

View file

@ -2044,7 +2044,7 @@ as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct as_fs_entry *entry = to_as(attr);
if (!entry->show)
return 0;
return -EIO;
return entry->show(e->elevator_data, page);
}
@ -2057,7 +2057,7 @@ as_attr_store(struct kobject *kobj, struct attribute *attr,
struct as_fs_entry *entry = to_as(attr);
if (!entry->store)
return -EINVAL;
return -EIO;
return entry->store(e->elevator_data, page, length);
}

View file

@ -1775,7 +1775,7 @@ cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct cfq_fs_entry *entry = to_cfq(attr);
if (!entry->show)
return 0;
return -EIO;
return entry->show(e->elevator_data, page);
}
@ -1788,7 +1788,7 @@ cfq_attr_store(struct kobject *kobj, struct attribute *attr,
struct cfq_fs_entry *entry = to_cfq(attr);
if (!entry->store)
return -EINVAL;
return -EIO;
return entry->store(e->elevator_data, page, length);
}

View file

@ -886,7 +886,7 @@ deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct deadline_fs_entry *entry = to_deadline(attr);
if (!entry->show)
return 0;
return -EIO;
return entry->show(e->elevator_data, page);
}
@ -899,7 +899,7 @@ deadline_attr_store(struct kobject *kobj, struct attribute *attr,
struct deadline_fs_entry *entry = to_deadline(attr);
if (!entry->store)
return -EINVAL;
return -EIO;
return entry->store(e->elevator_data, page, length);
}

View file

@ -322,7 +322,7 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
struct gendisk *disk = to_disk(kobj);
struct disk_attribute *disk_attr =
container_of(attr,struct disk_attribute,attr);
ssize_t ret = 0;
ssize_t ret = -EIO;
if (disk_attr->show)
ret = disk_attr->show(disk,page);

View file

@ -3574,7 +3574,7 @@ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
q = container_of(kobj, struct request_queue, kobj);
if (!entry->show)
return 0;
return -EIO;
return entry->show(q, page);
}
@ -3588,7 +3588,7 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
q = container_of(kobj, struct request_queue, kobj);
if (!entry->store)
return -EINVAL;
return -EIO;
return entry->store(q, page, length);
}

View file

@ -222,7 +222,7 @@ static int pg_identify(struct pg *dev, int log);
static char pg_scratch[512]; /* scratch block buffer */
static struct class_simple *pg_class;
static struct class *pg_class;
/* kernel glue structures */
@ -666,7 +666,7 @@ static int __init pg_init(void)
err = -1;
goto out;
}
pg_class = class_simple_create(THIS_MODULE, "pg");
pg_class = class_create(THIS_MODULE, "pg");
if (IS_ERR(pg_class)) {
err = PTR_ERR(pg_class);
goto out_chrdev;
@ -675,7 +675,7 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
class_simple_device_add(pg_class, MKDEV(major, unit),
class_device_create(pg_class, MKDEV(major, unit),
NULL, "pg%u", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
@ -688,8 +688,8 @@ static int __init pg_init(void)
goto out;
out_class:
class_simple_device_remove(MKDEV(major, unit));
class_simple_destroy(pg_class);
class_device_destroy(pg_class, MKDEV(major, unit));
class_destroy(pg_class);
out_chrdev:
unregister_chrdev(major, "pg");
out:
@ -703,11 +703,11 @@ static void __exit pg_exit(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
class_simple_device_remove(MKDEV(major, unit));
class_device_destroy(pg_class, MKDEV(major, unit));
devfs_remove("pg/%u", unit);
}
}
class_simple_destroy(pg_class);
class_destroy(pg_class);
devfs_remove("pg");
unregister_chrdev(major, name);

View file

@ -242,7 +242,7 @@ static struct file_operations pt_fops = {
};
/* sysfs class support */
static struct class_simple *pt_class;
static struct class *pt_class;
static inline int status_reg(struct pi_adapter *pi)
{
@ -963,7 +963,7 @@ static int __init pt_init(void)
err = -1;
goto out;
}
pt_class = class_simple_create(THIS_MODULE, "pt");
pt_class = class_create(THIS_MODULE, "pt");
if (IS_ERR(pt_class)) {
err = PTR_ERR(pt_class);
goto out_chrdev;
@ -972,29 +972,29 @@ static int __init pt_init(void)
devfs_mk_dir("pt");
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
class_simple_device_add(pt_class, MKDEV(major, unit),
class_device_create(pt_class, MKDEV(major, unit),
NULL, "pt%d", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%d", unit);
if (err) {
class_simple_device_remove(MKDEV(major, unit));
class_device_destroy(pt_class, MKDEV(major, unit));
goto out_class;
}
class_simple_device_add(pt_class, MKDEV(major, unit + 128),
class_device_create(pt_class, MKDEV(major, unit + 128),
NULL, "pt%dn", unit);
err = devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%dn", unit);
if (err) {
class_simple_device_remove(MKDEV(major, unit + 128));
class_device_destroy(pt_class, MKDEV(major, unit + 128));
goto out_class;
}
}
goto out;
out_class:
class_simple_destroy(pt_class);
class_destroy(pt_class);
out_chrdev:
unregister_chrdev(major, "pt");
out:
@ -1006,12 +1006,12 @@ static void __exit pt_exit(void)
int unit;
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
class_simple_device_remove(MKDEV(major, unit));
class_device_destroy(pt_class, MKDEV(major, unit));
devfs_remove("pt/%d", unit);
class_simple_device_remove(MKDEV(major, unit + 128));
class_device_destroy(pt_class, MKDEV(major, unit + 128));
devfs_remove("pt/%dn", unit);
}
class_simple_destroy(pt_class);
class_destroy(pt_class);
devfs_remove("pt");
unregister_chrdev(major, name);
for (unit = 0; unit < PT_UNITS; unit++)

View file

@ -430,7 +430,7 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
}
}
static ssize_t ub_diag_show(struct device *dev, char *page)
static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page)
{
struct usb_interface *intf;
struct ub_dev *sc;

View file

@ -144,7 +144,7 @@ static struct dsp56k_device {
int tx_wsize, rx_wsize;
} dsp56k;
static struct class_simple *dsp56k_class;
static struct class *dsp56k_class;
static int dsp56k_reset(void)
{
@ -510,12 +510,12 @@ static int __init dsp56k_init_driver(void)
printk("DSP56k driver: Unable to register driver\n");
return -ENODEV;
}
dsp56k_class = class_simple_create(THIS_MODULE, "dsp56k");
dsp56k_class = class_create(THIS_MODULE, "dsp56k");
if (IS_ERR(dsp56k_class)) {
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
class_simple_device_add(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
@ -526,8 +526,8 @@ static int __init dsp56k_init_driver(void)
goto out;
out_class:
class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
class_simple_destroy(dsp56k_class);
class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
class_destroy(dsp56k_class);
out_chrdev:
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
out:
@ -537,8 +537,8 @@ module_init(dsp56k_init_driver);
static void __exit dsp56k_cleanup_driver(void)
{
class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
class_simple_destroy(dsp56k_class);
class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
class_destroy(dsp56k_class);
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
devfs_remove("dsp56k");
}

View file

@ -99,7 +99,7 @@ static struct file_operations zft_cdev =
.release = zft_close,
};
static struct class_simple *zft_class;
static struct class *zft_class;
/* Open floppy tape device
*/
@ -329,29 +329,29 @@ KERN_INFO
"installing zftape VFS interface for ftape driver ...");
TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
zft_class = class_simple_create(THIS_MODULE, "zft");
zft_class = class_create(THIS_MODULE, "zft");
for (i = 0; i < 4; i++) {
class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"qft%i", i);
class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
S_IFCHR | S_IRUSR | S_IWUSR,
"nqft%i", i);
class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
S_IFCHR | S_IRUSR | S_IWUSR,
"zqft%i", i);
class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
S_IFCHR | S_IRUSR | S_IWUSR,
"nzqft%i", i);
class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
S_IFCHR | S_IRUSR | S_IWUSR,
"rawqft%i", i);
class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
S_IFCHR | S_IRUSR | S_IWUSR,
"nrawqft%i", i);
@ -381,19 +381,19 @@ static void zft_exit(void)
}
for (i = 0; i < 4; i++) {
devfs_remove("qft%i", i);
class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i));
class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
devfs_remove("nqft%i", i);
class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 4));
class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
devfs_remove("zqft%i", i);
class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 16));
class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
devfs_remove("nzqft%i", i);
class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 20));
class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
devfs_remove("rawqft%i", i);
class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 32));
class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
devfs_remove("nrawqft%i", i);
class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 36));
class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
}
class_simple_destroy(zft_class);
class_destroy(zft_class);
zft_uninit_mem(); /* release remaining memory, if any */
printk(KERN_INFO "zftape successfully unloaded.\n");
TRACE_EXIT;

View file

@ -1466,7 +1466,7 @@ static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
}
/* The sysfs interface for the driver and devices */
static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@ -1480,7 +1480,7 @@ static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
}
static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@ -1494,7 +1494,7 @@ static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
}
static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
size_t count)
{
/*
@ -1505,7 +1505,7 @@ static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
return -EPERM;
}
static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@ -1521,7 +1521,7 @@ static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
static DEVICE_ATTR(current_vty,
S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct vio_dev *viod = to_vio_dev(dev);
@ -1559,7 +1559,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
return count;
}
static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@ -1574,7 +1574,7 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
hvcs_vterm_state_show, hvcs_vterm_state_store);
static ssize_t hvcs_index_show(struct device *dev, char *buf)
static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);

View file

@ -302,7 +302,7 @@ static char rirqs[IP2_MAX_BOARDS];
static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
/* for sysfs class support */
static struct class_simple *ip2_class;
static struct class *ip2_class;
// Some functions to keep track of what irq's we have
@ -414,9 +414,9 @@ cleanup_module(void)
iiResetDelay( i2BoardPtrTable[i] );
/* free io addresses and Tibet */
release_region( ip2config.addr[i], 8 );
class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i));
class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
devfs_remove("ip2/ipl%d", i);
class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
devfs_remove("ip2/stat%d", i);
}
/* Disable and remove interrupt handler. */
@ -425,7 +425,7 @@ cleanup_module(void)
clear_requested_irq( ip2config.irq[i]);
}
}
class_simple_destroy(ip2_class);
class_destroy(ip2_class);
devfs_remove("ip2");
if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
@ -700,7 +700,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
} else {
/* create the sysfs class */
ip2_class = class_simple_create(THIS_MODULE, "ip2");
ip2_class = class_create(THIS_MODULE, "ip2");
if (IS_ERR(ip2_class)) {
err = PTR_ERR(ip2_class);
goto out_chrdev;
@ -722,25 +722,25 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR,
class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
4 * i), NULL, "ipl%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/ipl%d", i);
if (err) {
class_simple_device_remove(MKDEV(IP2_IPL_MAJOR,
4 * i));
class_device_destroy(ip2_class,
MKDEV(IP2_IPL_MAJOR, 4 * i));
goto out_class;
}
class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR,
class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
4 * i + 1), NULL, "stat%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/stat%d", i);
if (err) {
class_simple_device_remove(MKDEV(IP2_IPL_MAJOR,
4 * i + 1));
class_device_destroy(ip2_class,
MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
goto out_class;
}
@ -798,7 +798,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
goto out;
out_class:
class_simple_destroy(ip2_class);
class_destroy(ip2_class);
out_chrdev:
unregister_chrdev(IP2_IPL_MAJOR, "ip2");
out:

View file

@ -520,7 +520,7 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
" interface. Other values will set the major device number"
" to that value.");
static struct class_simple *ipmi_class;
static struct class *ipmi_class;
static void ipmi_new_smi(int if_num)
{
@ -529,12 +529,12 @@ static void ipmi_new_smi(int if_num)
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num);
class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
}
static void ipmi_smi_gone(int if_num)
{
class_simple_device_remove(MKDEV(ipmi_major, if_num));
class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
devfs_remove("ipmidev/%d", if_num);
}
@ -555,7 +555,7 @@ static __init int init_ipmi_devintf(void)
printk(KERN_INFO "ipmi device interface version "
IPMI_DEVINTF_VERSION "\n");
ipmi_class = class_simple_create(THIS_MODULE, "ipmi");
ipmi_class = class_create(THIS_MODULE, "ipmi");
if (IS_ERR(ipmi_class)) {
printk(KERN_ERR "ipmi: can't register device class\n");
return PTR_ERR(ipmi_class);
@ -563,7 +563,7 @@ static __init int init_ipmi_devintf(void)
rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
if (rv < 0) {
class_simple_destroy(ipmi_class);
class_destroy(ipmi_class);
printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
return rv;
}
@ -577,7 +577,7 @@ static __init int init_ipmi_devintf(void)
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
unregister_chrdev(ipmi_major, DEVICE_NAME);
class_simple_destroy(ipmi_class);
class_destroy(ipmi_class);
printk(KERN_WARNING "ipmi: can't register smi watcher\n");
return rv;
}
@ -588,7 +588,7 @@ module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
{
class_simple_destroy(ipmi_class);
class_destroy(ipmi_class);
ipmi_smi_watcher_unregister(&smi_watcher);
devfs_remove(DEVICE_NAME);
unregister_chrdev(ipmi_major, DEVICE_NAME);

View file

@ -792,7 +792,7 @@ static int stli_timeron;
/*****************************************************************************/
static struct class_simple *istallion_class;
static struct class *istallion_class;
#ifdef MODULE
@ -854,10 +854,10 @@ static void __exit istallion_module_exit(void)
put_tty_driver(stli_serial);
for (i = 0; i < 4; i++) {
devfs_remove("staliomem/%d", i);
class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
}
devfs_remove("staliomem");
class_simple_destroy(istallion_class);
class_destroy(istallion_class);
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
@ -5242,12 +5242,12 @@ int __init stli_init(void)
"device\n");
devfs_mk_dir("staliomem");
istallion_class = class_simple_create(THIS_MODULE, "staliomem");
istallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++) {
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"staliomem/%d", i);
class_simple_device_add(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
NULL, "staliomem%d", i);
}

View file

@ -146,7 +146,7 @@
static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
static struct class_simple *lp_class;
static struct class *lp_class;
#ifdef CONFIG_LP_CONSOLE
static struct parport *console_registered; // initially NULL
@ -804,7 +804,7 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL,
class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr);
@ -907,7 +907,7 @@ static int __init lp_init (void)
}
devfs_mk_dir("printers");
lp_class = class_simple_create(THIS_MODULE, "printer");
lp_class = class_create(THIS_MODULE, "printer");
if (IS_ERR(lp_class)) {
err = PTR_ERR(lp_class);
goto out_devfs;
@ -930,7 +930,7 @@ static int __init lp_init (void)
return 0;
out_class:
class_simple_destroy(lp_class);
class_destroy(lp_class);
out_devfs:
devfs_remove("printers");
unregister_chrdev(LP_MAJOR, "lp");
@ -981,10 +981,10 @@ static void lp_cleanup_module (void)
continue;
parport_unregister_device(lp_table[offset].dev);
devfs_remove("printers/%d", offset);
class_simple_device_remove(MKDEV(LP_MAJOR, offset));
class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
}
devfs_remove("printers");
class_simple_destroy(lp_class);
class_destroy(lp_class);
}
__setup("lp=", lp_setup);

View file

@ -699,7 +699,7 @@ static inline int mbcs_hw_init(struct mbcs_soft *soft)
return 0;
}
static ssize_t show_algo(struct device *dev, char *buf)
static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cx_dev *cx_dev = to_cx_dev(dev);
struct mbcs_soft *soft = cx_dev->soft;
@ -715,7 +715,7 @@ static ssize_t show_algo(struct device *dev, char *buf)
(debug0 >> 32), (debug0 & 0xffffffff));
}
static ssize_t store_algo(struct device *dev, const char *buf, size_t count)
static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int n;
struct cx_dev *cx_dev = to_cx_dev(dev);

View file

@ -856,7 +856,7 @@ static const struct {
{11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops},
};
static struct class_simple *mem_class;
static struct class *mem_class;
static int __init chr_dev_init(void)
{
@ -865,10 +865,9 @@ static int __init chr_dev_init(void)
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
mem_class = class_simple_create(THIS_MODULE, "mem");
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) {
class_simple_device_add(mem_class,
MKDEV(MEM_MAJOR, devlist[i].minor),
class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name);
devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
S_IFCHR | devlist[i].mode, devlist[i].name);

View file

@ -177,10 +177,10 @@ static int misc_open(struct inode * inode, struct file * file)
/*
* TODO for 2.7:
* - add a struct class_device to struct miscdevice and make all usages of
* - add a struct kref to struct miscdevice and make all usages of
* them dynamic.
*/
static struct class_simple *misc_class;
static struct class *misc_class;
static struct file_operations misc_fops = {
.owner = THIS_MODULE,
@ -238,8 +238,8 @@ int misc_register(struct miscdevice * misc)
}
dev = MKDEV(MISC_MAJOR, misc->minor);
misc->class = class_simple_device_add(misc_class, dev,
misc->dev, misc->name);
misc->class = class_device_create(misc_class, dev, misc->dev,
"%s", misc->name);
if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class);
goto out;
@ -248,7 +248,7 @@ int misc_register(struct miscdevice * misc)
err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,
misc->devfs_name);
if (err) {
class_simple_device_remove(dev);
class_device_destroy(misc_class, dev);
goto out;
}
@ -281,7 +281,7 @@ int misc_deregister(struct miscdevice * misc)
down(&misc_sem);
list_del(&misc->list);
class_simple_device_remove(MKDEV(MISC_MAJOR, misc->minor));
class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
devfs_remove(misc->devfs_name);
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
@ -302,7 +302,7 @@ static int __init misc_init(void)
if (ent)
ent->proc_fops = &misc_proc_fops;
#endif
misc_class = class_simple_create(THIS_MODULE, "misc");
misc_class = class_create(THIS_MODULE, "misc");
if (IS_ERR(misc_class))
return PTR_ERR(misc_class);
#ifdef CONFIG_MVME16x
@ -323,7 +323,7 @@ static int __init misc_init(void)
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
class_simple_destroy(misc_class);
class_destroy(misc_class);
return -EIO;
}
return 0;

View file

@ -472,7 +472,7 @@ struct device mwave_device;
/* Prevent code redundancy, create a macro for mwave_show_* functions. */
#define mwave_show_function(attr_name, format_string, field) \
static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \
static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
DSP_3780I_CONFIG_SETTINGS *pSettings = \
&mwave_s_mdd.rBDData.rDspSettings; \

View file

@ -737,7 +737,7 @@ static unsigned int pp_poll (struct file * file, poll_table * wait)
return mask;
}
static struct class_simple *ppdev_class;
static struct class *ppdev_class;
static struct file_operations pp_fops = {
.owner = THIS_MODULE,
@ -752,13 +752,13 @@ static struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
class_simple_device_add(ppdev_class, MKDEV(PP_MAJOR, port->number),
class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number);
}
static void pp_detach(struct parport *port)
{
class_simple_device_remove(MKDEV(PP_MAJOR, port->number));
class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
}
static struct parport_driver pp_driver = {
@ -776,7 +776,7 @@ static int __init ppdev_init (void)
PP_MAJOR);
return -EIO;
}
ppdev_class = class_simple_create(THIS_MODULE, CHRDEV);
ppdev_class = class_create(THIS_MODULE, CHRDEV);
if (IS_ERR(ppdev_class)) {
err = PTR_ERR(ppdev_class);
goto out_chrdev;
@ -798,7 +798,7 @@ static int __init ppdev_init (void)
for (i = 0; i < PARPORT_MAX; i++)
devfs_remove("parports/%d", i);
devfs_remove("parports");
class_simple_destroy(ppdev_class);
class_destroy(ppdev_class);
out_chrdev:
unregister_chrdev(PP_MAJOR, CHRDEV);
out:
@ -813,7 +813,7 @@ static void __exit ppdev_cleanup (void)
devfs_remove("parports/%d", i);
parport_unregister_driver(&pp_driver);
devfs_remove("parports");
class_simple_destroy(ppdev_class);
class_destroy(ppdev_class);
unregister_chrdev (PP_MAJOR, CHRDEV);
}

View file

@ -27,7 +27,7 @@ struct raw_device_data {
int inuse;
};
static struct class_simple *raw_class;
static struct class *raw_class;
static struct raw_device_data raw_devices[MAX_RAW_MINORS];
static DECLARE_MUTEX(raw_mutex);
static struct file_operations raw_ctl_fops; /* forward declaration */
@ -127,8 +127,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor);
}
@ -200,8 +200,8 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
rawdev->binding = NULL;
class_simple_device_remove(MKDEV(RAW_MAJOR,
rq.raw_minor));
class_device_destroy(raw_class,
MKDEV(RAW_MAJOR, rq.raw_minor));
} else {
rawdev->binding = bdget(dev);
if (rawdev->binding == NULL)
@ -300,14 +300,14 @@ static int __init raw_init(void)
goto error;
}
raw_class = class_simple_create(THIS_MODULE, "raw");
raw_class = class_create(THIS_MODULE, "raw");
if (IS_ERR(raw_class)) {
printk(KERN_ERR "Error creating raw class.\n");
cdev_del(&raw_cdev);
unregister_chrdev_region(dev, MAX_RAW_MINORS);
goto error;
}
class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
S_IFCHR | S_IRUGO | S_IWUGO,
@ -331,8 +331,8 @@ static void __exit raw_exit(void)
devfs_remove("raw/raw%d", i);
devfs_remove("raw/rawctl");
devfs_remove("raw");
class_simple_device_remove(MKDEV(RAW_MAJOR, 0));
class_simple_destroy(raw_class);
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
class_destroy(raw_class);
cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
}

View file

@ -357,6 +357,8 @@ static struct file_operations scdrv_fops = {
.release = scdrv_release,
};
static struct class *snsc_class;
/*
* scdrv_init
*
@ -372,7 +374,6 @@ scdrv_init(void)
char *devnamep;
struct sysctl_data_s *scd;
void *salbuf;
struct class_simple *snsc_class;
dev_t first_dev, dev;
nasid_t event_nasid = ia64_sn_get_console_nasid();
@ -382,7 +383,7 @@ scdrv_init(void)
__FUNCTION__);
return -ENODEV;
}
snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
for (cnode = 0; cnode < numionodes; cnode++) {
geoid = cnodeid_get_geoid(cnode);
@ -436,7 +437,7 @@ scdrv_init(void)
continue;
}
class_simple_device_add(snsc_class, dev, NULL,
class_device_create(snsc_class, dev, NULL,
"%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,

View file

@ -719,7 +719,7 @@ static struct file_operations stl_fsiomem = {
/*****************************************************************************/
static struct class_simple *stallion_class;
static struct class *stallion_class;
/*
* Loadable module initialization stuff.
@ -777,13 +777,13 @@ static void __exit stallion_module_exit(void)
}
for (i = 0; i < 4; i++) {
devfs_remove("staliomem/%d", i);
class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
}
devfs_remove("staliomem");
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
class_simple_destroy(stallion_class);
class_destroy(stallion_class);
if (stl_tmpwritebuf != (char *) NULL)
kfree(stl_tmpwritebuf);
@ -3090,12 +3090,12 @@ static int __init stl_init(void)
printk("STALLION: failed to register serial board device\n");
devfs_mk_dir("staliomem");
stallion_class = class_simple_create(THIS_MODULE, "staliomem");
stallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++) {
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR,
"staliomem/%d", i);
class_simple_device_add(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
}
stl_serial->owner = THIS_MODULE;

View file

@ -90,7 +90,7 @@ static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
static unsigned int tp_count; /* tipar count */
static unsigned long opened; /* opened devices */
static struct class_simple *tipar_class;
static struct class *tipar_class;
/* --- macros for parport access -------------------------------------- */
@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
goto out;
}
class_simple_device_add(tipar_class, MKDEV(TIPAR_MAJOR,
class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
TIPAR_MINOR + nr), NULL, "par%d", nr);
/* Use devfs, tree: /dev/ticables/par/[0..2] */
err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
@ -458,8 +458,8 @@ tipar_register(int nr, struct parport *port)
goto out;
out_class:
class_simple_device_remove(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
class_simple_destroy(tipar_class);
class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
class_destroy(tipar_class);
out:
return err;
}
@ -505,7 +505,7 @@ tipar_init_module(void)
/* Use devfs with tree: /dev/ticables/par/[0..2] */
devfs_mk_dir("ticables/par");
tipar_class = class_simple_create(THIS_MODULE, "ticables");
tipar_class = class_create(THIS_MODULE, "ticables");
if (IS_ERR(tipar_class)) {
err = PTR_ERR(tipar_class);
goto out_chrdev;
@ -539,10 +539,10 @@ tipar_cleanup_module(void)
if (table[i].dev == NULL)
continue;
parport_unregister_device(table[i].dev);
class_simple_device_remove(MKDEV(TIPAR_MAJOR, i));
class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
devfs_remove("ticables/par/%d", i);
}
class_simple_destroy(tipar_class);
class_destroy(tipar_class);
devfs_remove("ticables/par");
pr_info("tipar: module unloaded\n");

View file

@ -212,7 +212,7 @@ static u8 pcrread[] = {
0, 0, 0, 0 /* PCR index */
};
static ssize_t show_pcrs(struct device *dev, char *buf)
static ssize_t show_pcrs(struct device *dev, struct device_attribute *attr, char *buf)
{
u8 data[READ_PCR_RESULT_SIZE];
ssize_t len;
@ -255,7 +255,7 @@ static u8 readpubek[] = {
0, 0, 0, 124, /* TPM_ORD_ReadPubek */
};
static ssize_t show_pubek(struct device *dev, char *buf)
static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, char *buf)
{
u8 data[READ_PUBEK_RESULT_SIZE];
ssize_t len;
@ -330,7 +330,7 @@ static u8 cap_manufacturer[] = {
0, 0, 1, 3
};
static ssize_t show_caps(struct device *dev, char *buf)
static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char *buf)
{
u8 data[READ_PUBEK_RESULT_SIZE];
ssize_t len;

View file

@ -2654,7 +2654,7 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
tty->driver->write(tty, &ch, 1);
}
static struct class_simple *tty_class;
static struct class *tty_class;
/**
* tty_register_device - register a tty device
@ -2687,7 +2687,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
pty_line_name(driver, index, name);
else
tty_line_name(driver, index, name);
class_simple_device_add(tty_class, dev, device, name);
class_device_create(tty_class, dev, device, name);
}
/**
@ -2701,7 +2701,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index);
class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
}
EXPORT_SYMBOL(tty_register_device);
@ -2918,7 +2918,7 @@ extern int vty_init(void);
static int __init tty_class_init(void)
{
tty_class = class_simple_create(THIS_MODULE, "tty");
tty_class = class_create(THIS_MODULE, "tty");
if (IS_ERR(tty_class))
return PTR_ERR(tty_class);
return 0;
@ -2947,14 +2947,14 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
@ -2962,7 +2962,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@ -2971,7 +2971,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif

View file

@ -474,7 +474,7 @@ static struct file_operations vcs_fops = {
.open = vcs_open,
};
static struct class_simple *vc_class;
static struct class *vc_class;
void vcs_make_devfs(struct tty_struct *tty)
{
@ -484,26 +484,26 @@ void vcs_make_devfs(struct tty_struct *tty)
devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
S_IFCHR|S_IRUSR|S_IWUSR,
"vcc/a%u", tty->index + 1);
class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_devfs(struct tty_struct *tty)
{
devfs_remove("vcc/%u", tty->index + 1);
devfs_remove("vcc/a%u", tty->index + 1);
class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 1));
class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 129));
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
}
int __init vcs_init(void)
{
if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_simple_create(THIS_MODULE, "vc");
vc_class = class_create(THIS_MODULE, "vc");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}

View file

@ -237,7 +237,7 @@ static dma_addr_t viotape_unitinfo_token;
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
static struct class_simple *tape_class;
static struct class *tape_class;
static struct device *tape_device[VIOTAPE_MAX_TAPE];
@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE;
class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
"iseries!vt%d", i);
class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
NULL, "iseries!nvt%d", i);
devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
"iseries/vt%d", i);
@ -980,8 +980,8 @@ static int viotape_remove(struct vio_dev *vdev)
devfs_remove("iseries/nvt%d", i);
devfs_remove("iseries/vt%d", i);
devfs_unregister_tape(state[i].dev_handle);
class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80));
class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i));
class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
return 0;
}
@ -1045,7 +1045,7 @@ int __init viotap_init(void)
goto clear_handler;
}
tape_class = class_simple_create(THIS_MODULE, "tape");
tape_class = class_create(THIS_MODULE, "tape");
if (IS_ERR(tape_class)) {
printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
ret = PTR_ERR(tape_class);
@ -1070,7 +1070,7 @@ int __init viotap_init(void)
return 0;
unreg_class:
class_simple_destroy(tape_class);
class_destroy(tape_class);
unreg_chrdev:
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
clear_handler:
@ -1110,7 +1110,7 @@ static void __exit viotap_exit(void)
remove_proc_entry("iSeries/viotape", NULL);
vio_unregister_driver(&viotape_driver);
class_simple_destroy(tape_class);
class_destroy(tape_class);
ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape");
if (ret < 0)
printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n",

View file

@ -192,7 +192,12 @@ static struct miscdevice ixp2000_wdt_miscdev =
static int __init ixp2000_wdt_init(void)
{
wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;;
if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
return -EIO;
}
wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
return misc_register(&ixp2000_wdt_miscdev);
}

Some files were not shown because too many files have changed in this diff Show more