Commit 2b738648 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-bt.bkbits.net/bt-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 4b283d59 715814fd
This diff is collapsed.
......@@ -130,6 +130,7 @@ Table 1-1: Process specific entries in /proc
stat Process status
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
..............................................................................
For example, to get the status information of a process, all you have to do is
......
......@@ -2,13 +2,13 @@ bttv.o
card=0 - *** UNKNOWN/GENERIC ***
card=1 - MIRO PCTV
card=2 - Hauppauge (bt848)
card=3 - STB
card=3 - STB, Gateway P/N 6000699 (bt848)
card=4 - Intel Create and Share PCI/ Smart Video Recorder III
card=5 - Diamond DTV2000
card=6 - AVerMedia TVPhone
card=7 - MATRIX-Vision MV-Delta
card=8 - Lifeview FlyVideo II (Bt848) LR26
card=9 - IXMicro TurboTV
card=9 - IMS/IXmicro TurboTV
card=10 - Hauppauge (bt878)
card=11 - MIRO PCTV pro
card=12 - ADS Technologies Channel Surfer TV (bt848)
......@@ -24,22 +24,22 @@ bttv.o
card=22 - Askey CPH050/ Phoebe Tv Master + FM
card=23 - Modular Technology MM205 PCTV, bt878
card=24 - Askey CPH05X/06X (bt878) [many vendors]
card=25 - Terratec Terra TV+ Version 1.0 (Bt848)/Vobis TV-Boostar
card=25 - Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar
card=26 - Hauppauge WinCam newer (bt878)
card=27 - Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50
card=28 - Terratec TerraTV+
card=28 - Terratec TerraTV+ Version 1.1 (bt878)
card=29 - Imagenation PXC200
card=30 - Lifeview FlyVideo 98 LR50
card=31 - Formac iProTV
card=32 - Intel Create and Share PCI/ Smart Video Recorder III
card=33 - Terratec TerraTValue
card=34 - Leadtek WinFast 2000
card=33 - Terratec TerraTValue Version Bt878
card=34 - Leadtek WinFast 2000/ WinFast 2000 XP
card=35 - Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II
card=36 - Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner
card=37 - Prolink PixelView PlayTV pro
card=38 - Askey CPH06X TView99
card=39 - Pinnacle PCTV Studio/Rave
card=40 - STB2
card=40 - STB TV PCI FM, Gateway P/N 6000704 (bt878)
card=41 - AVerMedia TVPhone 98
card=42 - ProVideo PV951
card=43 - Little OnAir TV
......@@ -78,14 +78,17 @@ bttv.o
card=76 - Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)
card=77 - GrandTec Multi Capture Card (Bt878)
card=78 - Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF
card=79 - DSP Design TCVIDEO
card=80 - Hauppauge WinTV PVR
card=81 - GV-BCTV5/PCI
tuner.o
type=0 - Temic PAL (4002 FH5)
type=1 - Philips PAL_I
type=2 - Philips NTSC
type=3 - Philips SECAM
type=1 - Philips PAL_I (FI1246 and compatibles)
type=2 - Philips NTSC (FI1236 and compatibles)
type=3 - Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)
type=4 - NoTuner
type=5 - Philips PAL
type=5 - Philips PAL_BG (FI1216 and compatibles)
type=6 - Temic NTSC (4032 FY5)
type=7 - Temic PAL_I (4062 FY5)
type=8 - Temic NTSC (4036 FY5)
......@@ -103,7 +106,7 @@ tuner.o
type=20 - Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)
type=21 - Temic NTSC (4039 FR5)
type=22 - Temic PAL/SECAM multi (4046 FM5)
type=23 - Philips PAL_DK
type=23 - Philips PAL_DK (FI1256 and compatibles)
type=24 - Philips PAL/SECAM multi (FQ1216ME)
type=25 - LG PAL_I+FM (TAPC-I001D)
type=26 - LG PAL_I (TAPC-I701D)
......@@ -118,3 +121,5 @@ tuner.o
type=35 - Temic PAL_DK/SECAM_L (4012 FY5)
type=36 - Temic NTSC (4136 FY5)
type=37 - LG PAL (newer TAPC series)
type=38 - Philips PAL/SECAM multi (FM1216ME MK3)
type=39 - LG NTSC (newer TAPC series)
......@@ -157,6 +157,7 @@ Lifeview Flyvideo Series:
Flyvideo 2000S (Bt878) w/Stereo TV (Package incl. LR91 daughterboard)
LR91 = Stereo daughter card for LR90
LR97 = Flyvideo DVBS
LR99 Rev.E = Low profile card for OEM integration (only internal audio!) bt878
LR136 = Flyvideo 2100/3100 (Low profile, SAA7130/SAA7134)
LR137 = Flyvideo DV2000/DV3000 (SAA7130/SAA7134 + IEEE1394)
LR138 Rev.C= Flyvideo 2000 (SAA7130)
......@@ -236,6 +237,7 @@ Prolink
Further Cards:
PV-BT878P+rev.9B (Play TV Pro, opt. w/FM w/NICAM)
PV-BT878P+rev.2F
PV-BT878P Rev.1D (bt878, capture only)
Video Conferencing:
PixelView Meeting PAK - (Model: PV-BT878P)
......@@ -273,6 +275,7 @@ Leadtek
WinView 601 (Bt848)
WinView 610 (Zoran)
WinFast2000
WinFast2000 XP
KNC One
-------
......@@ -282,15 +285,19 @@ KNC One
TV-Station FM (+Radio)
TV-Station RDS (+RDS)
Provideo PV951
--------------
These are sold as:
newer Cards have saa7134, but model name stayed the same?
Provideo
--------
PV951 or PV-951 (also are sold as:
Boeder TV-FM Video Capture Card
Titanmedia Supervision TV-2400
Provideo PV951 TF
3DeMon PV951
MediaForte TV-Vision PV951
Yoko PV951
)
PV-148 (capture only)
Highscreen
----------
......@@ -320,15 +327,47 @@ AVerMedia
PCB PCI-ID Model-Name Eeprom Tuner Sound Country
--------------------------------------------------------------------
M1A8-A -- AVer TV-Phone FM1216 --
M101.C ISA !
M108-B Bt848 -- FR1236 US (2),(3)
M1A8-A Bt848 AVer TV-Phone FM1216 --
M168-T 1461:0003 AVerTV Studio 48:17 FM1216 TDA9840T D (1) w/FM w/Remote
M168-U 1461:0004 TVCapture98 40:11 FI1216 -- D w/Remote
M168II-B 1461:0003 Medion MD9592 48:16 FM1216 TDA9873H D w/FM
(1) Daughterboard MB68-A with TDA9820T and TDA9840T
(2) Sony NE41S soldered (stereo sound?)
(3) Daughterboard M118-A w/ pic 16c54 and 4 MHz quartz
US site has different drivers for (as of 09/2002):
EZ Capture/InterCam PCI (BT-848 chip)
EZ Capture/InterCam PCI (BT-878 chip)
TV-Phone (BT-848 chip)
TV98 (BT-848 chip)
TV98 With Remote (BT-848 chip)
TV98 (BT-878 chip)
TV98 With Remote (BT-878)
TV/FM98 (BT-878 chip)
AVerTV
AverTV Stereo
AVerTV Studio
DE hat diverse Treiber fuer diese Modelle (Stand 09/2002):
TVPhone (848) mit Philips tuner FR12X6 (w/ FM radio)
TVPhone (848) mit Philips tuner FM12X6 (w/ FM radio)
TVCapture (848) w/Philips tuner FI12X6
TVCapture (848) non-Philips tuner
TVCapture98 (Bt878)
TVPhone98 (Bt878)
AVerTV und TVCapture98 w/VCR (Bt 878)
AVerTVStudio und TVPhone98 w/VCR (Bt878)
AVerTV GO Serie (Kein SVideo Input)
AVerTV98 (BT-878 chip)
AVerTV98 mit Fernbedienung (BT-878 chip)
AVerTV/FM98 (BT-878 chip)
Aimslab
-------
Video Highway or "Video Highway TR200" (ISA)
Video Highway Xtreme (aka "VHX") (Bt848, FM w/ TEA5757)
IXMicro (former: IMS=Integrated Micro Solutions)
......@@ -364,6 +403,9 @@ Terratec
LR74 is a newer PCB revision of ceb105 (both incl. connector for Active Radio Upgrade)
Cinergy 400 (saa7134), "E877 11(S)", "PM820092D" printed on PCB
Cinergy 600 (saa7134)
Technisat
---------
Discos ADR PC-Karte ISA (no TV!)
......@@ -373,7 +415,7 @@ Technisat
Mediafocus I (zr36120/zr36125, drp3510, Sat. analog + ADR Radio)
Mediafocus II (saa7146, Sat. analog)
SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A)
SkyStar 1 DVB (AV7110)
SkyStar 1 DVB (AV7110) = Technotrend Premium
SkyStar 2 DVB (B2C2) (=Sky2PC)
Siemens
......@@ -387,6 +429,9 @@ Stradis
Powercolor
----------
MTV878
Package comes with different contents:
a) pcb "MTV878" (CARD=75)
b) Pixelview Rev. 4_
MTV878R w/Remote Control
MTV878F w/Remote Control w/FM radio
......@@ -394,10 +439,14 @@ Pinnacle
--------
Mirovideo PCTV (Bt848)
Mirovideo PCTV SE (Bt848)
Mirovideo PCTV Pro (Bt848 + Daughterboard)
Mirovideo PCTV Pro (Bt848 + Daughterboard for TV Stereo and FM)
Studio PCTV Rave (Bt848 Version = Mirovideo PCTV)
Studio PCTV Rave (Bt878 package w/o infrared)
Studio PCTV (Bt878)
Studio PCTV Pro (Bt878 stereo w/ FM)
Pinnacle PCTV (Bt878, MT2032)
Pinnacle PCTV Pro (Bt878, MT2032)
Pinncale PCTV Sat
M(J)PEG capture and playback:
DC1+ (ISA)
......@@ -495,8 +544,10 @@ Intel
STB
---
TV PCI (Temic4032FY5, tda9850??)
other variants?
STB bt878 == Gateway 6000704
STB Gateway 6000699 (bt848)
STB Gateway 6000402 (bt848)
STB TV130 PCI
Videologic
----------
......@@ -507,6 +558,16 @@ Technotrend
------------
TT-SAT PCI (PCB "Sat-PCI Rev.:1.3.1"; zr36125, vpx3225d, stc0056a, Tuner:BSKE6-155A
TT-DVB-Sat
This card is sold as OEM from:
Siemens DVB-s Card
Hauppauge WinTV DVB-S
Technisat SkyStar 1 DVB
Galaxis DVB Sat
Now this card is called TT-PCline Premium Family
TT-Budget
This card is sold as OEM from:
Hauppauge WinTV Nova
Satelco Standard PCI (DVB-S)
TT-DVB-C PCI
Teles
......@@ -546,10 +607,13 @@ Galaxis
Hauppauge
---------
many many WinTV models ...
WinTV DVBs
WinTV NOVA
WinTV DVBs = Tehcnotrend Premium
WinTV NOVA = Technotrend Budget
WinTV NOVA-CI
WinTV-Nexus-s
WinTV PVR
WinTV PVR 250
WinTV PVR 450
Matrix-Vision
-------------
......@@ -615,7 +679,7 @@ AVEC www.prochips.com
NoBrand
-------
TV Excel = Australian Name for "PV-BT878P+ 8E" or so
TV Excel = Australian Name for "PV-BT878P+ 8E" or "878TV Rev.3_"
Mach www.machspeed.com
----
......@@ -638,9 +702,51 @@ Boser www.boser.com.tw
Satelco
-------
TV-FM =KNC1 saa7134
Standard PCI (DVB-S) = Technotrend Budget
Standard PCI (DVB-S) w/ CI
Satelco Hoghend PCI (DVB-S) = Technotrend Premium
Sensoray www.sensoray.com
--------
Sensoray 311 (PC/104 bus)
Sensoray 611 (PCI)
CEI (Chartered Electronics Industries Pte Ltd [CEI] [FCC ID HBY])
---
TV Tuner - HBY-33A-RAFFLES Brooktree Bt848KPF + Philips
TV Tuner MG9910 - HBY33A-TVO CEI + Philips SAA7110 + OKI M548262 + ST STV8438CV
Primetime TV (ISA)
acquired by Singapore Technologies
now operating as Chartered Semiconductor Manufacturing
Manufacturer of video cards is listed as:
Cogent Electronics Industries [CEI]
AITech
------
AITech WaveWatcher TV-PCI = LR26
WaveWatcher TVR-202 TV/FM Radio Card (ISA)
MAXRON
------
Maxron MaxTV/FM Radio (KW-TV878-FNT) = Kworld or JW-TV878-FBK
www.ids-imaging.de
------------------
Falcon Series (capture only)
In USA: http://www.theimagingsource.com/
DFG/LC1
www.sknet-web.co.jp
-------------------
SKnet Monster TV (saa7134)
A-Max www.amaxhk.com (Colormax, Amax, Napa)
-------------------
APAC Viewcomp 878
Cybertainment
-------------
CyberMail AV Video Email Kit w/ PCI Capture Card (capture only)
CyberMail Xtreme
These are Flyvideo
......@@ -76,6 +76,12 @@ correct card type in case the autodetection does'nt work. If you get
video but no sound you've very likely specified the wrong (or no)
card type. A list of supported cards is in CARDLIST.
For the WinTV/PVR you need one firmware file from the driver CD:
hcwamc.rbf. The file is in the pvr45xxx.exe archive (self-extracting
zip file, unzip can unpack it). Put it into the /etc/pvr directory or
use the firm_altera=<path> insmod option to point the driver to the
location of the file.
If your card isn't listed in CARDLIST or if you have trouble making
audio work, you should read the Sound-FAQ.
......
......@@ -61,6 +61,9 @@ greatest workarounds for hardware bugs might fix these problems.
other
-----
If you use some binary-only yunk (like nvidia module) try to reproduce
the problem without.
IRQ sharing is known to cause problems in some cases. It works just
fine in theory and many configurations. Neverless it might be worth a
try to shuffle around the PCI cards to give bttv another IRQ or make
......
1) Tuner Programming
====================
There are some flavors of Tuner programming APIs.
These differ mainly by the bandswitch byte.
L= LG_API (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04)
P= PHILIPS_API (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04)
T= TEMIC_API (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01)
A= ALPS_API (VHF_LO=0x14, VHF_HI=0x12, UHF=0x11)
M= PHILIPS_MK3 (VHF_LO=0x01, VHF_HI=0x02, UHF=0x04, radio=0x19)
2) Tuner Manufacturers
======================
SAMSUNG Tuner identification: (e.g. TCPM9091PD27)
TCP [ABCJLMNQ] 90[89][125] [DP] [ACD] 27 [ABCD]
......@@ -24,6 +37,8 @@ SAMSUNG Tuner identification: (e.g. TCPM9091PD27)
[ABCD]:
3-wire/I2C tuning, 2-band/3-band
These Tuners are PHILIPS_API compatible.
Philips Tuner identification: (e.g. FM1216MF)
F[IRMQ]12[1345]6{MF|ME|MP}
F[IRMQ]:
......@@ -39,15 +54,17 @@ Philips Tuner identification: (e.g. FM1216MF)
1246: PAL I
1256: Pal DK
{MF|ME|MP}
MF: w/ Secam
MF: BG LL w/ Secam (Multi France)
ME: BG DK I LL (Multi Europe)
MP: BG DK I (Multi PAL)
MR: BG DK M (?)
MG: BG DKI M (?)
MK2 series PHILIPS_API, most tuners are compatible to this one !
MK3 series introduced in 2002 w/ PHILIPS_MK3_API
Temic Tuner identification: (.e.g 4006FH5)
4[01][0136][269]F[HYNR]5
40x2: Tuner (5V/33V), different I2C programming from Philips !
40x2: Tuner (5V/33V), TEMIC_API.
40x6: Tuner 5V
41xx: Tuner compact
40x9: Tuner+FM compact
......@@ -62,6 +79,7 @@ Temic Tuner identification: (.e.g 4006FH5)
FN5: multistandard
FR5: w/ FM radio
3X xxxx: order number with specific connector
Note: Only 40x2 series has TEMIC_API, all newer tuners have PHILIPS_API.
LG Innotek Tuner:
TPI8NSR11 : NTSC J/M (TPI8NSR01 w/FM) (P,210/497)
......@@ -78,12 +96,6 @@ LG Innotek Tuner:
TADC-H002F: NTSC (L,175/410?; 2-B, C-W+11, W+12-69)
TADC-M201D: PAL D/K+B/G+I (L,143/425) (sound control at I2C address 0xc8)
TADC-T003F: NTSC Taiwan (L,175/410?; 2-B, C-W+11, W+12-69)
(API,Lo-Hi-takeover/Hi-UHF-takeover)
I2C APIs:
L= LG programming (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04)
P= Philips progr. (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04)
T= Temic progr. (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01)
Suffix:
P= Standard phono female socket
D= IEC female socket
......@@ -93,3 +105,11 @@ Other Tuners:
TCL2002MB-1 : PAL BG + DK =TUNER_LG_PAL_NEW_TAPC
TCL2002MB-1F: PAL BG + DK w/FM =PHILIPS_PAL
TCL2002MI-2 : PAL I = ??
ALPS Tuners:
Most are LG_API compatible
TSCH6 has ALPS_API (TSCH5 ?)
TSBE1 has extra API 05,02,08 Control_byte=0xCB Source:(1)
Lit.
(1) conexant100029b-PCI-Decoder-ApplicationNote.pdf
......@@ -528,7 +528,7 @@ show_interrupts(struct seq_file *p, void *v)
#else
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ", kstat.irqs[j][i]);
seq_printf(p, "%10u ", kstat_cpu(i).irqs[j]);
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %c%s",
......@@ -590,7 +590,7 @@ handle_irq(int irq, struct pt_regs * regs)
}
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(i).irqs[irq]++;
spin_lock_irq(&desc->lock); /* mask also the higher prio events */
desc->handler->ack(irq);
/*
......
......@@ -59,7 +59,7 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
smp_percpu_timer_interrupt(&regs);
cpu = smp_processor_id();
if (cpu != boot_cpuid) {
kstat.irqs[cpu][RTC_IRQ]++;
kstat_cpu(cpu).irqs[RTC_IRQ]++;
} else {
handle_irq(RTC_IRQ, &regs);
}
......
......@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/profile.h>
#define RTC_IRQ 8
......
......@@ -217,7 +217,7 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
desc->triggered = 1;
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
action = desc->action;
if (action)
......@@ -253,7 +253,7 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
*/
desc->running = 1;
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
do {
struct irqaction *action;
......
......@@ -234,7 +234,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %10u %c %s",
i, kstat.irqs[0][i],
i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action = action->next; action; action = action->next) {
......@@ -261,7 +261,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
cpu = smp_processor_id();
irq_enter(cpu);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
action = irq_action[irq];
if (action) {
......
......@@ -74,6 +74,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Cache size */
if (c->x86_cache_size >= 0)
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
#ifdef CONFIG_SMP
if (cpu_has_ht) {
extern int phys_proc_id[NR_CPUS];
seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
seq_printf(m, "siblings\t: %d\n", smp_num_siblings);
}
#endif
/* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu);
......
......@@ -44,7 +44,7 @@
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/limits.h>
#include <linux/driverfs_fs.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <asm/edd.h>
#include <linux/device.h>
......@@ -63,20 +63,9 @@ MODULE_LICENSE("GPL");
#define left (count - (p - buf) - 1)
/*
* bios_dir may go away completely,
* and it definitely won't be at the root
* of driverfs forever.
*/
static struct driver_dir_entry bios_dir = {
.name = "bios",
.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO),
};
struct edd_device {
char name[EDD_DEVICE_NAME_SIZE];
struct edd_info *info;
struct driver_dir_entry dir;
struct kobject kobj;
};
struct edd_attribute {
......@@ -112,13 +101,13 @@ edd_dev_set_info(struct edd_device *edev, struct edd_info *info)
}
#define to_edd_attr(_attr) container_of(_attr,struct edd_attribute,attr)
#define to_edd_device(_dir) container_of(_dir,struct edd_device,dir)
#define to_edd_device(obj) container_of(obj,struct edd_device,kobj)
static ssize_t
edd_attr_show(struct driver_dir_entry *dir, struct attribute *attr,
edd_attr_show(struct kobject * kobj, struct attribute *attr,
char *buf, size_t count, loff_t off)
{
struct edd_device *dev = to_edd_device(dir);
struct edd_device *dev = to_edd_device(kobj);
struct edd_attribute *edd_attr = to_edd_attr(attr);
ssize_t ret = 0;
......@@ -127,7 +116,7 @@ edd_attr_show(struct driver_dir_entry *dir, struct attribute *attr,
return ret;
}
static struct driverfs_ops edd_attr_ops = {
static struct sysfs_ops edd_attr_ops = {
.show = edd_attr_show,
};
......@@ -586,89 +575,26 @@ static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30);
static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30);
static struct edd_attribute * def_attrs[] = {
&edd_attr_raw_data,
&edd_attr_version,
&edd_attr_extensions,
&edd_attr_info_flags,
&edd_attr_sectors,
&edd_attr_default_cylinders,
&edd_attr_default_heads,
&edd_attr_default_sectors_per_track,
&edd_attr_interface,
&edd_attr_host_bus,
static struct attribute * def_attrs[] = {
&edd_attr_raw_data.attr,
&edd_attr_version.attr,
&edd_attr_extensions.attr,
&edd_attr_info_flags.attr,
&edd_attr_sectors.attr,
&edd_attr_default_cylinders.attr,
&edd_attr_default_heads.attr,
&edd_attr_default_sectors_per_track.attr,
&edd_attr_interface.attr,
&edd_attr_host_bus.attr,
NULL,
};
/* edd_get_devpath_length(), edd_fill_devpath(), and edd_device_link()
were taken from linux/drivers/base/fs/device.c. When these
or similar are exported to generic code, remove these.
*/
static int
edd_get_devpath_length(struct device *dev)
{
int length = 1;
struct device *parent = dev;
/* walk up the ancestors until we hit the root.
* Add 1 to strlen for leading '/' of each level.
*/
do {
length += strlen(parent->bus_id) + 1;
parent = parent->parent;
} while (parent);
return length;
}
static void
edd_fill_devpath(struct device *dev, char *path, int length)
{
struct device *parent;
--length;
for (parent = dev; parent; parent = parent->parent) {
int cur = strlen(parent->bus_id);
/* back up enough to print this bus id with '/' */
length -= cur;
strncpy(path + length, parent->bus_id, cur);
*(path + --length) = '/';
}
}
static int
edd_device_symlink(struct edd_device *edev, struct device *dev, char *name)
{
char *path;
int length;
int error = 0;
if (!dev->bus || !name)
return 0;
length = edd_get_devpath_length(dev);
/* now add the path from the edd_device directory
* It should be '../..' (one to get to the 'bios' directory,
* and one to get to the root of the fs.)
*/
length += strlen("../../root");
if (length > PATH_MAX)
return -ENAMETOOLONG;
if (!(path = kmalloc(length, GFP_KERNEL)))
return -ENOMEM;
memset(path, 0, length);
static struct subsystem edd_subsys = {
.kobj = { .name = "edd" },
.sysfs_ops = &edd_attr_ops,
.default_attrs = def_attrs,
};
/* our relative position */
strcpy(path, "../../root");
edd_fill_devpath(dev, path, length);
error = driverfs_create_symlink(&edev->dir, name, path);
kfree(path);
return error;
}
/**
* edd_dev_is_type() - is this EDD device a 'type' device?
......@@ -721,7 +647,7 @@ edd_create_symlink_to_pcidev(struct edd_device *edev)
struct pci_dev *pci_dev = edd_get_pci_dev(edev);
if (!pci_dev)
return 1;
return edd_device_symlink(edev, &pci_dev->dev, "pci_dev");
return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
}
/**
......@@ -833,61 +759,16 @@ edd_create_symlink_to_scsidev(struct edd_device *edev)
return 1;
get_device(&sdev->sdev_driverfs_dev);
rc = edd_device_symlink(edev, &sdev->sdev_driverfs_dev, "disc");
rc = sysfs_create_link(&edev->kobj,&sdev->sdev_driverfs_dev.kobj, "disc");
put_device(&sdev->sdev_driverfs_dev);
return rc;
}
static inline int
edd_create_file(struct edd_device *edev, struct edd_attribute *attr)
{
return driverfs_create_file(&attr->attr, &edev->dir);
}
static inline void
edd_device_unregister(struct edd_device *edev)
{
driverfs_remove_dir(&edev->dir);
}
static int
edd_populate_dir(struct edd_device *edev)
{
struct edd_attribute *attr;
int i;
int error = 0;
for (i = 0; (attr=def_attrs[i]); i++) {
if (!attr->test || (attr->test && !attr->test(edev))) {
if ((error = edd_create_file(edev, attr))) {
break;
}
}
}
if (error)
return error;
edd_create_symlink_to_pcidev(edev);
edd_create_symlink_to_scsidev(edev);
return 0;
}
static int
edd_make_dir(struct edd_device *edev)
{
int error;
edev->dir.name = edev->name;
edev->dir.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
edev->dir.ops = &edd_attr_ops;
error = driverfs_create_dir(&edev->dir, &bios_dir);
if (!error)
error = edd_populate_dir(edev);
return error;
kobject_unregister(&edev->kobj);
}
static int
......@@ -899,9 +780,15 @@ edd_device_register(struct edd_device *edev, int i)
return 1;
memset(edev, 0, sizeof (*edev));
edd_dev_set_info(edev, &edd[i]);
snprintf(edev->name, EDD_DEVICE_NAME_SIZE, "int13_dev%02x",
kobject_init(&edev->kobj);
snprintf(edev->kobj.name, EDD_DEVICE_NAME_SIZE, "int13_dev%02x",
edd[i].device);
error = edd_make_dir(edev);
edev->kobj.subsys = &edd_subsys;
error = kobject_register(&edev->kobj);
if (!error) {
edd_create_symlink_to_pcidev(edev);
edd_create_symlink_to_scsidev(edev);
}
return error;
}
......@@ -926,7 +813,7 @@ edd_init(void)
return 1;
}
rc = driverfs_create_dir(&bios_dir, NULL);
rc = firmware_register(&edd_subsys);
if (rc)
return rc;
......@@ -943,12 +830,9 @@ edd_init(void)
edd_devices[i] = edev;
}
if (rc) {
driverfs_remove_dir(&bios_dir);
return rc;
}
return 0;
if (rc)
firmware_unregister(&edd_subsys);
return rc;
}
static void __exit
......@@ -963,8 +847,7 @@ edd_exit(void)
kfree(edev);
}
}
driverfs_remove_dir(&bios_dir);
firmware_unregister(&edd_subsys);
}
late_initcall(edd_init);
......
......@@ -740,6 +740,7 @@ ENTRY(sys_call_table)
.long sys_epoll_create
.long sys_epoll_ctl /* 255 */
.long sys_epoll_wait
.long sys_remap_file_pages
.rept NR_syscalls-(.-sys_call_table)/4
......
......@@ -153,7 +153,7 @@ int show_interrupts(struct seq_file *p, void *v)
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
p += seq_printf(p, "%10u ",
kstat.irqs[j][i]);
kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %s", action->name);
......@@ -345,7 +345,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
}
}
#endif
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
......
......@@ -247,6 +247,7 @@ void flush_thread(void)
struct task_struct *tsk = current;
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
/*
* Forget coprocessor state..
*/
......
......@@ -58,7 +58,7 @@ static int __initdata smp_b_stepping;
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
int __initdata phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
/* Bitmask of currently online CPUs */
unsigned long cpu_online_map;
......
......@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
......@@ -248,91 +249,68 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
}
#ifdef CONFIG_HUGETLB_PAGE
#define HPAGE_ALIGN(x) (((unsigned long)x + (HPAGE_SIZE -1)) & HPAGE_MASK)
extern long sys_munmap(unsigned long, size_t);
/* get_addr function gets the currently unused virtaul range in
* current process's address space. It returns the LARGE_PAGE_SIZE
* current process's address space. It returns the HPAGE_SIZE
* aligned address (in cases of success). Other kernel generic
* routines only could gurantee that allocated address is PAGE_SIZSE aligned.
* routines only could gurantee that allocated address is PAGE_SIZE aligned.
*/
static unsigned long
get_addr(unsigned long addr, unsigned long len)
static unsigned long get_addr(unsigned long addr, unsigned long len)
{
struct vm_area_struct *vma;
struct vm_area_struct *vma;
if (addr) {
addr = HPAGE_ALIGN(addr);
addr = (addr + HPAGE_SIZE - 1) & HPAGE_MASK;
vma = find_vma(current->mm, addr);
if (((TASK_SIZE - len) >= addr) &&
(!vma || addr + len <= vma->vm_start))
if (TASK_SIZE > addr + len && !(vma && addr + len >= vma->vm_start))
goto found_addr;
}
addr = HPAGE_ALIGN(TASK_UNMAPPED_BASE);
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
if (TASK_SIZE - len < addr)
return -ENOMEM;
if (!vma || ((addr + len) < vma->vm_start))
addr = TASK_UNMAPPED_BASE;
for (vma = find_vma(current->mm, addr); TASK_SIZE > addr + len; vma = vma->vm_next) {
if (!vma || addr + len < vma->vm_start)
goto found_addr;
addr = HPAGE_ALIGN(vma->vm_end);
addr = (vma->vm_end + HPAGE_SIZE - 1) & HPAGE_MASK;
}
return -ENOMEM;
found_addr:
return addr;
}
asmlinkage unsigned long
sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
{
struct mm_struct *mm = current->mm;
unsigned long raddr;
int retval = 0;
extern int alloc_hugetlb_pages(int, unsigned long, unsigned long, int, int);
if (!(cpu_has_pse))
return -EINVAL;
if (key < 0)
return -EINVAL;
if (len & (HPAGE_SIZE - 1))
if (!cpu_has_pse || key < 0 || len & ~HPAGE_MASK)
return -EINVAL;
down_write(&mm->mmap_sem);
raddr = get_addr(addr, len);
if (raddr == -ENOMEM)
goto raddr_out;
retval = alloc_hugetlb_pages(key, raddr, len, prot, flag);
raddr_out: up_write(&mm->mmap_sem);
if (retval < 0)
return (unsigned long) retval;
return raddr;
if (raddr != -ENOMEM)
retval = alloc_hugetlb_pages(key, raddr, len, prot, flag);
up_write(&mm->mmap_sem);
return (retval < 0) ? (unsigned long)retval : raddr;
}
asmlinkage int
sys_free_hugepages(unsigned long addr)
asmlinkage int sys_free_hugepages(unsigned long addr)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
int retval;
extern int free_hugepages(struct vm_area_struct *);
struct vm_area_struct *vma;
int retval;
vma = find_vma(current->mm, addr);
if ((!vma) || (!is_vm_hugetlb_page(vma)) || (vma->vm_start!=addr))
if (!vma || !(vma->vm_flags & VM_HUGETLB) || vma->vm_start != addr)
return -EINVAL;
down_write(&mm->mmap_sem);
spin_lock(&mm->page_table_lock);
retval = free_hugepages(vma);
spin_unlock(&mm->page_table_lock);
retval = do_munmap(vma->vm_mm, addr, vma->vm_end - addr);
up_write(&mm->mmap_sem);
return retval;
}
#else
asmlinkage unsigned long
sys_alloc_hugepages(int key, unsigned long addr, size_t len, int prot, int flag)
asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, size_t len, int prot, int flag)
{
return -ENOSYS;
}
asmlinkage int
sys_free_hugepages(unsigned long addr)
asmlinkage int sys_free_hugepages(unsigned long addr)
{
return -ENOSYS;
}
#endif
......@@ -6,6 +6,7 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <asm/mpspec.h>
#include <asm/timer.h>
#include <asm/io.h>
......
......@@ -324,7 +324,7 @@ static void do_piix4_master_IRQ(unsigned int irq, struct pt_regs * regs)
/*
* handle this 'virtual interrupt' as a Cobalt one now.
*/
kstat.irqs[smp_processor_id()][irq]++;
kstat_cpu(smp_processor_id()).irqs[irq]++;
do_cobalt_IRQ(realirq, regs);
spin_lock(&irq_controller_lock);
......
This diff is collapsed.
......@@ -16,6 +16,7 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/init.h>
......
vpath %.c = . $(TOPDIR)/drivers/oprofile
obj-$(CONFIG_OPROFILE) += oprofile.o
DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
......@@ -9,8 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofile-objs := $(DRIVER_OBJS) init.o timer_int.o
ifdef CONFIG_X86_LOCAL_APIC
oprofile-objs += nmi_int.o op_model_athlon.o op_model_ppro.o
endif
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o op_model_ppro.o
include $(TOPDIR)/Rules.make
......@@ -135,9 +135,19 @@ static void nmi_restore_registers(struct op_msrs * msrs)
static void nmi_cpu_shutdown(void * dummy)
{
unsigned int v;
int cpu = smp_processor_id();
struct op_msrs * msrs = &cpu_msrs[cpu];
/* restoring APIC_LVTPC can trigger an apic error because the delivery
* mode and vector nr combination can be illegal. That's by design: on
* power on apic lvt contain a zero vector nr which are legal only for
* NMI delivery mode. So inhibit apic err before restoring lvtpc
*/
v = apic_read(APIC_LVTERR);
apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
apic_write(APIC_LVTPC, saved_lvtpc[cpu]);
apic_write(APIC_LVTERR, v);
nmi_restore_registers(msrs);
}
......
......@@ -172,7 +172,7 @@ int show_interrupts(struct seq_file *p, void *v)
#else
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ", kstat.irqs[j][i]);
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", idesc->handler->typename);
seq_printf(p, " %s", action->name);
......@@ -346,7 +346,7 @@ unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
unsigned int status;
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
if (desc->status & IRQ_PER_CPU) {
/* no locking required for CPU-local interrupts: */
......
......@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/file.h> /* doh, must come after sched.h... */
......
......@@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
......
......@@ -350,7 +350,7 @@ void amiga_disable_irq(unsigned int irq)
inline void amiga_do_irq(int irq, struct pt_regs *fp)
{
kstat.irqs[0][SYS_IRQS + irq]++;
kstat_cpu(0).irqs[SYS_IRQS + irq]++;
ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
}
......@@ -358,7 +358,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)
{
irq_node_t *node;
kstat.irqs[0][SYS_IRQS + irq]++;
kstat_cpu(0).irqs[SYS_IRQS + irq]++;
custom.intreq = amiga_intena_vals[irq];
......@@ -479,7 +479,7 @@ int show_amiga_interrupts(struct seq_file *p, void *v)
if (!(node = ami_irq_list[i]))
continue;
seq_printf(p, "ami %2d: %10u ", i,
kstat.irqs[0][SYS_IRQS + i]);
kstat_cpu(0).irqs[SYS_IRQS + i]);
do {
if (node->flags & SA_INTERRUPT)
seq_puts(p, "F ");
......
......@@ -131,7 +131,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
custom.intreq = base->int_mask;
for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
if (ints & 1) {
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp);
}
ints >>= 1;
......@@ -166,7 +166,7 @@ int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
j = base->cia_irq;
for (i = 0; i < CIA_IRQS; i++) {
seq_printf(p, "cia %2d: %10d ", j + i,
kstat.irqs[0][SYS_IRQS + j + i]);
kstat_cpu(0).irqs[SYS_IRQS + j + i]);
seq_puts(p, " ");
seq_printf(p, "%s\n", base->irq_list[i].devname);
}
......
......@@ -191,7 +191,7 @@ __asm__ (__ALIGN_STR "\n" \
" andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \
" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \
" jbra ret_from_interrupt\n" \
: : "i" (&kstat.irqs[0][n+8]), "i" (&irq_handler[n+8]), \
: : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \
"n" (PT_OFF_SR), "n" (n), \
"i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \
: (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \
......@@ -297,7 +297,7 @@ atari_prio_irq_handler:\t
addql #8,%%sp
addql #4,%%sp
jbra ret_from_interrupt"
: : "i" (&kstat.irqs[0]), "n" (PT_OFF_FORMATVEC),
: : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
"m" (local_irq_count(0))
);
for (;;);
......@@ -623,11 +623,11 @@ int show_atari_interrupts(struct seq_file *p, void *v)
continue;
if (i < STMFP_SOURCE_BASE)
seq_printf(p, "auto %2d: %10u ",
i, kstat.irqs[0][i]);
i, kstat_cpu(0).irqs[i]);
else
seq_printf(p, "vec $%02x: %10u ",
IRQ_SOURCE_TO_VECTOR(i),
kstat.irqs[0][i]);
kstat_cpu(0).irqs[i]);
if (irq_handler[i].handler != atari_call_irq_list) {
seq_printf(p, "%s\n", irq_param[i].devname);
......
......@@ -231,7 +231,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
{
if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
vec -= VEC_SPUR;
kstat.irqs[0][vec]++;
kstat_cpu(0).irqs[vec]++;
irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
} else {
if (mach_process_int)
......@@ -250,7 +250,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (mach_default_handler) {
for (i = 0; i < SYS_IRQS; i++) {
seq_printf(p, "auto %2d: %10u ", i,
i ? kstat.irqs[0][i] : num_spurious);
i ? kstat_cpu(0).irqs[i] : num_spurious);
seq_puts(p, " ");
seq_printf(p, "%s\n", irq_list[i].devname);
}
......
......@@ -345,7 +345,7 @@ void mac_do_irq_list(int irq, struct pt_regs *fp)
irq_node_t *node, *slow_nodes;
unsigned long cpu_flags;
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
#ifdef DEBUG_SPURIOUS
if (!mac_irq_list[irq] && (console_loglevel > 7)) {
......@@ -620,7 +620,7 @@ int show_mac_interrupts(struct seq_file *p, void *v)
case 8: base = "bbn";
break;
}
seq_printf(p, "%4s %2d: %10u ", base, i, kstat.irqs[0][i]);
seq_printf(p, "%4s %2d: %10u ", base, i, kstat_cpu(0).irqs[i]);
do {
if (node->flags & IRQ_FLG_FAST) {
......
......@@ -58,7 +58,7 @@ void sun3_disable_irq(unsigned int irq)
inline void sun3_do_irq(int irq, struct pt_regs *fp)
{
kstat.irqs[0][SYS_IRQS + irq]++;
kstat_cpu(0).irqs[SYS_IRQS + irq]++;
*sun3_intreg &= ~(1<<irq);
*sun3_intreg |= (1<<irq);
}
......@@ -71,13 +71,14 @@ int show_sun3_interrupts(struct seq_file *p, void *v)
static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
{
sun3_do_irq(irq,fp);
if(!(kstat.irqs[0][SYS_IRQS + irq] % 2000))
sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%16000)/2000]);
if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 2000))
sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%16000)
/2000]);
}
static void sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
{
kstat.irqs[0][SYS_IRQS + irq]++;
kstat_cpu(0).irqs[SYS_IRQS + irq]++;
#ifdef CONFIG_SUN3
intersil_clear();
#endif
......@@ -87,8 +88,8 @@ static void sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
intersil_clear();
#endif
do_timer(fp);
if(!(kstat.irqs[0][SYS_IRQS + irq] % 20))
sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%160)
if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20))
sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160)
/20]);
}
......@@ -107,7 +108,7 @@ static void sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
if(sun3_inthandler[irq] == NULL)
panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
kstat.irqs[0][SYS_IRQS + irq]++;
kstat_cpu(0).irqs[SYS_IRQS + irq]++;
*sun3_intreg &= ~(1<<irq);
sun3_inthandler[irq](irq, dev_ids[irq], fp);
......
......@@ -68,7 +68,7 @@ void mips_timer_interrupt(struct pt_regs *regs)
goto null;
do {
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
do_timer(regs);
r4k_cur += r4k_offset;
ack_r4ktimer(r4k_cur);
......
......@@ -152,7 +152,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -180,7 +180,7 @@ static void do_IRQ(int irq, struct pt_regs * regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
mask_irq(irq);
action = *(irq + irq_action);
......
......@@ -103,7 +103,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action = action->next; action; action = action->next) {
......@@ -130,7 +130,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
mask_irq(irq);
action = *(irq + irq_action);
......
......@@ -256,7 +256,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
#if 0
if (irq_desc[irq].handler && irq_desc[irq].handler->ack) {
// printk("invoking ack handler\n");
......
......@@ -244,7 +244,7 @@ asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
struct irqaction * action;
unsigned int status;
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
......
......@@ -134,7 +134,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -176,7 +176,7 @@ asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
i8259_mask_and_ack_irq(irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
action = *(irq + irq_action);
if (!action)
......@@ -214,7 +214,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
action = *(irq + irq_action);
if (action) {
......
......@@ -424,7 +424,7 @@ r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
*/
write_32bit_cp0_register (CP0_COMPARE,
(unsigned long) (count + r4k_interval));
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
#endif
timer_interrupt(irq, dev_id, regs);
......
......@@ -369,7 +369,7 @@ asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
int cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
/* we keep interrupt disabled all the time */
timer_interrupt(irq, NULL, regs);
......
......@@ -105,7 +105,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
num, kstat_cpu(0).irqs[num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -202,7 +202,7 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs)
}
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
action->handler(irq, action->dev_id, regs);
irq_exit(cpu, irq);
......
......@@ -139,7 +139,7 @@ void mips_timer_interrupt(struct pt_regs *regs)
goto null;
do {
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
do_timer(regs);
/* Historical comment/code:
......
......@@ -125,7 +125,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action = action->next; action; action = action->next) {
......@@ -161,7 +161,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(0).irqs[irq]++;
if (irq == 20) {
printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n",
......
......@@ -418,7 +418,7 @@ void indy_buserror_irq(struct pt_regs *regs)
int irq = 6;
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
printk("Got a bus error IRQ, shouldn't happen yet\n");
show_regs(regs);
printk("Spinning...\n");
......
......@@ -13,7 +13,7 @@ void indy_8254timer_irq(void)
int irq = 4;
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
prom_getchar();
ArcEnterInteractiveMode();
......
......@@ -101,7 +101,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
num, kstat_cpu(0).irqs[num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -198,7 +198,7 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs)
}
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
action->handler(irq, action->dev_id, regs);
irq_exit(cpu, irq);
......
......@@ -138,7 +138,7 @@ void mips_timer_interrupt(struct pt_regs *regs)
goto null;
do {
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
do_timer(regs);
/* Historical comment/code:
......
......@@ -131,7 +131,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
num, kstat_cpu(0).irqs[num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -146,7 +146,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
num, kstat_cpu(0).irqs[num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -322,7 +322,7 @@ void malta_hw0_irqdispatch(struct pt_regs *regs)
return;
irq_enter(cpu, irq);
kstat.irqs[0][irq + 8]++;
kstat_cpu(0).irqs[irq + 8]++;
do {
action->handler(irq, action->dev_id, regs);
action = action->next;
......
......@@ -243,7 +243,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
num, kstat_cpu(0).irqs[num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -258,7 +258,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
num, kstat_cpu(0).irqs[num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -285,7 +285,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
panic(KERN_DEBUG "Got irq %d, press a key.", irq);
......@@ -444,7 +444,7 @@ void indy_local0_irqdispatch(struct pt_regs *regs)
}
irq_enter(cpu, irq);
kstat.irqs[0][irq + 16]++;
kstat_cpu(0).irqs[irq + 16]++;
action->handler(irq, action->dev_id, regs);
irq_exit(cpu, irq);
}
......@@ -468,7 +468,7 @@ void indy_local1_irqdispatch(struct pt_regs *regs)
action = local_irq_action[irq];
}
irq_enter(cpu, irq);
kstat.irqs[0][irq + 24]++;
kstat_cpu(0).irqs[irq + 24]++;
action->handler(irq, action->dev_id, regs);
irq_exit(cpu, irq);
}
......@@ -479,7 +479,7 @@ void indy_buserror_irq(struct pt_regs *regs)
int irq = 6;
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
printk("Got a bus error IRQ, shouldn't happen yet\n");
show_regs(regs);
printk("Spinning...\n");
......
......@@ -98,7 +98,7 @@ void indy_timer_interrupt(struct pt_regs *regs)
else
r4k_cur += r4k_offset;
ack_r4ktimer(r4k_cur);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
do_timer(regs);
/* We update the Dallas time of day approx. every 11 minutes,
......@@ -236,7 +236,7 @@ void indy_8254timer_irq(void)
int irq = 4;
irq_enter(cpu, irq);
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
panic("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
irq_exit(cpu, irq);
}
......
......@@ -146,7 +146,7 @@ int show_interrupts(struct seq_file *p, void *v)
action = irq_action[i];
if (!action)
continue;
seq_printf(p, "%2d: %8d %c %s", i, kstat.irqs[0][i],
seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
......@@ -170,7 +170,7 @@ static void do_IRQ(cpuid_t thiscpu, int irq, struct pt_regs * regs)
int do_random;
irq_enter(thiscpu, irq);
kstat.irqs[thiscpu][irq]++;
kstat_cpu(thiscpu).irqs[irq]++;
action = *(irq + irq_action);
if (action) {
......
......@@ -103,7 +103,7 @@ void rt_timer_interrupt(struct pt_regs *regs)
if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
goto again;
kstat.irqs[cpu][irq]++; /* kstat only for bootcpu? */
kstat_cpu(cpu).irqs[irq]++; /* kstat only for bootcpu? */
if (cpu == 0)
do_timer(regs);
......
......@@ -232,7 +232,7 @@ int show_interrupts(struct seq_file *p, void *v)
#else
for (j = 0; j < smp_num_cpus; j++)
seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][irq_no]);
kstat_cpu(cpu_logical_map(j)).irqs[irq_no]);
#endif
seq_printf(p, " %14s",
region->data.name ? region->data.name : "N/A");
......
......@@ -189,7 +189,7 @@ inline void amiga_do_irq(int irq, struct pt_regs *fp)
irq_desc_t *desc = irq_desc + irq;
struct irqaction *action = desc->action;
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
action->handler(irq, action->dev_id, fp);
}
......@@ -198,7 +198,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)
irq_desc_t *desc = irq_desc + irq;
struct irqaction *action;
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
custom.intreq = ami_intena_vals[irq];
......
......@@ -148,7 +148,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
custom.intreq = base->int_mask;
for (i = 0; i < CIA_IRQS; i++, irq++) {
if (ints & 1) {
kstat.irqs[0][irq]++;
kstat_cpu(0).irqs[irq]++;
action = desc->action;
action->handler(irq, action->dev_id, fp);
}
......
......@@ -130,7 +130,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
{
if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
vec -= VEC_SPUR;
kstat.irqs[0][vec]++;
kstat_cpu(0).irqs[vec]++;
irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
} else {
if (mach_process_int)
......@@ -149,7 +149,7 @@ int m68k_get_irq_list(struct seq_file *p, void *v)
if (mach_default_handler) {
for (i = 0; i < SYS_IRQS; i++) {
seq_printf(p, "auto %2d: %10u ", i,
i ? kstat.irqs[0][i] : num_spurious);
i ? kstat_cpu(0).irqs[i] : num_spurious);
seq_puts(p, " ");
seq_printf(p, "%s\n", irq_list[i].devname);
}
......
......@@ -362,7 +362,7 @@ int show_interrupts(struct seq_file *p, void *v)
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ",
kstat.irqs[j][i]);
kstat_cpu(j).irqs[i]);
#else
seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */
......@@ -423,7 +423,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq;
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
ack_irq(irq);
/*
......
......@@ -357,7 +357,7 @@ int show_interrupts(struct seq_file *p, void *v)
#ifdef CONFIG_SMP
for (j = 0; j < NR_CPUS; j++) {
if (cpu_online(j))
seq_printf(p, "%10u ", kstat.irqs[j][i]);
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
}
#else
seq_printf(p, "%10u ", kstat_irqs(i));
......@@ -484,7 +484,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
if (naca->interrupt_controller == IC_OPEN_PIC)
balance_irq(irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
ack_irq(irq);
/*
......
......@@ -239,7 +239,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
:"=z" (irq));
irq = irq_demux(irq);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
desc = irq_desc + irq;
spin_lock(&desc->lock);
desc->handler->ack(irq);
......
......@@ -124,7 +124,7 @@ int show_interrupts(struct seq_file *p, void *v)
for (j = 0; j < NR_CPUS; j++) {
if (cpu_online(j))
seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
kstat_cpu(cpu_logical_map(j)).irqs[i]);
}
#endif
seq_printf(p, " %c %s",
......@@ -424,7 +424,7 @@ void handler_irq(int irq, struct pt_regs * regs)
smp4m_irq_rotate(cpu);
#endif
action = *(irq + irq_action);
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
do {
if (!action || !action->handler)
unexpected_irq(irq, 0, regs);
......@@ -444,7 +444,7 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
disable_pil_irq(irq);
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
floppy_interrupt(irq, dev_id, regs);
irq_exit();
enable_pil_irq(irq);
......
......@@ -102,7 +102,7 @@ found_it: seq_printf(p, "%3d: ", i);
for (x = 0; x < NR_CPUS; x++) {
if (cpu_online)
seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(x)][i]);
kstat_cpu(cpu_logical_map(x)).irqs[i]);
}
#endif
seq_printf(p, "%c %s",
......@@ -199,7 +199,7 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs)
cc_set_iclr(1 << irq);
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
if (!sbusl) {
action = *(irq + irq_action);
if (!action)
......
......@@ -135,7 +135,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!cpu_online(j))
continue;
seq_printf(p, "%10u ",
kstat.irqs[j][i]);
kstat_cpu(j).irqs[i]);
}
#endif
seq_printf(p, " %s:%lx", action->name,
......@@ -738,7 +738,7 @@ void handler_irq(int irq, struct pt_regs *regs)
#endif
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
if (irq == 9)
kbd_pt_regs = regs;
......@@ -813,7 +813,7 @@ void sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
int cpu = smp_processor_id();
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
*(irq_work(cpu, irq)) = 0;
bucket = get_ino_in_irqaction(action) + ivector_table;
......
......@@ -967,7 +967,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
if (cpu == boot_cpu_id) {
irq_enter();
kstat.irqs[cpu][0]++;
kstat_cpu(cpu).irqs[0]++;
timer_tick_interrupt(regs);
irq_exit();
......
......@@ -13,6 +13,7 @@
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
......
......@@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
......
......@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/slab.h>
#include <linux/blk.h>
#include <linux/swap.h>
......
......@@ -108,7 +108,7 @@ int get_irq_list(char *buf)
#else
for (j = 0; j < num_online_cpus(); j++)
p += sprintf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
kstat_cpu(cpu_logical_map(j)).irqs[i]);
#endif
p += sprintf(p, " %14s", irq_desc[i].handler->typename);
p += sprintf(p, " %s", action->name);
......@@ -283,7 +283,7 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
unsigned int status;
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
......
......@@ -151,7 +151,7 @@ int show_interrupts(struct seq_file *p, void *v)
#else
for_each_cpu(j)
seq_printf(p, "%10u ",
kstat.irqs[j][i]);
kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %s", action->name);
......@@ -328,7 +328,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
if (irq > 256) BUG();
irq_enter();
kstat.irqs[cpu][irq]++;
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
......
......@@ -32,7 +32,7 @@ obj-$(CONFIG_ACPI_INTERPRETER) += osl.o utils.o \
#
# ACPI Bus and Device Drivers
#
obj-$(CONFIG_ACPI_BUS) += bus.o driverfs.o
obj-$(CONFIG_ACPI_BUS) += bus.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
......
......@@ -27,7 +27,7 @@
#define __ACPI_BUS_H__
#include <linux/version.h>
#include <linux/driverfs_fs.h>
#include <linux/kobject.h>
#include "include/acpi.h"
......@@ -255,7 +255,7 @@ struct acpi_device {
struct acpi_device_ops ops;
struct acpi_driver *driver;
void *driver_data;
struct driver_dir_entry driverfs_dir;
struct kobject kobj;
};
#define acpi_driver_data(d) ((d)->driver_data)
......@@ -274,6 +274,7 @@ struct acpi_bus_event {
u32 data;
};
extern struct subsystem acpi_subsys;
/*
* External Functions
......
......@@ -675,6 +675,9 @@ acpi_bus_init (void)
return_VALUE(-ENODEV);
}
struct subsystem acpi_subsys = {
.kobj = { .name = "acpi" },
};
static int __init acpi_init (void)
{
......@@ -693,6 +696,8 @@ static int __init acpi_init (void)
return -ENODEV;
}
firmware_register(&acpi_subsys);
result = acpi_bus_init();
if (!result) {
......
/*
* driverfs.c - ACPI bindings for driverfs.
*
* Copyright (c) 2002 Patrick Mochel
* Copyright (c) 2002 The Open Source Development Lab
*
*/
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/driverfs_fs.h>
#include "acpi_bus.h"
static struct driver_dir_entry acpi_dir = {
.name = "acpi",
.mode = (S_IRWXU | S_IRUGO | S_IXUGO),
};
/* driverfs ops for ACPI attribute files go here, when/if
* there are ACPI attribute files.
* For now, we just have directory creation and removal.
*/
void acpi_remove_dir(struct acpi_device * dev)
{
if (dev)
driverfs_remove_dir(&dev->driverfs_dir);
}
int acpi_create_dir(struct acpi_device * dev)
{
struct driver_dir_entry * parent;
parent = dev->parent ? &dev->parent->driverfs_dir : &acpi_dir;
dev->driverfs_dir.name = dev->pnp.bus_id;
dev->driverfs_dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
return driverfs_create_dir(&dev->driverfs_dir,parent);
}
static int __init acpi_driverfs_init(void)
{
return driverfs_create_dir(&acpi_dir,NULL);
}
subsys_initcall(acpi_driverfs_init);
......@@ -25,20 +25,52 @@ extern struct acpi_device *acpi_root;
static LIST_HEAD(acpi_device_list);
static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
static int
acpi_device_register (
struct acpi_device *device,
struct acpi_device *parent)
static void acpi_device_release(struct kobject * kobj)
{
return acpi_create_dir(device);
struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
kfree(dev);
}
static struct subsystem acpi_namespace_subsys = {
.kobj = { .name = "namespace" },
.parent = &acpi_subsys,
.release = acpi_device_release,
};
static void acpi_device_register(struct acpi_device * device, struct acpi_device * parent)
{
/*
* Linkage
* -------
* Link this device to its parent and siblings.
*/
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->g_list);
spin_lock(&acpi_device_lock);
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
list_add_tail(&device->g_list,&device->parent->g_list);
} else
list_add_tail(&device->g_list,&acpi_device_list);
spin_unlock(&acpi_device_lock);
kobject_init(&device->kobj);
strncpy(device->kobj.name,device->pnp.bus_id,KOBJ_NAME_LEN);
if (parent)
device->kobj.parent = &parent->kobj;
device->kobj.subsys = &acpi_namespace_subsys;
kobject_register(&device->kobj);
}
static int
acpi_device_unregister (
struct acpi_device *device)
struct acpi_device *device,
int type)
{
acpi_remove_dir(device);
kobject_unregister(&device->kobj);
return 0;
}
......@@ -443,16 +475,6 @@ acpi_bus_get_flags (
return_VALUE(0);
}
static int
acpi_bus_remove (
struct acpi_device *device,
int type)
{
acpi_device_unregister(device);
kfree(device);
return 0;
}
static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handle, int type)
{
char bus_id[5] = {'?',0};
......@@ -621,28 +643,6 @@ void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle,
#endif /*CONFIG_ACPI_DEBUG*/
}
static void acpi_device_attach(struct acpi_device * device, struct acpi_device * parent)
{
/*
* Linkage
* -------
* Link this device to its parent and siblings.
*/
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->g_list);
spin_lock(&acpi_device_lock);
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
list_add_tail(&device->g_list,&device->parent->g_list);
} else
list_add_tail(&device->g_list,&acpi_device_list);
spin_unlock(&acpi_device_lock);
acpi_device_register(device, parent);
}
static int
acpi_bus_add (
struct acpi_device **child,
......@@ -741,7 +741,7 @@ acpi_bus_add (
acpi_device_get_debug_info(device,handle,type);
acpi_device_attach(device,parent);
acpi_device_register(device,parent);
/*
* Bind _ADR-Based Devices
......@@ -919,6 +919,8 @@ static int __init acpi_scan_init(void)
if (acpi_disabled)
return_VALUE(0);
subsystem_register(&acpi_namespace_subsys);
/*
* Create the root device in the bus's device tree
*/
......@@ -935,7 +937,7 @@ static int __init acpi_scan_init(void)
result = acpi_bus_scan(acpi_root);
if (result)
acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
Done:
return_VALUE(result);
......
......@@ -2,13 +2,14 @@
obj-y := core.o sys.o interface.o power.o bus.o \
driver.o class.o intf.o platform.o \
cpu.o
cpu.o firmware.o
obj-y += fs/
obj-$(CONFIG_HOTPLUG) += hotplug.o
export-objs := core.o power.o sys.o bus.o driver.o \
class.o intf.o platform.o cpu.o
class.o intf.o platform.o cpu.o \
firmware.o
include $(TOPDIR)/Rules.make
......@@ -10,44 +10,15 @@ extern struct list_head global_device_list;
extern spinlock_t device_lock;
extern struct semaphore device_sem;
extern struct device * get_device_locked(struct device *);
extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
extern int device_make_dir(struct device * dev);
extern void device_remove_dir(struct device * dev);
extern int bus_make_dir(struct bus_type * bus);
extern void bus_remove_dir(struct bus_type * bus);
extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
extern int driver_make_dir(struct device_driver * drv);
extern void driver_remove_dir(struct device_driver * drv);
extern int device_bus_link(struct device * dev);
extern void device_remove_symlink(struct driver_dir_entry * dir, const char * name);
extern int devclass_make_dir(struct device_class *);
extern void devclass_remove_dir(struct device_class *);
extern int devclass_drv_link(struct device_driver *);
extern void devclass_drv_unlink(struct device_driver *);
extern int devclass_dev_link(struct device_class *, struct device *);
extern void devclass_dev_unlink(struct device_class *, struct device *);
extern int devclass_add_device(struct device *);
extern void devclass_remove_device(struct device *);
extern int intf_make_dir(struct device_interface *);
extern void intf_remove_dir(struct device_interface *);
extern int intf_dev_link(struct intf_data *);
extern void intf_dev_unlink(struct intf_data *);
extern int interface_add(struct device_class *, struct device *);
extern void interface_remove(struct device_class *, struct device *);
......
......@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/init.h>
#include "base.h"
static LIST_HEAD(bus_driver_list);
......@@ -19,6 +20,109 @@ static LIST_HEAD(bus_driver_list);
#define to_dev(node) container_of(node,struct device,bus_list)
#define to_drv(node) container_of(node,struct device_driver,bus_list)
#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
#define to_bus(obj) container_of(obj,struct bus_type,subsys.kobj)
/*
* sysfs bindings for drivers
*/
#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr)
#define to_driver(obj) container_of(obj, struct device_driver, kobj)
static ssize_t
drv_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
ssize_t ret = 0;
if (drv_attr->show)
ret = drv_attr->show(drv,buf,count,off);
return ret;
}
static ssize_t
drv_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
ssize_t ret = 0;
if (drv_attr->store)
ret = drv_attr->store(drv,buf,count,off);
return ret;
}
static struct sysfs_ops driver_sysfs_ops = {
.show = drv_attr_show,
.store = drv_attr_store,
};
/*
* sysfs bindings for drivers
*/
static ssize_t
bus_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(kobj);
ssize_t ret = 0;
if (bus_attr->show)
ret = bus_attr->show(bus,buf,count,off);
return ret;
}
static ssize_t
bus_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(kobj);
ssize_t ret = 0;
if (bus_attr->store)
ret = bus_attr->store(bus,buf,count,off);
return ret;
}
static struct sysfs_ops bus_sysfs_ops = {
.show = bus_attr_show,
.store = bus_attr_store,
};
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
{
int error;
if (get_bus(bus)) {
error = sysfs_create_file(&bus->subsys.kobj,&attr->attr);
put_bus(bus);
} else
error = -EINVAL;
return error;
}
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
{
if (get_bus(bus)) {
sysfs_remove_file(&bus->subsys.kobj,&attr->attr);
put_bus(bus);
}
}
struct subsystem bus_subsys = {
.kobj = { .name = "bus" },
.sysfs_ops = &bus_sysfs_ops,
};
/**
* bus_for_each_dev - walk list of devices and do something to each
* @bus: bus in question
......@@ -92,6 +196,7 @@ static void attach(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,dev->kobj.name);
}
static int bus_match(struct device * dev, struct device_driver * drv)
......@@ -162,6 +267,7 @@ static int driver_attach(struct device_driver * drv)
static void detach(struct device * dev, struct device_driver * drv)
{
if (drv) {
sysfs_remove_link(&drv->kobj,dev->kobj.name);
list_del_init(&dev->driver_list);
devclass_remove_device(dev);
if (drv->remove)
......@@ -206,7 +312,7 @@ int bus_add_device(struct device * dev)
list_add_tail(&dev->bus_list,&dev->bus->devices);
device_attach(dev);
up_write(&dev->bus->rwsem);
device_bus_link(dev);
sysfs_create_link(&bus->devsubsys.kobj,&dev->kobj,dev->bus_id);
}
return 0;
}
......@@ -221,9 +327,9 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
sysfs_remove_link(&dev->bus->devsubsys.kobj,dev->bus_id);
down_write(&dev->bus->rwsem);
pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id);
device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
device_detach(dev);
list_del_init(&dev->bus_list);
up_write(&dev->bus->rwsem);
......@@ -240,7 +346,6 @@ int bus_add_driver(struct device_driver * drv)
list_add_tail(&drv->bus_list,&bus->drivers);
driver_attach(drv);
up_write(&bus->rwsem);
driver_make_dir(drv);
}
return 0;
}
......@@ -275,7 +380,6 @@ void put_bus(struct bus_type * bus)
list_del_init(&bus->node);
spin_unlock(&device_lock);
WARN_ON(bus->present);
bus_remove_dir(bus);
}
int bus_register(struct bus_type * bus)
......@@ -286,16 +390,25 @@ int bus_register(struct bus_type * bus)
atomic_set(&bus->refcount,2);
bus->present = 1;
strncpy(bus->subsys.kobj.name,bus->name,KOBJ_NAME_LEN);
bus->subsys.parent = &bus_subsys;
subsystem_register(&bus->subsys);
snprintf(bus->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
bus->devsubsys.parent = &bus->subsys;
subsystem_register(&bus->devsubsys);
snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers");
bus->drvsubsys.parent = &bus->subsys;
bus->drvsubsys.sysfs_ops = &driver_sysfs_ops;
subsystem_register(&bus->drvsubsys);
spin_lock(&device_lock);
list_add_tail(&bus->node,&bus_driver_list);
spin_unlock(&device_lock);
pr_debug("bus type '%s' registered\n",bus->name);
/* give it some driverfs entities */
bus_make_dir(bus);
put_bus(bus);
return 0;
}
......@@ -306,9 +419,19 @@ void bus_unregister(struct bus_type * bus)
spin_unlock(&device_lock);
pr_debug("bus %s: unregistering\n",bus->name);
subsystem_unregister(&bus->drvsubsys);
subsystem_unregister(&bus->devsubsys);
subsystem_unregister(&bus->subsys);
put_bus(bus);
}
static int __init bus_subsys_init(void)
{
return subsystem_register(&bus_subsys);
}
core_initcall(bus_subsys_init);
EXPORT_SYMBOL(bus_for_each_dev);
EXPORT_SYMBOL(bus_for_each_drv);
EXPORT_SYMBOL(bus_add_device);
......@@ -317,3 +440,6 @@ EXPORT_SYMBOL(bus_register);
EXPORT_SYMBOL(bus_unregister);
EXPORT_SYMBOL(get_bus);
EXPORT_SYMBOL(put_bus);
EXPORT_SYMBOL(bus_create_file);
EXPORT_SYMBOL(bus_remove_file);
......@@ -4,10 +4,98 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include "base.h"
static LIST_HEAD(class_list);
#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
#define to_class(obj) container_of(obj,struct device_class,subsys.kobj)
static ssize_t
devclass_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct devclass_attribute * class_attr = to_class_attr(attr);
struct device_class * dc = to_class(kobj);
ssize_t ret = 0;
if (class_attr->show)
ret = class_attr->show(dc,buf,count,off);
return ret;
}
static ssize_t
devclass_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct devclass_attribute * class_attr = to_class_attr(attr);
struct device_class * dc = to_class(kobj);
ssize_t ret = 0;
if (class_attr->store)
ret = class_attr->store(dc,buf,count,off);
return ret;
}
static struct sysfs_ops class_sysfs_ops = {
show: devclass_attr_show,
store: devclass_attr_store,
};
static struct subsystem class_subsys = {
.kobj = { .name = "class", },
.sysfs_ops = &class_sysfs_ops,
};
static int devclass_dev_link(struct device_class * cls, struct device * dev)
{
char linkname[16];
snprintf(linkname,16,"%u",dev->class_num);
return sysfs_create_link(&cls->devsubsys.kobj,&dev->kobj,linkname);
}
static void devclass_dev_unlink(struct device_class * cls, struct device * dev)
{
char linkname[16];
snprintf(linkname,16,"%u",dev->class_num);
sysfs_remove_link(&cls->devsubsys.kobj,linkname);
}
static int devclass_drv_link(struct device_driver * drv)
{
char name[KOBJ_NAME_LEN * 3];
snprintf(name,KOBJ_NAME_LEN * 3,"%s:%s",drv->bus->name,drv->name);
return sysfs_create_link(&drv->devclass->drvsubsys.kobj,&drv->kobj,name);
}
static void devclass_drv_unlink(struct device_driver * drv)
{
char name[KOBJ_NAME_LEN * 3];
snprintf(name,KOBJ_NAME_LEN * 3,"%s:%s",drv->bus->name,drv->name);
return sysfs_remove_link(&drv->devclass->drvsubsys.kobj,name);
}
int devclass_create_file(struct device_class * cls, struct devclass_attribute * attr)
{
int error;
if (cls) {
error = sysfs_create_file(&cls->subsys.kobj,&attr->attr);
} else
error = -EINVAL;
return error;
}
void devclass_remove_file(struct device_class * cls, struct devclass_attribute * attr)
{
if (cls)
sysfs_remove_file(&cls->subsys.kobj,&attr->attr);
}
int devclass_add_driver(struct device_driver * drv)
{
struct device_class * cls = get_devclass(drv->devclass);
......@@ -136,7 +224,6 @@ void put_devclass(struct device_class * cls)
if (atomic_dec_and_lock(&cls->refcount,&device_lock)) {
list_del_init(&cls->node);
spin_unlock(&device_lock);
devclass_remove_dir(cls);
}
}
......@@ -150,10 +237,21 @@ int devclass_register(struct device_class * cls)
cls->present = 1;
pr_debug("device class '%s': registering\n",cls->name);
strncpy(cls->subsys.kobj.name,cls->name,KOBJ_NAME_LEN);
cls->subsys.parent = &class_subsys;
subsystem_register(&cls->subsys);
snprintf(cls->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
cls->devsubsys.parent = &cls->subsys;
subsystem_register(&cls->devsubsys);
snprintf(cls->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers");
cls->drvsubsys.parent = &cls->subsys;
subsystem_register(&cls->drvsubsys);
spin_lock(&device_lock);
list_add_tail(&cls->node,&class_list);
spin_unlock(&device_lock);
devclass_make_dir(cls);
put_devclass(cls);
return 0;
}
......@@ -164,9 +262,19 @@ void devclass_unregister(struct device_class * cls)
cls->present = 0;
spin_unlock(&device_lock);
pr_debug("device class '%s': unregistering\n",cls->name);
subsystem_unregister(&cls->drvsubsys);
subsystem_unregister(&cls->devsubsys);
subsystem_unregister(&cls->subsys);
put_devclass(cls);
}
static int __init class_subsys_init(void)
{
return subsystem_register(&class_subsys);
}
core_initcall(class_subsys_init);
EXPORT_SYMBOL(devclass_register);
EXPORT_SYMBOL(devclass_unregister);
EXPORT_SYMBOL(get_devclass);
......
......@@ -23,7 +23,74 @@ DECLARE_MUTEX(device_sem);
spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
#define to_dev(node) container_of(node,struct device,driver_list)
#define to_dev(obj) container_of(obj,struct device,kobj)
/*
* sysfs bindings for devices.
*/
#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
extern struct attribute * dev_default_attrs[];
static ssize_t
dev_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
ssize_t ret = 0;
if (dev_attr->show)
ret = dev_attr->show(dev,buf,count,off);
return ret;
}
static ssize_t
dev_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
ssize_t ret = 0;
if (dev_attr->store)
ret = dev_attr->store(dev,buf,count,off);
return ret;
}
static struct sysfs_ops dev_sysfs_ops = {
.show = dev_attr_show,
.store = dev_attr_store,
};
struct subsystem device_subsys = {
.kobj = {
.name = "devices",
},
.sysfs_ops = &dev_sysfs_ops,
.default_attrs = dev_default_attrs,
};
int device_create_file(struct device * dev, struct device_attribute * attr)
{
int error = 0;
if (get_device(dev)) {
error = sysfs_create_file(&dev->kobj,&attr->attr);
put_device(dev);
}
return error;
}
void device_remove_file(struct device * dev, struct device_attribute * attr)
{
if (get_device(dev)) {
sysfs_remove_file(&dev->kobj,&attr->attr);
put_device(dev);
}
}
int device_add(struct device *dev)
{
......@@ -44,7 +111,11 @@ int device_add(struct device *dev)
pr_debug("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
if ((error = device_make_dir(dev)))
strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN);
if (dev->parent)
dev->kobj.parent = &dev->parent->kobj;
dev->kobj.subsys = &device_subsys;
if ((error = kobject_register(&dev->kobj)))
goto register_done;
bus_add_device(dev);
......@@ -69,6 +140,7 @@ int device_add(struct device *dev)
void device_initialize(struct device *dev)
{
kobject_init(&dev->kobj);
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->g_list);
......@@ -157,9 +229,6 @@ void device_del(struct device * dev)
bus_remove_device(dev);
/* remove the driverfs directory */
device_remove_dir(dev);
if (dev->release)
dev->release(dev);
......@@ -184,10 +253,21 @@ void device_unregister(struct device * dev)
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
kobject_unregister(&dev->kobj);
put_device(dev);
}
static int __init device_subsys_init(void)
{
return subsystem_register(&device_subsys);
}
core_initcall(device_subsys_init);
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(device_unregister);
EXPORT_SYMBOL(get_device);
EXPORT_SYMBOL(put_device);
EXPORT_SYMBOL(device_create_file);
EXPORT_SYMBOL(device_remove_file);
......@@ -12,6 +12,29 @@
#define to_dev(node) container_of(node,struct device,driver_list)
/*
* helpers for creating driver attributes in sysfs
*/
int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
{
int error;
if (get_driver(drv)) {
error = sysfs_create_file(&drv->kobj,&attr->attr);
put_driver(drv);
} else
error = -EINVAL;
return error;
}
void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
{
if (get_driver(drv)) {
sysfs_remove_file(&drv->kobj,&attr->attr);
put_driver(drv);
}
}
int driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device *, void * ))
{
......@@ -65,7 +88,6 @@ void put_driver(struct device_driver * drv)
return;
spin_unlock(&device_lock);
BUG_ON(drv->present);
bus_remove_driver(drv);
if (drv->release)
drv->release(drv);
put_bus(bus);
......@@ -84,6 +106,11 @@ int driver_register(struct device_driver * drv)
pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name);
kobject_init(&drv->kobj);
strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
drv->kobj.subsys = &drv->bus->drvsubsys;
kobject_register(&drv->kobj);
get_bus(drv->bus);
atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock);
......@@ -108,3 +135,6 @@ EXPORT_SYMBOL(driver_register);
EXPORT_SYMBOL(driver_unregister);
EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver);
EXPORT_SYMBOL(driver_create_file);
EXPORT_SYMBOL(driver_remove_file);
/*
* firmware.c - firmware subsystem hoohaw.
*/
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/init.h>
static struct subsystem firmware_subsys = {
.kobj = { .name = "firmware" },
};
int firmware_register(struct subsystem * s)
{
s->parent = &firmware_subsys;
return subsystem_register(s);
}
void firmware_unregister(struct subsystem * s)
{
subsystem_unregister(s);
}
static int __init firmware_init(void)
{
return subsystem_register(&firmware_subsys);
}
core_initcall(firmware_init);
EXPORT_SYMBOL(firmware_register);
EXPORT_SYMBOL(firmware_unregister);
obj-y := device.o bus.o driver.o class.o intf.o
obj-y := device.o
export-objs := device.o bus.o driver.o class.o
export-objs := device.o
include $(TOPDIR)/Rules.make
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/stat.h>
#include "fs.h"
static struct driver_dir_entry bus_dir;
#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
#define to_bus(dir) container_of(dir,struct bus_type,dir)
/* driverfs ops for device attribute files */
static int
bus_attr_open(struct driver_dir_entry * dir)
{
struct bus_type * bus = to_bus(dir);
get_bus(bus);
return 0;
}
static int
bus_attr_close(struct driver_dir_entry * dir)
{
struct bus_type * bus = to_bus(dir);
put_bus(bus);
return 0;
}
static ssize_t
bus_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(dir);
ssize_t ret = 0;
if (bus_attr->show)
ret = bus_attr->show(bus,buf,count,off);
return ret;
}
static ssize_t
bus_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(dir);
ssize_t ret = 0;
if (bus_attr->store)
ret = bus_attr->store(bus,buf,count,off);
return ret;
}
static struct driverfs_ops bus_attr_ops = {
.open = bus_attr_open,
.close = bus_attr_close,
.show = bus_attr_show,
.store = bus_attr_store,
};
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
{
int error;
if (get_bus(bus)) {
error = driverfs_create_file(&attr->attr,&bus->dir);
put_bus(bus);
} else
error = -EINVAL;
return error;
}
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
{
if (get_bus(bus)) {
driverfs_remove_file(&bus->dir,attr->attr.name);
put_bus(bus);
}
}
int bus_make_dir(struct bus_type * bus)
{
int error;
bus->dir.name = bus->name;
bus->dir.ops = &bus_attr_ops;
error = device_create_dir(&bus->dir,&bus_dir);
if (!error) {
bus->device_dir.name = "devices";
device_create_dir(&bus->device_dir,&bus->dir);
bus->driver_dir.name = "drivers";
device_create_dir(&bus->driver_dir,&bus->dir);
}
return error;
}
void bus_remove_dir(struct bus_type * bus)
{
/* remove driverfs entries */
driverfs_remove_dir(&bus->driver_dir);
driverfs_remove_dir(&bus->device_dir);
driverfs_remove_dir(&bus->dir);
}
static struct driver_dir_entry bus_dir = {
.name = "bus",
.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
};
static int __init bus_init(void)
{
/* make 'bus' driverfs directory */
return driverfs_create_dir(&bus_dir,NULL);
}
core_initcall(bus_init);
EXPORT_SYMBOL(bus_create_file);
EXPORT_SYMBOL(bus_remove_file);
/*
* class.c - driverfs bindings for device classes.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include "fs.h"
static struct driver_dir_entry class_dir;
#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
#define to_class(d) container_of(d,struct device_class,dir)
static ssize_t
devclass_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct devclass_attribute * class_attr = to_class_attr(attr);
struct device_class * dc = to_class(dir);
ssize_t ret = 0;
if (class_attr->show)
ret = class_attr->show(dc,buf,count,off);
return ret;
}
static ssize_t
devclass_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct devclass_attribute * class_attr = to_class_attr(attr);
struct device_class * dc = to_class(dir);
ssize_t ret = 0;
if (class_attr->store)
ret = class_attr->store(dc,buf,count,off);
return ret;
}
static struct driverfs_ops devclass_attr_ops = {
show: devclass_attr_show,
store: devclass_attr_store,
};
int devclass_create_file(struct device_class * dc, struct devclass_attribute * attr)
{
int error;
if (dc) {
error = driverfs_create_file(&attr->attr,&dc->dir);
} else
error = -EINVAL;
return error;
}
void devclass_remove_file(struct device_class * dc, struct devclass_attribute * attr)
{
if (dc)
driverfs_remove_file(&dc->dir,attr->attr.name);
}
/**
* devclass_dev_link - create symlink to device's directory
* @cls - device class we're a part of
* @dev - device we're linking to
*
* Create a symlink in the class's devices/ directory to @dev's
* directory in the physical hierarchy. The name is the device's
* class-enumerated value (struct device::class_num). We're
* creating:
* class/<class name>/devices/<link name> ->
* root/<path to device>/<device's dir>
* So, the link looks like:
* ../../../root/<path to device>/
*/
int devclass_dev_link(struct device_class * cls, struct device * dev)
{
char linkname[16];
char * path;
int length;
int error;
length = get_devpath_length(dev);
length += strlen("../../../root");
if (length > PATH_MAX)
return -ENAMETOOLONG;
if (!(path = kmalloc(length,GFP_KERNEL)))
return -ENOMEM;
memset(path,0,length);
strcpy(path,"../../../root");
fill_devpath(dev,path,length);
snprintf(linkname,16,"%u",dev->class_num);
error = driverfs_create_symlink(&cls->device_dir,linkname,path);
kfree(path);
return error;
}
void devclass_dev_unlink(struct device_class * cls, struct device * dev)
{
char linkname[16];
snprintf(linkname,16,"%u",dev->class_num);
driverfs_remove_file(&cls->device_dir,linkname);
}
/**
* devclass_drv_link - create symlink to driver's directory
* @drv: driver we're linking up
*
* Create a symlink in the class's drivers/ directory to @drv's
* directory (in the bus's directory). It's name is <bus>:<driver>
* to prevent naming conflicts.
*
* We're creating
* class/<class name>/drivers/<link name> ->
* bus/<bus name>/drivers/<driver name>/
* So, the link looks like:
* ../../../bus/<bus name>/drivers/<driver name>
*/
int devclass_drv_link(struct device_driver * drv)
{
char * name;
char * path;
int namelen;
int pathlen;
int error = 0;
namelen = strlen(drv->name) + strlen(drv->bus->name) + 2;
name = kmalloc(namelen,GFP_KERNEL);
if (!name)
return -ENOMEM;
snprintf(name,namelen,"%s:%s",drv->bus->name,drv->name);
pathlen = strlen("../../../bus/") +
strlen(drv->bus->name) +
strlen("/drivers/") +
strlen(drv->name) + 1;
if (!(path = kmalloc(pathlen,GFP_KERNEL))) {
error = -ENOMEM;
goto Done;
}
snprintf(path,pathlen,"%s%s%s%s",
"../../../bus/",
drv->bus->name,
"/drivers/",
drv->name);
error = driverfs_create_symlink(&drv->devclass->driver_dir,name,path);
Done:
kfree(name);
kfree(path);
return error;
}
void devclass_drv_unlink(struct device_driver * drv)
{
char * name;
int length;
length = strlen(drv->name) + strlen(drv->bus->name) + 2;
if ((name = kmalloc(length,GFP_KERNEL))) {
driverfs_remove_file(&drv->devclass->driver_dir,name);
kfree(name);
}
}
void devclass_remove_dir(struct device_class * dc)
{
driverfs_remove_dir(&dc->device_dir);
driverfs_remove_dir(&dc->driver_dir);
driverfs_remove_dir(&dc->dir);
}
int devclass_make_dir(struct device_class * dc)
{
int error;
dc->dir.name = dc->name;
dc->dir.ops = &devclass_attr_ops;
error = device_create_dir(&dc->dir,&class_dir);
if (!error) {
dc->driver_dir.name = "drivers";
error = device_create_dir(&dc->driver_dir,&dc->dir);
if (!error) {
dc->device_dir.name = "devices";
error = device_create_dir(&dc->device_dir,&dc->dir);
}
if (error)
driverfs_remove_dir(&dc->dir);
}
return error;
}
static struct driver_dir_entry class_dir = {
name: "class",
mode: (S_IRWXU | S_IRUGO | S_IXUGO),
};
static int __init devclass_driverfs_init(void)
{
return driverfs_create_dir(&class_dir,NULL);
}
core_initcall(devclass_driverfs_init);
EXPORT_SYMBOL(devclass_create_file);
EXPORT_SYMBOL(devclass_remove_file);
......@@ -16,112 +16,6 @@
#include <linux/stat.h>
#include <linux/limits.h>
static struct driver_dir_entry device_root_dir = {
.name = "root",
.mode = (S_IRWXU | S_IRUGO | S_IXUGO),
};
extern struct device_attribute * device_default_files[];
#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
#define to_device(d) container_of(d, struct device, dir)
/* driverfs ops for device attribute files */
static int
dev_attr_open(struct driver_dir_entry * dir)
{
struct device * dev = to_device(dir);
get_device(dev);
return 0;
}
static int
dev_attr_close(struct driver_dir_entry * dir)
{
struct device * dev = to_device(dir);
put_device(dev);
return 0;
}
static ssize_t
dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_device(dir);
ssize_t ret = 0;
if (dev_attr->show)
ret = dev_attr->show(dev,buf,count,off);
return ret;
}
static ssize_t
dev_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_device(dir);
ssize_t ret = 0;
if (dev_attr->store)
ret = dev_attr->store(dev,buf,count,off);
return ret;
}
static struct driverfs_ops dev_attr_ops = {
.open = dev_attr_open,
.close = dev_attr_close,
.show = dev_attr_show,
.store = dev_attr_store,
};
/**
* device_create_file - create a driverfs file for a device
* @dev: device requesting file
* @entry: entry describing file
*
* Allocate space for file entry, copy descriptor, and create.
*/
int device_create_file(struct device * dev, struct device_attribute * entry)
{
int error = -EINVAL;
if (get_device(dev)) {
error = driverfs_create_file(&entry->attr,&dev->dir);
put_device(dev);
}
return error;
}
/**
* device_remove_file - remove a device's file by name
* @dev: device requesting removal
* @name: name of the file
*
*/
void device_remove_file(struct device * dev, struct device_attribute * attr)
{
if (dev) {
get_device(dev);
driverfs_remove_file(&dev->dir,attr->attr.name);
put_device(dev);
}
}
/**
* device_remove_dir - remove a device's directory
* @dev: device in question
*/
void device_remove_dir(struct device * dev)
{
if (dev)
driverfs_remove_dir(&dev->dir);
}
int get_devpath_length(struct device * dev)
{
int length = 1;
......@@ -153,92 +47,3 @@ void fill_devpath(struct device * dev, char * path, int length)
pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
}
int device_bus_link(struct device * dev)
{
char * path;
int length;
int error = 0;
if (!dev->bus)
return 0;
length = get_devpath_length(dev);
/* now add the path from the bus directory
* It should be '../../..' (one to get to the bus's directory,
* one to get to the 'bus' directory, and one to get to the root
* of the fs.)
*/
length += strlen("../../../root");
if (length > PATH_MAX)
return -ENAMETOOLONG;
if (!(path = kmalloc(length,GFP_KERNEL)))
return -ENOMEM;
memset(path,0,length);
/* our relative position */
strcpy(path,"../../../root");
fill_devpath(dev,path,length);
error = driverfs_create_symlink(&dev->bus->device_dir,dev->bus_id,path);
kfree(path);
return error;
}
void device_remove_symlink(struct driver_dir_entry * dir, const char * name)
{
driverfs_remove_file(dir,name);
}
int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent)
{
dir->mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
return driverfs_create_dir(dir,parent);
}
/**
* device_make_dir - create a driverfs directory
* @name: name of directory
* @parent: dentry for the parent directory
*
* Do the initial creation of the device's driverfs directory
* and populate it with the one default file.
*
* This is just a helper for device_register(), as we
* don't export this function. (Yes, that means we don't allow
* devices to create subdirectories).
*/
int device_make_dir(struct device * dev)
{
struct driver_dir_entry * parent;
struct device_attribute * entry;
int error;
int i;
parent = dev->parent ? &dev->parent->dir : &device_root_dir;
dev->dir.name = dev->bus_id;
dev->dir.ops = &dev_attr_ops;
if ((error = device_create_dir(&dev->dir,parent)))
return error;
for (i = 0; (entry = *(device_default_files + i)); i++) {
if ((error = device_create_file(dev,entry))) {
device_remove_dir(dev);
break;
}
}
return error;
}
static int device_driverfs_init(void)
{
return driverfs_create_dir(&device_root_dir,NULL);
}
core_initcall(device_driverfs_init);
EXPORT_SYMBOL(device_create_file);
EXPORT_SYMBOL(device_remove_file);
#include <linux/device.h>
#include <linux/module.h>
#include <linux/stat.h>
#include <linux/err.h>
#include "fs.h"
#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr)
#define to_drv(d) container_of(d, struct device_driver, dir)
/* driverfs ops for device attribute files */
static int
drv_attr_open(struct driver_dir_entry * dir)
{
struct device_driver * drv = to_drv(dir);
get_driver(drv);
return 0;
}
static int
drv_attr_close(struct driver_dir_entry * dir)
{
struct device_driver * drv = to_drv(dir);
put_driver(drv);
return 0;
}
static ssize_t
drv_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_drv(dir);
ssize_t ret = 0;
if (drv_attr->show)
ret = drv_attr->show(drv,buf,count,off);
return ret;
}
static ssize_t
drv_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_drv(dir);
ssize_t ret = 0;
if (drv_attr->store)
ret = drv_attr->store(drv,buf,count,off);
return ret;
}
static struct driverfs_ops drv_attr_ops = {
.open = drv_attr_open,
.close = drv_attr_close,
.show = drv_attr_show,
.store = drv_attr_store,
};
int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
{
int error;
if (get_driver(drv)) {
error = driverfs_create_file(&attr->attr,&drv->dir);
put_driver(drv);
} else
error = -EINVAL;
return error;
}
void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
{
if (get_driver(drv)) {
driverfs_remove_file(&drv->dir,attr->attr.name);
put_driver(drv);
}
}
/**
* driver_make_dir - create a driverfs directory for a driver
* @drv: driver in question
*/
int driver_make_dir(struct device_driver * drv)
{
drv->dir.name = drv->name;
drv->dir.ops = &drv_attr_ops;
return device_create_dir(&drv->dir,&drv->bus->driver_dir);
}
void driver_remove_dir(struct device_driver * drv)
{
driverfs_remove_dir(&drv->dir);
}
EXPORT_SYMBOL(driver_create_file);
EXPORT_SYMBOL(driver_remove_file);
extern int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent);
int get_devpath_length(struct device * dev);
void fill_devpath(struct device * dev, char * path, int length);
......
/*
* intf.c - driverfs glue for device interfaces
*/
#include <linux/device.h>
#include <linux/slab.h>
#include "fs.h"
/**
* intf_dev_link - symlink from interface's directory to device's directory
*
*/
int intf_dev_link(struct intf_data * data)
{
char linkname[16];
char * path;
int length;
int error;
length = get_devpath_length(data->dev);
length += strlen("../../../root");
if (length > PATH_MAX)
return -ENAMETOOLONG;
if (!(path = kmalloc(length,GFP_KERNEL)))
return -ENOMEM;
memset(path,0,length);
strcpy(path,"../../../root");
fill_devpath(data->dev,path,length);
snprintf(linkname,16,"%u",data->intf_num);
error = driverfs_create_symlink(&data->intf->dir,linkname,path);
kfree(path);
return error;
}
void intf_dev_unlink(struct intf_data * data)
{
char linkname[16];
snprintf(linkname,16,"%u",data->intf_num);
driverfs_remove_file(&data->intf->dir,linkname);
}
void intf_remove_dir(struct device_interface * intf)
{
driverfs_remove_dir(&intf->dir);
}
int intf_make_dir(struct device_interface * intf)
{
intf->dir.name = intf->name;
return device_create_dir(&intf->dir,&intf->devclass->dir);
}
......@@ -88,8 +88,8 @@ device_write_power(struct device * dev, const char * buf, size_t count, loff_t o
static DEVICE_ATTR(power,S_IWUSR | S_IRUGO,
device_read_power,device_write_power);
struct device_attribute * device_default_files[] = {
&dev_attr_name,
&dev_attr_power,
struct attribute * dev_default_attrs[] = {
&dev_attr_name.attr,
&dev_attr_power.attr,
NULL,
};
......@@ -11,6 +11,26 @@
#define to_intf(node) container_of(node,struct device_interface,node)
/**
* intf_dev_link - symlink from interface's directory to device's directory
*
*/
static int intf_dev_link(struct intf_data * data)
{
char linkname[16];
snprintf(linkname,16,"%u",data->intf_num);
return sysfs_create_link(&data->intf->kobj,&data->dev->kobj,linkname);
}
static void intf_dev_unlink(struct intf_data * data)
{
char linkname[16];
snprintf(linkname,16,"%u",data->intf_num);
sysfs_remove_link(&data->intf->kobj,linkname);
}
int interface_register(struct device_interface * intf)
{
struct device_class * cls = intf->devclass;
......@@ -18,7 +38,11 @@ int interface_register(struct device_interface * intf)
if (cls) {
pr_debug("register interface '%s' with class '%s\n",
intf->name,cls->name);
intf_make_dir(intf);
kobject_init(&intf->kobj);
strncpy(intf->kobj.name,intf->name,KOBJ_NAME_LEN);
intf->kobj.subsys = &cls->subsys;
kobject_register(&intf->kobj);
spin_lock(&device_lock);
list_add_tail(&intf->node,&cls->intf_list);
spin_unlock(&device_lock);
......@@ -31,11 +55,10 @@ void interface_unregister(struct device_interface * intf)
{
pr_debug("unregistering interface '%s' from class '%s'\n",
intf->name,intf->devclass->name);
kobject_unregister(&intf->kobj);
spin_lock(&device_lock);
list_del_init(&intf->node);
spin_unlock(&device_lock);
intf_remove_dir(intf);
}
int interface_add(struct device_class * cls, struct device * dev)
......
......@@ -252,14 +252,6 @@ struct seq_operations partitions_op = {
extern int blk_dev_init(void);
struct device_class disk_devclass = {
.name = "disk",
};
static struct bus_type disk_bus = {
name: "block",
};
static struct gendisk *base_probe(dev_t dev, int *part, void *data)
{
char name[20];
......@@ -268,6 +260,8 @@ static struct gendisk *base_probe(dev_t dev, int *part, void *data)
return NULL;
}
struct subsystem block_subsys;
int __init device_init(void)
{
struct blk_probe *base = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
......@@ -280,23 +274,116 @@ int __init device_init(void)
for (i = 1; i < MAX_BLKDEV; i++)
probes[i] = base;
blk_dev_init();
devclass_register(&disk_devclass);
bus_register(&disk_bus);
subsystem_register(&block_subsys);
return 0;
}
__initcall(device_init);
subsys_initcall(device_init);
/*
* kobject & sysfs bindings for block devices
*/
#define to_disk(obj) container_of(obj,struct gendisk,kobj)
struct disk_attribute {
struct attribute attr;
ssize_t (*show)(struct gendisk *, char *, size_t, loff_t);
};
static ssize_t disk_attr_show(struct kobject * kobj, struct attribute * attr,
char * page, size_t count, loff_t off)
{
struct gendisk * disk = to_disk(kobj);
struct disk_attribute * disk_attr = container_of(attr,struct disk_attribute,attr);
ssize_t ret = 0;
if (disk_attr->show)
ret = disk_attr->show(disk,page,count,off);
return ret;
}
static struct sysfs_ops disk_sysfs_ops = {
.show = &disk_attr_show,
};
static ssize_t disk_dev_read(struct gendisk * disk,
char *page, size_t count, loff_t off)
{
dev_t base = MKDEV(disk->major, disk->first_minor);
return off ? 0 : sprintf(page, "%04x\n",base);
}
static ssize_t disk_range_read(struct gendisk * disk,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf(page, "%d\n",disk->minors);
}
static ssize_t disk_size_read(struct gendisk * disk,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
}
static inline unsigned MSEC(unsigned x)
{
return x * 1000 / HZ;
}
static ssize_t disk_stat_read(struct gendisk * disk,
char *page, size_t count, loff_t off)
{
disk_round_stats(disk);
return off ? 0 : sprintf(page,
"%8u %8u %8llu %8u "
"%8u %8u %8llu %8u "
"%8u %8u %8u"
"\n",
disk->reads, disk->read_merges, (u64)disk->read_sectors,
MSEC(disk->read_ticks),
disk->writes, disk->write_merges, (u64)disk->write_sectors,
MSEC(disk->write_ticks),
disk->in_flight, MSEC(disk->io_ticks),
MSEC(disk->time_in_queue));
}
static struct disk_attribute disk_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
.show = disk_dev_read
};
static struct disk_attribute disk_attr_range = {
.attr = {.name = "range", .mode = S_IRUGO },
.show = disk_range_read
};
static struct disk_attribute disk_attr_size = {
.attr = {.name = "size", .mode = S_IRUGO },
.show = disk_size_read
};
static struct disk_attribute disk_attr_stat = {
.attr = {.name = "stat", .mode = S_IRUGO },
.show = disk_stat_read
};
EXPORT_SYMBOL(disk_devclass);
static struct attribute * default_attrs[] = {
&disk_attr_dev.attr,
&disk_attr_range.attr,
&disk_attr_size.attr,
&disk_attr_stat.attr,
NULL,
};
static void disk_release(struct device *dev)
static void disk_release(struct kobject * kobj)
{
struct gendisk *disk = dev->driver_data;
struct gendisk *disk = to_disk(kobj);
kfree(disk->random);
kfree(disk->part);
kfree(disk);
}
struct subsystem block_subsys = {
.kobj = { .name = "block" },
.release = disk_release,
.sysfs_ops = &disk_sysfs_ops,
.default_attrs = default_attrs,
};
struct gendisk *alloc_disk(int minors)
{
struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
......@@ -314,11 +401,9 @@ struct gendisk *alloc_disk(int minors)
disk->minors = minors;
while (minors >>= 1)
disk->minor_shift++;
kobject_init(&disk->kobj);
disk->kobj.subsys = &block_subsys;
INIT_LIST_HEAD(&disk->full_list);
disk->disk_dev.bus = &disk_bus;
disk->disk_dev.release = disk_release;
disk->disk_dev.driver_data = disk;
device_initialize(&disk->disk_dev);
}
rand_initialize_disk(disk);
return disk;
......@@ -332,14 +417,13 @@ struct gendisk *get_disk(struct gendisk *disk)
owner = disk->fops->owner;
if (owner && !try_inc_mod_count(owner))
return NULL;
atomic_inc(&disk->disk_dev.refcount);
return disk;
return to_disk(kobject_get(&disk->kobj));
}
void put_disk(struct gendisk *disk)
{
if (disk)
put_device(&disk->disk_dev);
kobject_put(&disk->kobj);
}
EXPORT_SYMBOL(alloc_disk);
......
......@@ -27,6 +27,10 @@
#include <linux/completion.h>
#include <linux/slab.h>
/*
* Disk stats
*/
struct disk_stat dkstat;
/*
* For the allocated request tables
......@@ -1432,13 +1436,13 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
return;
kstat.dk_drive[major][index] += new_io;
dkstat.drive[major][index] += new_io;
if (rw == READ) {
kstat.dk_drive_rio[major][index] += new_io;
kstat.dk_drive_rblk[major][index] += nr_sectors;
dkstat.drive_rio[major][index] += new_io;
dkstat.drive_rblk[major][index] += nr_sectors;
} else if (rw == WRITE) {
kstat.dk_drive_wio[major][index] += new_io;
kstat.dk_drive_wblk[major][index] += nr_sectors;
dkstat.drive_wio[major][index] += new_io;
dkstat.drive_wblk[major][index] += nr_sectors;
} else
printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
}
......
......@@ -12,9 +12,14 @@ config VIDEO_DEV
this are available from
<ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
If you are interested in writing a driver for such an audio/video
device or user software interacting with such a driver, please read
the file <file:Documentation/video4linux/API.html>.
This kernel includes support for the new Video for Linux Two API,
(V4L2) as well as the original system. Drivers and applications
need to be rewritten to use V4L2, but drivers for popular cards
and applications for most video capture functions already exist.
Documentation for the original API is included in the file
Documentation/video4linux/API.html. Documentation for V4L2 is
available on the web at http://bytesex.org/v4l/
This driver is also available as a module called videodev.o ( = code
which can be inserted in and removed from the running kernel
......
......@@ -212,5 +212,17 @@ config VIDEO_MEYE
whenever you want). If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>.
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
depends on VIDEO_DEV && PCI && I2C
---help---
This is a video4linux driver for Philips SAA7130/7134 based
TV cards.
This driver is available as a module called saa7134.o ( = code
which can be inserted in and removed from the running kernel
whenever you want). If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>.
endmenu
......@@ -5,13 +5,14 @@
# All of the (potential) objects that export symbols.
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
export-objs := videodev.o bttv-if.o cpia.o video-buf.o
export-objs := videodev.o v4l2-common.o \
bttv-if.o cpia.o video-buf.o
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
tda7432.o tda9875.o tuner.o video-buf.o
......@@ -34,6 +35,7 @@ obj-$(CONFIG_VIDEO_CPIA) += cpia.o
obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
obj-$(CONFIG_VIDEO_MEYE) += meye.o
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ tuner.o tda9887.o
obj-$(CONFIG_TUNER_3036) += tuner-3036.o
include $(TOPDIR)/Rules.make
......@@ -347,6 +347,8 @@
#define BT848_PLL_X (1<<7)
#define BT848_PLL_C (1<<6)
#define BT848_DVSIF 0x0FC
/* Bt878 register */
#define BT878_DEVCTRL 0x40
......
This diff is collapsed.
This diff is collapsed.
......@@ -41,11 +41,13 @@ static struct i2c_adapter bttv_i2c_adap_template;
static struct i2c_client bttv_i2c_client_template;
EXPORT_SYMBOL(bttv_get_cardinfo);
EXPORT_SYMBOL(bttv_get_pcidev);
EXPORT_SYMBOL(bttv_get_id);
EXPORT_SYMBOL(bttv_gpio_enable);
EXPORT_SYMBOL(bttv_read_gpio);
EXPORT_SYMBOL(bttv_write_gpio);
EXPORT_SYMBOL(bttv_get_gpio_queue);
EXPORT_SYMBOL(bttv_i2c_call);
/* ----------------------------------------------------------------------- */
/* Exported functions - for other modules which want to access the */
......@@ -62,6 +64,13 @@ int bttv_get_cardinfo(unsigned int card, int *type, int *cardid)
return 0;
}
struct pci_dev* bttv_get_pcidev(unsigned int card)
{
if (card >= bttv_num)
return NULL;
return bttvs[card].dev;
}
int bttv_get_id(unsigned int card)
{
printk("bttv_get_id is obsolete, use bttv_get_cardinfo instead\n");
......@@ -245,6 +254,13 @@ void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
}
}
void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg)
{
if (card >= bttv_num)
return;
bttv_call_i2c_clients(&bttvs[card], cmd, arg);
}
static struct i2c_algo_bit_data bttv_i2c_algo_template = {
setsda: bttv_bit_setsda,
setscl: bttv_bit_setscl,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment