Auto merge with /home/aegl/GIT/linus
This commit is contained in:
commit
29516d75a0
399 changed files with 8424 additions and 4069 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = ðernet_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 = ðernet_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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 \
|
||||
{ \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
11
arch/arm/mach-aaec2000/Kconfig
Normal file
11
arch/arm/mach-aaec2000/Kconfig
Normal 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
|
9
arch/arm/mach-aaec2000/Makefile
Normal file
9
arch/arm/mach-aaec2000/Makefile
Normal 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
|
48
arch/arm/mach-aaec2000/aaed2000.c
Normal file
48
arch/arm/mach-aaec2000/aaed2000.c
Normal 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
|
157
arch/arm/mach-aaec2000/core.c
Normal file
157
arch/arm/mach-aaec2000/core.c
Normal 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,
|
||||
};
|
||||
|
16
arch/arm/mach-aaec2000/core.h
Normal file
16
arch/arm/mach-aaec2000/core.h
Normal 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);
|
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
360
arch/arm/mach-versatile/pci.c
Normal file
360
arch/arm/mach-versatile/pci.c
Normal 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);
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); \
|
||||
\
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
|
@ -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
248
drivers/base/dd.c
Normal 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);
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue