From 667471386d4068e75a6a55b615701ced61eb6333 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Tue, 29 Apr 2008 01:02:26 -0700 Subject: powerpc: use non-racy method for proc entries creation Use proc_create()/proc_create_data() to make sure that ->proc_fops and ->data be setup before gluing PDE to main tree. Add correct ->owner to proc_fops to fix reading/module unloading race. Signed-off-by: Denis V. Lunev Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Alexey Dobriyan Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/lparcfg.c | 6 ++-- arch/powerpc/kernel/proc_ppc64.c | 5 ++-- arch/powerpc/kernel/rtas-proc.c | 45 +++++++++------------------- arch/powerpc/kernel/rtas_flash.c | 13 +++----- arch/powerpc/platforms/cell/spufs/sched.c | 3 +- arch/powerpc/platforms/cell/spufs/sputrace.c | 3 +- arch/powerpc/platforms/iseries/lpevents.c | 8 ++--- arch/powerpc/platforms/iseries/mf.c | 6 ++-- arch/powerpc/platforms/iseries/proc.c | 8 ++--- arch/powerpc/platforms/iseries/viopath.c | 7 +---- arch/powerpc/platforms/pseries/eeh.c | 10 ++----- arch/powerpc/platforms/pseries/reconfig.c | 7 ++--- arch/powerpc/platforms/pseries/rtasd.c | 7 ++--- 13 files changed, 39 insertions(+), 89 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 1ffacc698ffb..1e656b43ad7f 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -591,10 +591,8 @@ int __init lparcfg_init(void) !firmware_has_feature(FW_FEATURE_ISERIES)) mode |= S_IWUSR; - ent = create_proc_entry("ppc64/lparcfg", mode, NULL); - if (ent) { - ent->proc_fops = &lparcfg_fops; - } else { + ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops); + if (!ent) { printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); return -EIO; } diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index f78dfce1b771..c647ddef40dc 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -68,12 +68,11 @@ static int __init proc_ppc64_init(void) { struct proc_dir_entry *pde; - pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL); + pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL, + &page_map_fops, vdso_data); if (!pde) return 1; - pde->data = vdso_data; pde->size = PAGE_SIZE; - pde->proc_fops = &page_map_fops; return 0; } diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index f2e3bc714d76..f9c6abc84a94 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -255,8 +255,6 @@ static void check_location(struct seq_file *m, const char *c); static int __init proc_rtas_init(void) { - struct proc_dir_entry *entry; - if (!machine_is(pseries)) return -ENODEV; @@ -264,35 +262,20 @@ static int __init proc_rtas_init(void) if (rtas_node == NULL) return -ENODEV; - entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_progress_operations; - - entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_clock_operations; - - entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_poweron_operations; - - entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_sensors_operations; - - entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, - NULL); - if (entry) - entry->proc_fops = &ppc_rtas_tone_freq_operations; - - entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_tone_volume_operations; - - entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_rmo_buf_ops; - + proc_create("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL, + &ppc_rtas_progress_operations); + proc_create("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL, + &ppc_rtas_clock_operations); + proc_create("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL, + &ppc_rtas_poweron_operations); + proc_create("ppc64/rtas/sensors", S_IRUGO, NULL, + &ppc_rtas_sensors_operations); + proc_create("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, NULL, + &ppc_rtas_tone_freq_operations); + proc_create("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL, + &ppc_rtas_tone_volume_operations); + proc_create("ppc64/rtas/rmo_buffer", S_IRUSR, NULL, + &ppc_rtas_rmo_buf_ops); return 0; } diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 627f126d1848..0a5e22b22729 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -704,18 +704,11 @@ static int initialize_flash_pde_data(const char *rtas_call_name, static struct proc_dir_entry *create_flash_pde(const char *filename, const struct file_operations *fops) { - struct proc_dir_entry *ent = NULL; - - ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL); - if (ent != NULL) { - ent->proc_fops = fops; - ent->owner = THIS_MODULE; - } - - return ent; + return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops); } static const struct file_operations rtas_flash_operations = { + .owner = THIS_MODULE, .read = rtas_flash_read, .write = rtas_flash_write, .open = rtas_excl_open, @@ -723,6 +716,7 @@ static const struct file_operations rtas_flash_operations = { }; static const struct file_operations manage_flash_operations = { + .owner = THIS_MODULE, .read = manage_flash_read, .write = manage_flash_write, .open = rtas_excl_open, @@ -730,6 +724,7 @@ static const struct file_operations manage_flash_operations = { }; static const struct file_operations validate_flash_operations = { + .owner = THIS_MODULE, .read = validate_flash_read, .write = validate_flash_write, .open = rtas_excl_open, diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 00528ef84ad2..45dcd2693502 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -1063,10 +1063,9 @@ int __init spu_sched_init(void) mod_timer(&spuloadavg_timer, 0); - entry = create_proc_entry("spu_loadavg", 0, NULL); + entry = proc_create("spu_loadavg", 0, NULL, &spu_loadavg_fops); if (!entry) goto out_stop_kthread; - entry->proc_fops = &spu_loadavg_fops; pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n", SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE); diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c index 79aa773f3c99..aea5286f1245 100644 --- a/arch/powerpc/platforms/cell/spufs/sputrace.c +++ b/arch/powerpc/platforms/cell/spufs/sputrace.c @@ -201,10 +201,9 @@ static int __init sputrace_init(void) if (!sputrace_log) goto out; - entry = create_proc_entry("sputrace", S_IRUSR, NULL); + entry = proc_create("sputrace", S_IRUSR, NULL, &sputrace_fops); if (!entry) goto out_free_log; - entry->proc_fops = &sputrace_fops; for (i = 0; i < ARRAY_SIZE(spu_probes); i++) { struct spu_probe *p = &spu_probes[i]; diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index e5b40e3e0082..b0f8a857ec02 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -330,15 +330,11 @@ static const struct file_operations proc_lpevents_operations = { static int __init proc_lpevents_init(void) { - struct proc_dir_entry *e; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) return 0; - e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL); - if (e) - e->proc_fops = &proc_lpevents_operations; - + proc_create("iSeries/lpevents", S_IFREG|S_IRUGO, NULL, + &proc_lpevents_operations); return 0; } __initcall(proc_lpevents_init); diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index c0f2433bc16e..1dc7295746da 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -1255,11 +1255,11 @@ static int __init mf_proc_init(void) if (i == 3) /* no vmlinux entry for 'D' */ continue; - ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf); + ent = proc_create_data("vmlinux", S_IFREG|S_IWUSR, mf, + &proc_vmlinux_operations, + (void *)(long)i); if (!ent) return 1; - ent->data = (void *)(long)i; - ent->proc_fops = &proc_vmlinux_operations; } ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c index f2cde4180204..91f4c6cd4b99 100644 --- a/arch/powerpc/platforms/iseries/proc.c +++ b/arch/powerpc/platforms/iseries/proc.c @@ -110,15 +110,11 @@ static const struct file_operations proc_titantod_operations = { static int __init iseries_proc_init(void) { - struct proc_dir_entry *e; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) return 0; - e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL); - if (e) - e->proc_fops = &proc_titantod_operations; - + proc_create("iSeries/titanTod", S_IFREG|S_IRUGO, NULL, + &proc_titantod_operations); return 0; } __initcall(iseries_proc_init); diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index df23331eb25c..49ff4dc422b7 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -180,15 +180,10 @@ static const struct file_operations proc_viopath_operations = { static int __init vio_proc_init(void) { - struct proc_dir_entry *e; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) return 0; - e = create_proc_entry("iSeries/config", 0, NULL); - if (e) - e->proc_fops = &proc_viopath_operations; - + proc_create("iSeries/config", 0, NULL, &proc_viopath_operations); return 0; } __initcall(vio_proc_init); diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index a3fd56b186e6..6f544ba4b37f 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1259,14 +1259,8 @@ static const struct file_operations proc_eeh_operations = { static int __init eeh_init_proc(void) { - struct proc_dir_entry *e; - - if (machine_is(pseries)) { - e = create_proc_entry("ppc64/eeh", 0, NULL); - if (e) - e->proc_fops = &proc_eeh_operations; - } - + if (machine_is(pseries)) + proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations); return 0; } __initcall(eeh_init_proc); diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index ac75c10de278..75769aae41d5 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -512,12 +512,9 @@ static int proc_ppc64_create_ofdt(void) if (!machine_is(pseries)) return 0; - ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); - if (ent) { - ent->data = NULL; + ent = proc_create("ppc64/ofdt", S_IWUSR, NULL, &ofdt_fops); + if (ent) ent->size = 0; - ent->proc_fops = &ofdt_fops; - } return 0; } diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index befadd4f9524..7d3e2b0bd4d2 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -468,10 +468,9 @@ static int __init rtas_init(void) return -ENOMEM; } - entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &proc_rtas_log_operations; - else + entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL, + &proc_rtas_log_operations); + if (!entry) printk(KERN_ERR "Failed to create error_log proc entry\n"); if (kernel_thread(rtasd, NULL, CLONE_FS) < 0) -- cgit v1.2.3 From d4d298feeaebb43e0a74e5e2333f1b566c34a37c Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 29 Apr 2008 01:04:08 -0700 Subject: ppc/powerpc: use kbuild.h instead of defining macros in asm-offsets.c Signed-off-by: Christoph Lameter Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/asm-offsets.c | 6 +----- arch/ppc/kernel/asm-offsets.c | 7 ++----- 2 files changed, 3 insertions(+), 10 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 62134845af08..59044e7ed6f4 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -30,6 +30,7 @@ #include #include #endif +#include #include #include @@ -51,11 +52,6 @@ #include #endif -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { DEFINE(THREAD, offsetof(struct task_struct, thread)); diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index a51a17714231..8dcbdd6c2d2c 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -18,6 +18,8 @@ #include #include #include +#include + #include #include #include @@ -26,11 +28,6 @@ #include #include -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { -- cgit v1.2.3 From 3760f736716f74bdc62a4ba5406934338da93eb2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 29 Apr 2008 23:11:40 +0200 Subject: i2c: Convert most new-style drivers to use module aliasing Based on earlier work by Jon Smirl and Jochen Friedrich. Update most new-style i2c drivers to use standard module aliasing instead of the old driver_name/type driver matching scheme. I've left the video drivers apart (except for SoC camera drivers) as they're a bit more diffcult to deal with, they'll have their own patch later. Signed-off-by: Jean Delvare Cc: Jon Smirl Cc: Jochen Friedrich --- arch/arm/mach-at91/board-csb337.c | 3 +- arch/arm/mach-at91/board-dk.c | 3 +- arch/arm/mach-at91/board-eb9200.c | 3 +- arch/arm/mach-iop32x/em7210.c | 3 +- arch/arm/mach-iop32x/glantank.c | 4 +- arch/arm/mach-iop32x/n2100.c | 4 +- arch/arm/mach-ixp4xx/dsmg600-setup.c | 2 +- arch/arm/mach-ixp4xx/nas100d-setup.c | 2 +- arch/arm/mach-ixp4xx/nslu2-setup.c | 2 +- arch/arm/mach-omap1/board-h2.c | 2 - arch/arm/mach-omap1/board-h3.c | 3 +- arch/arm/mach-omap1/board-osk.c | 1 - arch/arm/mach-orion5x/db88f5281-setup.c | 4 +- arch/arm/mach-orion5x/dns323-setup.c | 7 +-- arch/arm/mach-orion5x/kurobox_pro-setup.c | 4 +- arch/arm/mach-orion5x/rd88f5182-setup.c | 4 +- arch/arm/mach-orion5x/ts209-setup.c | 3 +- arch/arm/mach-pxa/pcm990-baseboard.c | 5 +- arch/blackfin/mach-bf533/boards/stamp.c | 3 -- arch/blackfin/mach-bf537/boards/stamp.c | 3 -- arch/blackfin/mach-bf548/boards/ezkit.c | 2 - arch/powerpc/sysdev/fsl_soc.c | 27 +++++------ arch/sh/boards/renesas/migor/setup.c | 3 +- arch/sh/boards/renesas/r7780rp/setup.c | 3 +- drivers/gpio/pca953x.c | 23 ++------- drivers/gpio/pcf857x.c | 33 +++++++------ drivers/hwmon/f75375s.c | 23 +++++---- drivers/i2c/busses/i2c-taos-evm.c | 3 +- drivers/i2c/chips/ds1682.c | 7 +++ drivers/i2c/chips/menelaus.c | 7 +++ drivers/i2c/chips/tps65010.c | 29 +++++------- drivers/i2c/chips/tsl2550.c | 7 +++ drivers/media/video/mt9m001.c | 7 +++ drivers/media/video/mt9v022.c | 7 +++ drivers/rtc/rtc-ds1307.c | 63 ++++++++++--------------- drivers/rtc/rtc-ds1374.c | 7 +++ drivers/rtc/rtc-isl1208.c | 7 +++ drivers/rtc/rtc-m41t80.c | 78 ++++++++----------------------- drivers/rtc/rtc-pcf8563.c | 7 +++ drivers/rtc/rtc-rs5c372.c | 24 +++++----- drivers/rtc/rtc-s35390a.c | 7 +++ drivers/rtc/rtc-x1205.c | 7 +++ include/linux/i2c.h | 12 ++--- 43 files changed, 211 insertions(+), 247 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index 26fea4dcc3a0..81f1ebb4e964 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c @@ -79,8 +79,7 @@ static struct at91_udc_data __initdata csb337_udc_data = { static struct i2c_board_info __initdata csb337_i2c_devices[] = { { - I2C_BOARD_INFO("rtc-ds1307", 0x68), - .type = "ds1307", + I2C_BOARD_INFO("ds1307", 0x68), }, }; diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c index 0a897efeba8e..c1a813c7169b 100644 --- a/arch/arm/mach-at91/board-dk.c +++ b/arch/arm/mach-at91/board-dk.c @@ -132,8 +132,7 @@ static struct i2c_board_info __initdata dk_i2c_devices[] = { I2C_BOARD_INFO("x9429", 0x28), }, { - I2C_BOARD_INFO("at24c", 0x50), - .type = "24c1024", + I2C_BOARD_INFO("24c1024", 0x50), } }; diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c index b7b79bb9d6c4..af1a1d8ecc30 100644 --- a/arch/arm/mach-at91/board-eb9200.c +++ b/arch/arm/mach-at91/board-eb9200.c @@ -93,8 +93,7 @@ static struct at91_mmc_data __initdata eb9200_mmc_data = { static struct i2c_board_info __initdata eb9200_i2c_devices[] = { { - I2C_BOARD_INFO("at24c", 0x50), - .type = "24c512", + I2C_BOARD_INFO("24c512", 0x50), }, }; diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c index c947152f9a3c..4877597c8758 100644 --- a/arch/arm/mach-iop32x/em7210.c +++ b/arch/arm/mach-iop32x/em7210.c @@ -50,8 +50,7 @@ static struct sys_timer em7210_timer = { */ static struct i2c_board_info __initdata em7210_i2c_devices[] = { { - I2C_BOARD_INFO("rtc-rs5c372", 0x32), - .type = "rs5c372a", + I2C_BOARD_INFO("rs5c372a", 0x32), }, }; diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c index d2a7b04f1cb0..d4fca75ce542 100644 --- a/arch/arm/mach-iop32x/glantank.c +++ b/arch/arm/mach-iop32x/glantank.c @@ -176,12 +176,10 @@ static struct f75375s_platform_data glantank_f75375s = { static struct i2c_board_info __initdata glantank_i2c_devices[] = { { - I2C_BOARD_INFO("rtc-rs5c372", 0x32), - .type = "rs5c372a", + I2C_BOARD_INFO("rs5c372a", 0x32), }, { I2C_BOARD_INFO("f75375", 0x2e), - .type = "f75375", .platform_data = &glantank_f75375s, }, }; diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index bc91d6e66bc4..2741063bf361 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c @@ -208,12 +208,10 @@ static struct f75375s_platform_data n2100_f75375s = { static struct i2c_board_info __initdata n2100_i2c_devices[] = { { - I2C_BOARD_INFO("rtc-rs5c372", 0x32), - .type = "rs5c372b", + I2C_BOARD_INFO("rs5c372b", 0x32), }, { I2C_BOARD_INFO("f75375", 0x2e), - .type = "f75375", .platform_data = &n2100_f75375s, }, }; diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c index 8cb07437a807..a51bfa6978b6 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -65,7 +65,7 @@ static struct platform_device dsmg600_i2c_gpio = { static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = { { - I2C_BOARD_INFO("rtc-pcf8563", 0x51), + I2C_BOARD_INFO("pcf8563", 0x51), }, }; diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index 159e1c4f1eda..84b5e62a9c0a 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -54,7 +54,7 @@ static struct platform_device nas100d_flash = { static struct i2c_board_info __initdata nas100d_i2c_board_info [] = { { - I2C_BOARD_INFO("rtc-pcf8563", 0x51), + I2C_BOARD_INFO("pcf8563", 0x51), }, }; diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index d9a182895a0f..a48a6655b887 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -57,7 +57,7 @@ static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = { static struct i2c_board_info __initdata nslu2_i2c_board_info [] = { { - I2C_BOARD_INFO("rtc-x1205", 0x6f), + I2C_BOARD_INFO("x1205", 0x6f), }, }; diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 507987720015..4b444fdaafea 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -351,11 +351,9 @@ static void __init h2_init_smc91x(void) static struct i2c_board_info __initdata h2_i2c_board_info[] = { { I2C_BOARD_INFO("tps65010", 0x48), - .type = "tps65010", .irq = OMAP_GPIO_IRQ(58), }, { I2C_BOARD_INFO("isp1301_omap", 0x2d), - .type = "isp1301_omap", .irq = OMAP_GPIO_IRQ(2), }, }; diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index c3ef1ee5f77b..7fbaa8d648cd 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -473,8 +473,7 @@ static struct omap_board_config_kernel h3_config[] __initdata = { static struct i2c_board_info __initdata h3_i2c_board_info[] = { { - I2C_BOARD_INFO("tps65010", 0x48), - .type = "tps65013", + I2C_BOARD_INFO("tps65013", 0x48), /* .irq = OMAP_GPIO_IRQ(??), */ }, }; diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 4f9baba7d893..a66505f58b15 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -254,7 +254,6 @@ static struct tps65010_board tps_board = { static struct i2c_board_info __initdata osk_i2c_board_info[] = { { I2C_BOARD_INFO("tps65010", 0x48), - .type = "tps65010", .irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)), .platform_data = &tps_board, diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index 872aed372327..ea3141e3e3c0 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -292,9 +292,7 @@ static struct mv643xx_eth_platform_data db88f5281_eth_data = { * RTC DS1339 on I2C bus ****************************************************************************/ static struct i2c_board_info __initdata db88f5281_i2c_rtc = { - .driver_name = "rtc-ds1307", - .type = "ds1339", - .addr = 0x68, + I2C_BOARD_INFO("ds1339", 0x68), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index d67790ef236e..058a525c2ab6 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -220,19 +220,16 @@ static struct platform_device *dns323_plat_devices[] __initdata = { static struct i2c_board_info __initdata dns323_i2c_devices[] = { { I2C_BOARD_INFO("g760a", 0x3e), - .type = "g760a", }, #if 0 /* this entry requires the new-style driver model lm75 driver, * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */ { - I2C_BOARD_INFO("lm75", 0x48), - .type = "g751", + I2C_BOARD_INFO("g751", 0x48), }, #endif { - I2C_BOARD_INFO("rtc-m41t80", 0x68), - .type = "m41t80", + I2C_BOARD_INFO("m41t80", 0x68), } }; diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index 91413455beba..707db4be74a6 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -162,9 +162,7 @@ static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { * RTC 5C372a on I2C bus ****************************************************************************/ static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = { - .driver_name = "rtc-rs5c372", - .type = "rs5c372a", - .addr = 0x32, + I2C_BOARD_INFO("rs5c372a", 0x32), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index 37e8b2dc3ed5..7082fe8f83b1 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -224,9 +224,7 @@ static struct mv643xx_eth_platform_data rd88f5182_eth_data = { * RTC DS1338 on I2C bus ****************************************************************************/ static struct i2c_board_info __initdata rd88f5182_i2c_rtc = { - .driver_name = "rtc-ds1307", - .type = "ds1338", - .addr = 0x68, + I2C_BOARD_INFO("ds1338", 0x68), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index fd43863a86f6..6f93668b0ed5 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -276,8 +276,7 @@ static void __init ts209_find_mac_addr(void) #define TS209_RTC_GPIO 3 static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = { - .driver_name = "rtc-s35390a", - .addr = 0x30, + I2C_BOARD_INFO("s35390a", 0x30), .irq = 0, }; diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index e6be9d0aeccf..49d951db0f3d 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -320,16 +320,13 @@ static struct soc_camera_link iclink[] = { static struct i2c_board_info __initdata pcm990_i2c_devices[] = { { /* Must initialize before the camera(s) */ - I2C_BOARD_INFO("pca953x", 0x41), - .type = "pca9536", + I2C_BOARD_INFO("pca9536", 0x41), .platform_data = &pca9536_data, }, { I2C_BOARD_INFO("mt9v022", 0x48), - .type = "mt9v022", .platform_data = &iclink[0], /* With extender */ }, { I2C_BOARD_INFO("mt9m001", 0x5d), - .type = "mt9m001", .platform_data = &iclink[0], /* With extender */ }, }; diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index fddce32901a2..024f418ae543 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -499,20 +499,17 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { I2C_BOARD_INFO("ad7142_joystick", 0x2C), - .type = "ad7142_joystick", .irq = 39, }, #endif #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { I2C_BOARD_INFO("pcf8574_lcd", 0x22), - .type = "pcf8574_lcd", }, #endif #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE) { I2C_BOARD_INFO("pcf8574_keypad", 0x27), - .type = "pcf8574_keypad", .irq = 39, }, #endif diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 0cec14b1ef5c..d3727b7c2d7d 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -751,20 +751,17 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { I2C_BOARD_INFO("ad7142_joystick", 0x2C), - .type = "ad7142_joystick", .irq = 55, }, #endif #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { I2C_BOARD_INFO("pcf8574_lcd", 0x22), - .type = "pcf8574_lcd", }, #endif #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE) { I2C_BOARD_INFO("pcf8574_keypad", 0x27), - .type = "pcf8574_keypad", .irq = 72, }, #endif diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 231dfbd3bc1f..b00f68ac6bc9 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -641,13 +641,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { I2C_BOARD_INFO("pcf8574_lcd", 0x22), - .type = "pcf8574_lcd", }, #endif #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE) { I2C_BOARD_INFO("pcf8574_keypad", 0x27), - .type = "pcf8574_keypad", .irq = 212, }, #endif diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 7b45670c7af3..324c01b70ddd 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -418,22 +418,21 @@ arch_initcall(gfar_of_init); #include struct i2c_driver_device { char *of_device; - char *i2c_driver; char *i2c_type; }; static struct i2c_driver_device i2c_devices[] __initdata = { - {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",}, - {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",}, - {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",}, - {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",}, - {"dallas,ds1307", "rtc-ds1307", "ds1307",}, - {"dallas,ds1337", "rtc-ds1307", "ds1337",}, - {"dallas,ds1338", "rtc-ds1307", "ds1338",}, - {"dallas,ds1339", "rtc-ds1307", "ds1339",}, - {"dallas,ds1340", "rtc-ds1307", "ds1340",}, - {"stm,m41t00", "rtc-ds1307", "m41t00"}, - {"dallas,ds1374", "rtc-ds1374", "rtc-ds1374",}, + {"ricoh,rs5c372a", "rs5c372a"}, + {"ricoh,rs5c372b", "rs5c372b"}, + {"ricoh,rv5c386", "rv5c386"}, + {"ricoh,rv5c387a", "rv5c387a"}, + {"dallas,ds1307", "ds1307"}, + {"dallas,ds1337", "ds1337"}, + {"dallas,ds1338", "ds1338"}, + {"dallas,ds1339", "ds1339"}, + {"dallas,ds1340", "ds1340"}, + {"stm,m41t00", "m41t00"}, + {"dallas,ds1374", "rtc-ds1374"}, }; static int __init of_find_i2c_driver(struct device_node *node, @@ -444,9 +443,7 @@ static int __init of_find_i2c_driver(struct device_node *node, for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { if (!of_device_is_compatible(node, i2c_devices[i].of_device)) continue; - if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver, - KOBJ_NAME_LEN) >= KOBJ_NAME_LEN || - strlcpy(info->type, i2c_devices[i].i2c_type, + if (strlcpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE) >= I2C_NAME_SIZE) return -ENOMEM; return 0; diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c index 00d52a20d8a5..e7c150d49702 100644 --- a/arch/sh/boards/renesas/migor/setup.c +++ b/arch/sh/boards/renesas/migor/setup.c @@ -199,8 +199,7 @@ static struct platform_device *migor_devices[] __initdata = { static struct i2c_board_info __initdata migor_i2c_devices[] = { { - I2C_BOARD_INFO("rtc-rs5c372", 0x32), - .type = "rs5c372b", + I2C_BOARD_INFO("rs5c372b", 0x32), }, { I2C_BOARD_INFO("migor_ts", 0x51), diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index a5c5e9236501..ac0a96522e45 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -199,8 +199,7 @@ static struct platform_device smbus_device = { static struct i2c_board_info __initdata highlander_i2c_devices[] = { { - I2C_BOARD_INFO("rtc-rs5c372", 0x32), - .type = "r2025sd", + I2C_BOARD_INFO("r2025sd", 0x32), }, }; diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 2670519236e5..5a99e81d2784 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -23,13 +23,7 @@ #define PCA953X_INVERT 2 #define PCA953X_DIRECTION 3 -/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */ -struct pca953x_desc { - char name[I2C_NAME_SIZE]; - unsigned long driver_data; -}; - -static const struct pca953x_desc pca953x_descs[] = { +static const struct i2c_device_id pca953x_id[] = { { "pca9534", 8, }, { "pca9535", 16, }, { "pca9536", 4, }, @@ -37,7 +31,9 @@ static const struct pca953x_desc pca953x_descs[] = { { "pca9538", 8, }, { "pca9539", 16, }, /* REVISIT several pca955x parts should work here too */ + { } }; +MODULE_DEVICE_TABLE(i2c, pca953x_id); struct pca953x_chip { unsigned gpio_start; @@ -193,26 +189,16 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) } static int __devinit pca953x_probe(struct i2c_client *client, - const struct i2c_device_id *did) + const struct i2c_device_id *id) { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; int ret, i; - const struct pca953x_desc *id = NULL; pdata = client->dev.platform_data; if (pdata == NULL) return -ENODEV; - /* this loop vanishes when we get i2c_device_id */ - for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++) - if (!strcmp(pca953x_descs[i].name, client->name)) { - id = pca953x_descs + i; - break; - } - if (!id) - return -ENODEV; - chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -292,6 +278,7 @@ static struct i2c_driver pca953x_driver = { }, .probe = pca953x_probe, .remove = pca953x_remove, + .id_table = pca953x_id, }; static int __init pca953x_init(void) diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index 8856870dd738..aa6cc8b2a2bc 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c @@ -26,6 +26,21 @@ #include +static const struct i2c_device_id pcf857x_id[] = { + { "pcf8574", 8 }, + { "pca8574", 8 }, + { "pca9670", 8 }, + { "pca9672", 8 }, + { "pca9674", 8 }, + { "pcf8575", 16 }, + { "pca8575", 16 }, + { "pca9671", 16 }, + { "pca9673", 16 }, + { "pca9675", 16 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcf857x_id); + /* * The pcf857x, pca857x, and pca967x chips only expose one read and one * write register. Writing a "one" bit (to match the reset state) lets @@ -173,13 +188,8 @@ static int pcf857x_probe(struct i2c_client *client, * * NOTE: we don't distinguish here between *4 and *4a parts. */ - if (strcmp(client->name, "pcf8574") == 0 - || strcmp(client->name, "pca8574") == 0 - || strcmp(client->name, "pca9670") == 0 - || strcmp(client->name, "pca9672") == 0 - || strcmp(client->name, "pca9674") == 0 - ) { - gpio->chip.ngpio = 8; + gpio->chip.ngpio = id->driver_data; + if (gpio->chip.ngpio == 8) { gpio->chip.direction_input = pcf857x_input8; gpio->chip.get = pcf857x_get8; gpio->chip.direction_output = pcf857x_output8; @@ -199,13 +209,7 @@ static int pcf857x_probe(struct i2c_client *client, * * NOTE: we don't distinguish here between '75 and '75c parts. */ - } else if (strcmp(client->name, "pcf8575") == 0 - || strcmp(client->name, "pca8575") == 0 - || strcmp(client->name, "pca9671") == 0 - || strcmp(client->name, "pca9673") == 0 - || strcmp(client->name, "pca9675") == 0 - ) { - gpio->chip.ngpio = 16; + } else if (gpio->chip.ngpio == 16) { gpio->chip.direction_input = pcf857x_input16; gpio->chip.get = pcf857x_get16; gpio->chip.direction_output = pcf857x_output16; @@ -314,6 +318,7 @@ static struct i2c_driver pcf857x_driver = { }, .probe = pcf857x_probe, .remove = pcf857x_remove, + .id_table = pcf857x_id, }; static int __init pcf857x_init(void) diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 1f63bab05522..dc1f30e432ea 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -129,12 +129,20 @@ static struct i2c_driver f75375_legacy_driver = { .detach_client = f75375_detach_client, }; +static const struct i2c_device_id f75375_id[] = { + { "f75373", f75373 }, + { "f75375", f75375 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, f75375_id); + static struct i2c_driver f75375_driver = { .driver = { .name = "f75375", }, .probe = f75375_probe, .remove = f75375_remove, + .id_table = f75375_id, }; static inline int f75375_read8(struct i2c_client *client, u8 reg) @@ -645,15 +653,7 @@ static int f75375_probe(struct i2c_client *client, i2c_set_clientdata(client, data); data->client = client; mutex_init(&data->update_lock); - - if (strcmp(client->name, "f75375") == 0) - data->kind = f75375; - else if (strcmp(client->name, "f75373") == 0) - data->kind = f75373; - else { - dev_err(&client->dev, "Unsupported device: %s\n", client->name); - return -ENODEV; - } + data->kind = id->driver_data; if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) goto exit_free; @@ -714,6 +714,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) u8 version = 0; int err = 0; const char *name = ""; + struct i2c_device_id id; if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) { err = -ENOMEM; @@ -750,7 +751,9 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = i2c_attach_client(client))) goto exit_free; - if ((err = f75375_probe(client, NULL)) < 0) + strlcpy(id.name, name, I2C_NAME_SIZE); + id.driver_data = kind; + if ((err = f75375_probe(client, &id)) < 0) goto exit_detach; return 0; diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index 1b0cfd5472fd..de9db49e54d9 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -51,7 +51,6 @@ struct taos_data { /* TAOS TSL2550 EVM */ static struct i2c_board_info tsl2550_info = { I2C_BOARD_INFO("tsl2550", 0x39), - .type = "tsl2550", }; /* Instantiate i2c devices based on the adapter name */ @@ -59,7 +58,7 @@ static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter) { if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) { dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n", - tsl2550_info.driver_name, tsl2550_info.addr); + tsl2550_info.type, tsl2550_info.addr); return i2c_new_device(adapter, &tsl2550_info); } diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c index 3070821030e4..23be4d42cb02 100644 --- a/drivers/i2c/chips/ds1682.c +++ b/drivers/i2c/chips/ds1682.c @@ -235,12 +235,19 @@ static int ds1682_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id ds1682_id[] = { + { "ds1682", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds1682_id); + static struct i2c_driver ds1682_driver = { .driver = { .name = "ds1682", }, .probe = ds1682_probe, .remove = ds1682_remove, + .id_table = ds1682_id, }; static int __init ds1682_init(void) diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c index 3b8ba7e75843..b36db1797c11 100644 --- a/drivers/i2c/chips/menelaus.c +++ b/drivers/i2c/chips/menelaus.c @@ -1243,12 +1243,19 @@ static int __exit menelaus_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id menelaus_id[] = { + { "menelaus", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, menelaus_id); + static struct i2c_driver menelaus_i2c_driver = { .driver = { .name = DRIVER_NAME, }, .probe = menelaus_probe, .remove = __exit_p(menelaus_remove), + .id_table = menelaus_id, }; static int __init menelaus_init(void) diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 6ab3619a49de..85949685191b 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -64,7 +64,6 @@ static struct i2c_driver tps65010_driver; * as part of board setup by a bootloader. */ enum tps_model { - TPS_UNKNOWN = 0, TPS65010, TPS65011, TPS65012, @@ -554,20 +553,7 @@ static int tps65010_probe(struct i2c_client *client, mutex_init(&tps->lock); INIT_DELAYED_WORK(&tps->work, tps65010_work); tps->client = client; - - if (strcmp(client->name, "tps65010") == 0) - tps->model = TPS65010; - else if (strcmp(client->name, "tps65011") == 0) - tps->model = TPS65011; - else if (strcmp(client->name, "tps65012") == 0) - tps->model = TPS65012; - else if (strcmp(client->name, "tps65013") == 0) - tps->model = TPS65013; - else { - dev_warn(&client->dev, "unknown chip '%s'\n", client->name); - status = -ENODEV; - goto fail1; - } + tps->model = id->driver_data; /* the IRQ is active low, but many gpio lines can't support that * so this driver uses falling-edge triggers instead. @@ -596,9 +582,6 @@ static int tps65010_probe(struct i2c_client *client, case TPS65012: tps->por = 1; break; - case TPS_UNKNOWN: - printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME); - break; /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */ } tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG); @@ -685,12 +668,22 @@ fail1: return status; } +static const struct i2c_device_id tps65010_id[] = { + { "tps65010", TPS65010 }, + { "tps65011", TPS65011 }, + { "tps65012", TPS65012 }, + { "tps65013", TPS65013 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tps65010_id); + static struct i2c_driver tps65010_driver = { .driver = { .name = "tps65010", }, .probe = tps65010_probe, .remove = __exit_p(tps65010_remove), + .id_table = tps65010_id, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c index 59c2c662cc45..1a9cc135219f 100644 --- a/drivers/i2c/chips/tsl2550.c +++ b/drivers/i2c/chips/tsl2550.c @@ -452,6 +452,12 @@ static int tsl2550_resume(struct i2c_client *client) #endif /* CONFIG_PM */ +static const struct i2c_device_id tsl2550_id[] = { + { "tsl2550", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tsl2550_id); + static struct i2c_driver tsl2550_driver = { .driver = { .name = TSL2550_DRV_NAME, @@ -461,6 +467,7 @@ static struct i2c_driver tsl2550_driver = { .resume = tsl2550_resume, .probe = tsl2550_probe, .remove = __devexit_p(tsl2550_remove), + .id_table = tsl2550_id, }; static int __init tsl2550_init(void) diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 26cb27604e04..ba09826ddf48 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -697,12 +697,19 @@ static int mt9m001_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id mt9m001_id[] = { + { "mt9m001", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9m001_id); + static struct i2c_driver mt9m001_i2c_driver = { .driver = { .name = "mt9m001", }, .probe = mt9m001_probe, .remove = mt9m001_remove, + .id_table = mt9m001_id, }; static int __init mt9m001_mod_init(void) diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 7b1dd7ede9d0..7b223691ce96 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -819,12 +819,19 @@ static int mt9v022_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id mt9v022_id[] = { + { "mt9v022", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9v022_id); + static struct i2c_driver mt9v022_i2c_driver = { .driver = { .name = "mt9v022", }, .probe = mt9v022_probe, .remove = mt9v022_remove, + .id_table = mt9v022_id, }; static int __init mt9v022_mod_init(void) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 67ba8ae3217c..bbf97e65202a 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -99,45 +99,38 @@ struct ds1307 { }; struct chip_desc { - char name[9]; unsigned nvram56:1; unsigned alarm:1; - enum ds_type type; }; -static const struct chip_desc chips[] = { { - .name = "ds1307", - .type = ds_1307, +static const struct chip_desc chips[] = { +[ds_1307] = { .nvram56 = 1, -}, { - .name = "ds1337", - .type = ds_1337, +}, +[ds_1337] = { .alarm = 1, -}, { - .name = "ds1338", - .type = ds_1338, +}, +[ds_1338] = { .nvram56 = 1, -}, { - .name = "ds1339", - .type = ds_1339, +}, +[ds_1339] = { .alarm = 1, -}, { - .name = "ds1340", - .type = ds_1340, -}, { - .name = "m41t00", - .type = m41t00, +}, +[ds_1340] = { +}, +[m41t00] = { }, }; -static inline const struct chip_desc *find_chip(const char *s) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(chips); i++) - if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0) - return &chips[i]; - return NULL; -} +static const struct i2c_device_id ds1307_id[] = { + { "ds1307", ds_1307 }, + { "ds1337", ds_1337 }, + { "ds1338", ds_1338 }, + { "ds1339", ds_1339 }, + { "ds1340", ds_1340 }, + { "m41t00", m41t00 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds1307_id); static int ds1307_get_time(struct device *dev, struct rtc_time *t) { @@ -332,16 +325,9 @@ static int __devinit ds1307_probe(struct i2c_client *client, struct ds1307 *ds1307; int err = -ENODEV; int tmp; - const struct chip_desc *chip; + const struct chip_desc *chip = &chips[id->driver_data]; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - chip = find_chip(client->name); - if (!chip) { - dev_err(&client->dev, "unknown chip type '%s'\n", - client->name); - return -ENODEV; - } - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; @@ -362,7 +348,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, ds1307->msg[1].len = sizeof(ds1307->regs); ds1307->msg[1].buf = ds1307->regs; - ds1307->type = chip->type; + ds1307->type = id->driver_data; switch (ds1307->type) { case ds_1337: @@ -551,6 +537,7 @@ static struct i2c_driver ds1307_driver = { }, .probe = ds1307_probe, .remove = __devexit_p(ds1307_remove), + .id_table = ds1307_id, }; static int __init ds1307_init(void) diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 104dcfd5d9a8..fa2d2f8b3f4d 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -41,6 +41,12 @@ #define DS1374_REG_SR_AF 0x01 /* Alarm Flag */ #define DS1374_REG_TCR 0x09 /* Trickle Charge */ +static const struct i2c_device_id ds1374_id[] = { + { "rtc-ds1374", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds1374_id); + struct ds1374 { struct i2c_client *client; struct rtc_device *rtc; @@ -430,6 +436,7 @@ static struct i2c_driver ds1374_driver = { }, .probe = ds1374_probe, .remove = __devexit_p(ds1374_remove), + .id_table = ds1374_id, }; static int __init ds1374_init(void) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index d75d8faeead0..fbb90b1e4098 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -545,12 +545,19 @@ isl1208_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id isl1208_id[] = { + { "isl1208", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isl1208_id); + static struct i2c_driver isl1208_driver = { .driver = { .name = "rtc-isl1208", }, .probe = isl1208_probe, .remove = isl1208_remove, + .id_table = isl1208_id, }; static int __init diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 2ee0d070095a..316bfaa80872 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -60,48 +60,21 @@ #define DRV_VERSION "0.05" -struct m41t80_chip_info { - const char *name; - u8 features; -}; - -static const struct m41t80_chip_info m41t80_chip_info_tbl[] = { - { - .name = "m41t80", - .features = 0, - }, - { - .name = "m41t81", - .features = M41T80_FEATURE_HT, - }, - { - .name = "m41t81s", - .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL, - }, - { - .name = "m41t82", - .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL, - }, - { - .name = "m41t83", - .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL, - }, - { - .name = "m41st84", - .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL, - }, - { - .name = "m41st85", - .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL, - }, - { - .name = "m41st87", - .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL, - }, +static const struct i2c_device_id m41t80_id[] = { + { "m41t80", 0 }, + { "m41t81", M41T80_FEATURE_HT }, + { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, + { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, + { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, + { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, + { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, + { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, + { } }; +MODULE_DEVICE_TABLE(i2c, m41t80_id); struct m41t80_data { - const struct m41t80_chip_info *chip; + u8 features; struct rtc_device *rtc; }; @@ -208,7 +181,7 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq) struct m41t80_data *clientdata = i2c_get_clientdata(client); u8 reg; - if (clientdata->chip->features & M41T80_FEATURE_BL) { + if (clientdata->features & M41T80_FEATURE_BL) { reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); seq_printf(seq, "battery\t\t: %s\n", (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok"); @@ -759,10 +732,9 @@ static struct notifier_block wdt_notifier = { static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int i, rc = 0; + int rc = 0; struct rtc_device *rtc = NULL; struct rtc_time tm; - const struct m41t80_chip_info *chip; struct m41t80_data *clientdata = NULL; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C @@ -774,19 +746,6 @@ static int m41t80_probe(struct i2c_client *client, dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - chip = NULL; - for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) { - if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) { - chip = &m41t80_chip_info_tbl[i]; - break; - } - } - if (!chip) { - dev_err(&client->dev, "%s is not supported\n", client->name); - rc = -ENODEV; - goto exit; - } - clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL); if (!clientdata) { rc = -ENOMEM; @@ -802,7 +761,7 @@ static int m41t80_probe(struct i2c_client *client, } clientdata->rtc = rtc; - clientdata->chip = chip; + clientdata->features = id->driver_data; i2c_set_clientdata(client, clientdata); /* Make sure HT (Halt Update) bit is cleared */ @@ -811,7 +770,7 @@ static int m41t80_probe(struct i2c_client *client, goto ht_err; if (rc & M41T80_ALHOUR_HT) { - if (chip->features & M41T80_FEATURE_HT) { + if (clientdata->features & M41T80_FEATURE_HT) { m41t80_get_datetime(client, &tm); dev_info(&client->dev, "HT bit was set!\n"); dev_info(&client->dev, @@ -843,7 +802,7 @@ static int m41t80_probe(struct i2c_client *client, goto exit; #ifdef CONFIG_RTC_DRV_M41T80_WDT - if (chip->features & M41T80_FEATURE_HT) { + if (clientdata->features & M41T80_FEATURE_HT) { rc = misc_register(&wdt_dev); if (rc) goto exit; @@ -879,7 +838,7 @@ static int m41t80_remove(struct i2c_client *client) struct rtc_device *rtc = clientdata->rtc; #ifdef CONFIG_RTC_DRV_M41T80_WDT - if (clientdata->chip->features & M41T80_FEATURE_HT) { + if (clientdata->features & M41T80_FEATURE_HT) { misc_deregister(&wdt_dev); unregister_reboot_notifier(&wdt_notifier); } @@ -897,6 +856,7 @@ static struct i2c_driver m41t80_driver = { }, .probe = m41t80_probe, .remove = m41t80_remove, + .id_table = m41t80_id, }; static int __init m41t80_rtc_init(void) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 7b3c31db0fc0..0fc4c3630780 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -300,12 +300,19 @@ static int pcf8563_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id pcf8563_id[] = { + { "pcf8563", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcf8563_id); + static struct i2c_driver pcf8563_driver = { .driver = { .name = "rtc-pcf8563", }, .probe = pcf8563_probe, .remove = pcf8563_remove, + .id_table = pcf8563_id, }; static int __init pcf8563_init(void) diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 47db289bb0a3..56caf6b2c3e5 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -69,6 +69,15 @@ enum rtc_type { rtc_rv5c387a, }; +static const struct i2c_device_id rs5c372_id[] = { + { "rs5c372a", rtc_rs5c372a }, + { "rs5c372b", rtc_rs5c372b }, + { "rv5c386", rtc_rv5c386 }, + { "rv5c387a", rtc_rv5c387a }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rs5c372_id); + /* REVISIT: this assumes that: * - we're in the 21st century, so it's safe to ignore the century * bit for rv5c38[67] (REG_MONTH bit 7); @@ -515,6 +524,7 @@ static int rs5c372_probe(struct i2c_client *client, rs5c372->client = client; i2c_set_clientdata(client, rs5c372); + rs5c372->type = id->driver_data; /* we read registers 0x0f then 0x00-0x0f; skip the first one */ rs5c372->regs = &rs5c372->buf[1]; @@ -523,19 +533,6 @@ static int rs5c372_probe(struct i2c_client *client, if (err < 0) goto exit_kfree; - if (strcmp(client->name, "rs5c372a") == 0) - rs5c372->type = rtc_rs5c372a; - else if (strcmp(client->name, "rs5c372b") == 0) - rs5c372->type = rtc_rs5c372b; - else if (strcmp(client->name, "rv5c386") == 0) - rs5c372->type = rtc_rv5c386; - else if (strcmp(client->name, "rv5c387a") == 0) - rs5c372->type = rtc_rv5c387a; - else { - rs5c372->type = rtc_rs5c372b; - dev_warn(&client->dev, "assuming rs5c372b\n"); - } - /* clock may be set for am/pm or 24 hr time */ switch (rs5c372->type) { case rtc_rs5c372a: @@ -652,6 +649,7 @@ static struct i2c_driver rs5c372_driver = { }, .probe = rs5c372_probe, .remove = rs5c372_remove, + .id_table = rs5c372_id, }; static __init int rs5c372_init(void) diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index ab0c6d221404..29f47bacfc77 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -34,6 +34,12 @@ #define S35390A_FLAG_RESET 0x80 #define S35390A_FLAG_TEST 0x01 +static const struct i2c_device_id s35390a_id[] = { + { "s35390a", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, s35390a_id); + struct s35390a { struct i2c_client *client[8]; struct rtc_device *rtc; @@ -297,6 +303,7 @@ static struct i2c_driver s35390a_driver = { }, .probe = s35390a_probe, .remove = s35390a_remove, + .id_table = s35390a_id, }; static int __init s35390a_rtc_init(void) diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index b792ad4dcaa9..eaf55945f21b 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -553,12 +553,19 @@ static int x1205_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id x1205_id[] = { + { "x1205", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, x1205_id); + static struct i2c_driver x1205_driver = { .driver = { .name = "rtc-x1205", }, .probe = x1205_probe, .remove = x1205_remove, + .id_table = x1205_id, }; static int __init x1205_init(void) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 89cb34d5b0ba..cb63da5c2139 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -229,17 +229,17 @@ struct i2c_board_info { }; /** - * I2C_BOARD_INFO - macro used to list an i2c device and its driver - * @driver: identifies the driver to use with the device + * I2C_BOARD_INFO - macro used to list an i2c device and its address + * @dev_type: identifies the device type * @dev_addr: the device's address on the bus. * * This macro initializes essential fields of a struct i2c_board_info, * declaring what has been provided on a particular board. Optional - * fields (such as the chip type, its associated irq, or device-specific - * platform_data) are provided using conventional syntax. + * fields (such as associated irq, or device-specific platform_data) + * are provided using conventional syntax. */ -#define I2C_BOARD_INFO(driver,dev_addr) \ - .driver_name = (driver), .addr = (dev_addr) +#define I2C_BOARD_INFO(dev_type,dev_addr) \ + .type = (dev_type), .addr = (dev_addr) /* Add-on boards should register/unregister their devices; e.g. a board -- cgit v1.2.3 From f7511d5f66f01fc451747b24e79f3ada7a3af9af Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 30 Apr 2008 00:54:51 -0700 Subject: Basic braille screen reader support This adds a minimalistic braille screen reader support. This is meant to be used by blind people e.g. on boot failures or when / cannot be mounted etc and thus the userland screen readers can not work. [akpm@linux-foundation.org: fix exports] Signed-off-by: Samuel Thibault Cc: Jiri Kosina Cc: Dmitry Torokhov Acked-by: Alan Cox Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/braille-console.txt | 34 ++ Documentation/kernel-parameters.txt | 5 + arch/powerpc/kernel/ppc_ksyms.c | 3 - arch/ppc/kernel/ppc_ksyms.c | 3 - drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/accessibility/Kconfig | 23 ++ drivers/accessibility/Makefile | 1 + drivers/accessibility/braille/Makefile | 1 + drivers/accessibility/braille/braille_console.c | 397 ++++++++++++++++++++++++ drivers/char/consolemap.c | 1 + drivers/char/keyboard.c | 2 + drivers/char/vt.c | 1 + include/linux/console.h | 4 + kernel/printk.c | 90 ++++-- 15 files changed, 538 insertions(+), 30 deletions(-) create mode 100644 Documentation/braille-console.txt create mode 100644 drivers/accessibility/Kconfig create mode 100644 drivers/accessibility/Makefile create mode 100644 drivers/accessibility/braille/Makefile create mode 100644 drivers/accessibility/braille/braille_console.c (limited to 'arch/powerpc') diff --git a/Documentation/braille-console.txt b/Documentation/braille-console.txt new file mode 100644 index 000000000000..000b0fbdc105 --- /dev/null +++ b/Documentation/braille-console.txt @@ -0,0 +1,34 @@ + Linux Braille Console + +To get early boot messages on a braille device (before userspace screen +readers can start), you first need to compile the support for the usual serial +console (see serial-console.txt), and for braille device (in Device Drivers - +Accessibility). + +Then you need to specify a console=brl, option on the kernel command line, the +format is: + + console=brl,serial_options... + +where serial_options... are the same as described in serial-console.txt + +So for instance you can use console=brl,ttyS0 if the braille device is connected +to the first serial port, and console=brl,ttyS0,115200 to override the baud rate +to 115200, etc. + +By default, the braille device will just show the last kernel message (console +mode). To review previous messages, press the Insert key to switch to the VT +review mode. In review mode, the arrow keys permit to browse in the VT content, +page up/down keys go at the top/bottom of the screen, and the home key goes back +to the cursor, hence providing very basic screen reviewing facility. + +Sound feedback can be obtained by adding the braille_console.sound=1 kernel +parameter. + +For simplicity, only one braille console can be enabled, other uses of +console=brl,... will be discarded. Also note that it does not interfere with +the console selection mecanism described in serial-console.txt + +For now, only the VisioBraille device is supported. + +Samuel Thibault diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 3ce193f86565..0ba0861b5d18 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -496,6 +496,11 @@ and is between 256 and 4096 characters. It is defined in the file switching to the matching ttyS device later. The options are the same as for ttyS, above. + If the device connected to the port is not a TTY but a braille + device, prepend "brl," before the device type, for instance + console=brl,ttyS0 + For now, only VisioBraille is supported. + earlycon= [KNL] Output early console device and options. uart[8250],io,[,options] uart[8250],mmio,[,options] diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 09fcb50c45ae..cf6b5a7d8b3f 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -133,9 +133,6 @@ EXPORT_SYMBOL(adb_try_handler_change); EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_VT -EXPORT_SYMBOL(kd_mksound); -#endif EXPORT_SYMBOL(to_tm); #ifdef CONFIG_PPC32 diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index d9036ef0b658..16ac11ca7ba0 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -183,9 +183,6 @@ EXPORT_SYMBOL(cuda_poll); #if defined(CONFIG_BOOTX_TEXT) EXPORT_SYMBOL(btext_update_display); #endif -#ifdef CONFIG_VT -EXPORT_SYMBOL(kd_mksound); -#endif EXPORT_SYMBOL(to_tm); EXPORT_SYMBOL(pm_power_off); diff --git a/drivers/Kconfig b/drivers/Kconfig index 80f0ec91e2cf..59f33fa6af3e 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -84,6 +84,8 @@ source "drivers/memstick/Kconfig" source "drivers/leds/Kconfig" +source "drivers/accessibility/Kconfig" + source "drivers/infiniband/Kconfig" source "drivers/edac/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index e5e394a7e6c0..f65deda72d61 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ +obj-$(CONFIG_ACCESSIBILITY) += accessibility/ obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_EDAC) += edac/ obj-$(CONFIG_MCA) += mca/ diff --git a/drivers/accessibility/Kconfig b/drivers/accessibility/Kconfig new file mode 100644 index 000000000000..1264c4b98094 --- /dev/null +++ b/drivers/accessibility/Kconfig @@ -0,0 +1,23 @@ +menuconfig ACCESSIBILITY + bool "Accessibility support" + ---help--- + Enable a submenu where accessibility items may be enabled. + + If unsure, say N. + +if ACCESSIBILITY +config A11Y_BRAILLE_CONSOLE + bool "Console on braille device" + depends on VT + depends on SERIAL_CORE_CONSOLE + ---help--- + Enables console output on a braille device connected to a 8250 + serial port. For now only the VisioBraille device is supported. + + To actually enable it, you need to pass option + console=brl,ttyS0 + to the kernel. Options are the same as for serial console. + + If unsure, say N. + +endif # ACCESSIBILITY diff --git a/drivers/accessibility/Makefile b/drivers/accessibility/Makefile new file mode 100644 index 000000000000..72b01a46546f --- /dev/null +++ b/drivers/accessibility/Makefile @@ -0,0 +1 @@ +obj-y += braille/ diff --git a/drivers/accessibility/braille/Makefile b/drivers/accessibility/braille/Makefile new file mode 100644 index 000000000000..2e9f16c91347 --- /dev/null +++ b/drivers/accessibility/braille/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille_console.o diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c new file mode 100644 index 000000000000..0a5f6b2114c5 --- /dev/null +++ b/drivers/accessibility/braille/braille_console.c @@ -0,0 +1,397 @@ +/* + * Minimalistic braille device kernel support. + * + * By default, shows console messages on the braille device. + * Pressing Insert switches to VC browsing. + * + * Copyright (C) Samuel Thibault + * + * This program is free software ; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation ; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY ; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the program ; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +MODULE_AUTHOR("samuel.thibault@ens-lyon.org"); +MODULE_DESCRIPTION("braille device"); +MODULE_LICENSE("GPL"); + +/* + * Braille device support part. + */ + +/* Emit various sounds */ +static int sound; +module_param(sound, bool, 0); +MODULE_PARM_DESC(sound, "emit sounds"); + +static void beep(unsigned int freq) +{ + if (sound) + kd_mksound(freq, HZ/10); +} + +/* mini console */ +#define WIDTH 40 +#define BRAILLE_KEY KEY_INSERT +static u16 console_buf[WIDTH]; +static int console_cursor; + +/* mini view of VC */ +static int vc_x, vc_y, lastvc_x, lastvc_y; + +/* show console ? (or show VC) */ +static int console_show = 1; +/* pending newline ? */ +static int console_newline = 1; +static int lastVC = -1; + +static struct console *braille_co; + +/* Very VisioBraille-specific */ +static void braille_write(u16 *buf) +{ + static u16 lastwrite[WIDTH]; + unsigned char data[1 + 1 + 2*WIDTH + 2 + 1], csum = 0, *c; + u16 out; + int i; + + if (!braille_co) + return; + + if (!memcmp(lastwrite, buf, WIDTH * sizeof(*buf))) + return; + memcpy(lastwrite, buf, WIDTH * sizeof(*buf)); + +#define SOH 1 +#define STX 2 +#define ETX 2 +#define EOT 4 +#define ENQ 5 + data[0] = STX; + data[1] = '>'; + csum ^= '>'; + c = &data[2]; + for (i = 0; i < WIDTH; i++) { + out = buf[i]; + if (out >= 0x100) + out = '?'; + else if (out == 0x00) + out = ' '; + csum ^= out; + if (out <= 0x05) { + *c++ = SOH; + out |= 0x40; + } + *c++ = out; + } + + if (csum <= 0x05) { + *c++ = SOH; + csum |= 0x40; + } + *c++ = csum; + *c++ = ETX; + + braille_co->write(braille_co, data, c - data); +} + +/* Follow the VC cursor*/ +static void vc_follow_cursor(struct vc_data *vc) +{ + vc_x = vc->vc_x - (vc->vc_x % WIDTH); + vc_y = vc->vc_y; + lastvc_x = vc->vc_x; + lastvc_y = vc->vc_y; +} + +/* Maybe the VC cursor moved, if so follow it */ +static void vc_maybe_cursor_moved(struct vc_data *vc) +{ + if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y) + vc_follow_cursor(vc); +} + +/* Show portion of VC at vc_x, vc_y */ +static void vc_refresh(struct vc_data *vc) +{ + u16 buf[WIDTH]; + int i; + + for (i = 0; i < WIDTH; i++) { + u16 glyph = screen_glyph(vc, + 2 * (vc_x + i) + vc_y * vc->vc_size_row); + buf[i] = inverse_translate(vc, glyph, 1); + } + braille_write(buf); +} + +/* + * Link to keyboard + */ + +static int keyboard_notifier_call(struct notifier_block *blk, + unsigned long code, void *_param) +{ + struct keyboard_notifier_param *param = _param; + struct vc_data *vc = param->vc; + int ret = NOTIFY_OK; + + if (!param->down) + return ret; + + switch (code) { + case KBD_KEYCODE: + if (console_show) { + if (param->value == BRAILLE_KEY) { + console_show = 0; + beep(880); + vc_maybe_cursor_moved(vc); + vc_refresh(vc); + ret = NOTIFY_STOP; + } + } else { + ret = NOTIFY_STOP; + switch (param->value) { + case KEY_INSERT: + beep(440); + console_show = 1; + lastVC = -1; + braille_write(console_buf); + break; + case KEY_LEFT: + if (vc_x > 0) { + vc_x -= WIDTH; + if (vc_x < 0) + vc_x = 0; + } else if (vc_y >= 1) { + beep(880); + vc_y--; + vc_x = vc->vc_cols-WIDTH; + } else + beep(220); + break; + case KEY_RIGHT: + if (vc_x + WIDTH < vc->vc_cols) { + vc_x += WIDTH; + } else if (vc_y + 1 < vc->vc_rows) { + beep(880); + vc_y++; + vc_x = 0; + } else + beep(220); + break; + case KEY_DOWN: + if (vc_y + 1 < vc->vc_rows) + vc_y++; + else + beep(220); + break; + case KEY_UP: + if (vc_y >= 1) + vc_y--; + else + beep(220); + break; + case KEY_HOME: + vc_follow_cursor(vc); + break; + case KEY_PAGEUP: + vc_x = 0; + vc_y = 0; + break; + case KEY_PAGEDOWN: + vc_x = 0; + vc_y = vc->vc_rows-1; + break; + default: + ret = NOTIFY_OK; + break; + } + if (ret == NOTIFY_STOP) + vc_refresh(vc); + } + break; + case KBD_POST_KEYSYM: + { + unsigned char type = KTYP(param->value) - 0xf0; + if (type == KT_SPEC) { + unsigned char val = KVAL(param->value); + int on_off = -1; + + switch (val) { + case KVAL(K_CAPS): + on_off = vc_kbd_led(kbd_table + fg_console, + VC_CAPSLOCK); + break; + case KVAL(K_NUM): + on_off = vc_kbd_led(kbd_table + fg_console, + VC_NUMLOCK); + break; + case KVAL(K_HOLD): + on_off = vc_kbd_led(kbd_table + fg_console, + VC_SCROLLOCK); + break; + } + if (on_off == 1) + beep(880); + else if (on_off == 0) + beep(440); + } + } + case KBD_UNBOUND_KEYCODE: + case KBD_UNICODE: + case KBD_KEYSYM: + /* Unused */ + break; + } + return ret; +} + +static struct notifier_block keyboard_notifier_block = { + .notifier_call = keyboard_notifier_call, +}; + +static int vt_notifier_call(struct notifier_block *blk, + unsigned long code, void *_param) +{ + struct vt_notifier_param *param = _param; + struct vc_data *vc = param->vc; + switch (code) { + case VT_ALLOCATE: + break; + case VT_DEALLOCATE: + break; + case VT_WRITE: + { + unsigned char c = param->c; + if (vc->vc_num != fg_console) + break; + switch (c) { + case '\b': + case 127: + if (console_cursor > 0) { + console_cursor--; + console_buf[console_cursor] = ' '; + } + break; + case '\n': + case '\v': + case '\f': + case '\r': + console_newline = 1; + break; + case '\t': + c = ' '; + /* Fallthrough */ + default: + if (c < 32) + /* Ignore other control sequences */ + break; + if (console_newline) { + memset(console_buf, 0, sizeof(console_buf)); + console_cursor = 0; + console_newline = 0; + } + if (console_cursor == WIDTH) + memmove(console_buf, &console_buf[1], + (WIDTH-1) * sizeof(*console_buf)); + else + console_cursor++; + console_buf[console_cursor-1] = c; + break; + } + if (console_show) + braille_write(console_buf); + else { + vc_maybe_cursor_moved(vc); + vc_refresh(vc); + } + break; + } + case VT_UPDATE: + /* Maybe a VT switch, flush */ + if (console_show) { + if (vc->vc_num != lastVC) { + lastVC = vc->vc_num; + memset(console_buf, 0, sizeof(console_buf)); + console_cursor = 0; + braille_write(console_buf); + } + } else { + vc_maybe_cursor_moved(vc); + vc_refresh(vc); + } + break; + } + return NOTIFY_OK; +} + +static struct notifier_block vt_notifier_block = { + .notifier_call = vt_notifier_call, +}; + +/* + * Called from printk.c when console=brl is given + */ + +int braille_register_console(struct console *console, int index, + char *console_options, char *braille_options) +{ + int ret; + if (!console_options) + /* Only support VisioBraille for now */ + console_options = "57600o8"; + if (braille_co) + return -ENODEV; + if (console->setup) { + ret = console->setup(console, console_options); + if (ret != 0) + return ret; + } + console->flags |= CON_ENABLED; + console->index = index; + braille_co = console; + return 0; +} + +int braille_unregister_console(struct console *console) +{ + if (braille_co != console) + return -EINVAL; + braille_co = NULL; + return 0; +} + +static int __init braille_init(void) +{ + register_keyboard_notifier(&keyboard_notifier_block); + register_vt_notifier(&vt_notifier_block); + return 0; +} + +console_initcall(braille_init); diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index 6b104e45a322..4246b8e36cb3 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -277,6 +277,7 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode) return p->inverse_translations[m][glyph]; } } +EXPORT_SYMBOL_GPL(inverse_translate); static void update_user_maps(void) { diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index d1c50b3302e5..7f7e798c1384 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -110,6 +110,7 @@ const int max_vals[] = { const int NR_TYPES = ARRAY_SIZE(max_vals); struct kbd_struct kbd_table[MAX_NR_CONSOLES]; +EXPORT_SYMBOL_GPL(kbd_table); static struct kbd_struct *kbd = kbd_table; struct vt_spawn_console vt_spawn_con = { @@ -260,6 +261,7 @@ void kd_mksound(unsigned int hz, unsigned int ticks) } else kd_nosound(0); } +EXPORT_SYMBOL(kd_mksound); /* * Setting the keyboard rate. diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 71cf203d282d..e458b08139af 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -4004,6 +4004,7 @@ u16 screen_glyph(struct vc_data *vc, int offset) c |= 0x100; return c; } +EXPORT_SYMBOL_GPL(screen_glyph); /* used by vcs - note the word offset */ unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed) diff --git a/include/linux/console.h b/include/linux/console.h index a5f88a6a259d..a4f27fbdf549 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -91,6 +91,7 @@ void give_up_console(const struct consw *sw); #define CON_ENABLED (4) #define CON_BOOT (8) #define CON_ANYTIME (16) /* Safe to call when cpu is offline */ +#define CON_BRL (32) /* Used for a braille device */ struct console { char name[16]; @@ -121,6 +122,9 @@ extern struct tty_driver *console_device(int *); extern void console_stop(struct console *); extern void console_start(struct console *); extern int is_console_locked(void); +extern int braille_register_console(struct console *, int index, + char *console_options, char *braille_options); +extern int braille_unregister_console(struct console *); extern int console_suspend_enabled; diff --git a/kernel/printk.c b/kernel/printk.c index 0d232589a923..e61346faf6a5 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -111,6 +111,9 @@ struct console_cmdline char name[8]; /* Name of the driver */ int index; /* Minor dev. to use */ char *options; /* Options for the driver */ +#ifdef CONFIG_A11Y_BRAILLE_CONSOLE + char *brl_options; /* Options for braille driver */ +#endif }; #define MAX_CMDLINECONSOLES 8 @@ -808,15 +811,60 @@ static void call_console_drivers(unsigned start, unsigned end) #endif +static int __add_preferred_console(char *name, int idx, char *options, + char *brl_options) +{ + struct console_cmdline *c; + int i; + + /* + * See if this tty is not yet registered, and + * if we have a slot free. + */ + for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) + if (strcmp(console_cmdline[i].name, name) == 0 && + console_cmdline[i].index == idx) { + if (!brl_options) + selected_console = i; + return 0; + } + if (i == MAX_CMDLINECONSOLES) + return -E2BIG; + if (!brl_options) + selected_console = i; + c = &console_cmdline[i]; + strlcpy(c->name, name, sizeof(c->name)); + c->options = options; +#ifdef CONFIG_A11Y_BRAILLE_CONSOLE + c->brl_options = brl_options; +#endif + c->index = idx; + return 0; +} /* * Set up a list of consoles. Called from init/main.c */ static int __init console_setup(char *str) { char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */ - char *s, *options; + char *s, *options, *brl_options = NULL; int idx; +#ifdef CONFIG_A11Y_BRAILLE_CONSOLE + if (!memcmp(str, "brl,", 4)) { + brl_options = ""; + str += 4; + } else if (!memcmp(str, "brl=", 4)) { + brl_options = str + 4; + str = strchr(brl_options, ','); + if (!str) { + printk(KERN_ERR "need port name after brl=\n"); + return 1; + } + *(str++) = 0; + } +#endif + /* * Decode str into name, index, options. */ @@ -841,7 +889,7 @@ static int __init console_setup(char *str) idx = simple_strtoul(s, NULL, 10); *s = 0; - add_preferred_console(buf, idx, options); + __add_preferred_console(buf, idx, options, brl_options); return 1; } __setup("console=", console_setup); @@ -861,28 +909,7 @@ __setup("console=", console_setup); */ int add_preferred_console(char *name, int idx, char *options) { - struct console_cmdline *c; - int i; - - /* - * See if this tty is not yet registered, and - * if we have a slot free. - */ - for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) - if (strcmp(console_cmdline[i].name, name) == 0 && - console_cmdline[i].index == idx) { - selected_console = i; - return 0; - } - if (i == MAX_CMDLINECONSOLES) - return -E2BIG; - selected_console = i; - c = &console_cmdline[i]; - memcpy(c->name, name, sizeof(c->name)); - c->name[sizeof(c->name) - 1] = 0; - c->options = options; - c->index = idx; - return 0; + return __add_preferred_console(name, idx, options, NULL); } int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options) @@ -1163,6 +1190,16 @@ void register_console(struct console *console) continue; if (console->index < 0) console->index = console_cmdline[i].index; +#ifdef CONFIG_A11Y_BRAILLE_CONSOLE + if (console_cmdline[i].brl_options) { + console->flags |= CON_BRL; + braille_register_console(console, + console_cmdline[i].index, + console_cmdline[i].options, + console_cmdline[i].brl_options); + return; + } +#endif if (console->setup && console->setup(console, console_cmdline[i].options) != 0) break; @@ -1221,6 +1258,11 @@ int unregister_console(struct console *console) struct console *a, *b; int res = 1; +#ifdef CONFIG_A11Y_BRAILLE_CONSOLE + if (console->flags & CON_BRL) + return braille_unregister_console(console); +#endif + acquire_console_sem(); if (console_drivers == console) { console_drivers=console->next; -- cgit v1.2.3 From 074b3b87941c99bc0ce35385b5817924b1ed0c23 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Thu, 1 May 2008 04:34:34 -0700 Subject: ntp: increase time_freq resolution This changes time_freq to a 64bit value and makes it static (the only outside user had no real need to modify it). Intermediate values were already 64bit, so the change isn't that big, but it saves a little in shifts by replacing SHIFT_NSEC with TICK_LENGTH_SHIFT. PPM_SCALE is then used to convert between user space and kernel space representation. Signed-off-by: Roman Zippel Cc: john stultz Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/time.c | 2 -- include/linux/timex.h | 11 ++++++----- kernel/time/ntp.c | 30 +++++++++++++++--------------- 3 files changed, 21 insertions(+), 22 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 3b26fbd6bec9..c146af995854 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -1007,8 +1007,6 @@ void __init time_init(void) vdso_data->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; vdso_data->tb_to_xs = tb_to_xs; - time_freq = 0; - write_sequnlock_irqrestore(&xtime_lock, flags); /* Register the clocksource, if we're not running on iSeries */ diff --git a/include/linux/timex.h b/include/linux/timex.h index 3c49d173bf39..48c3376dce71 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -86,11 +86,14 @@ */ #define SHIFT_UPDATE (SHIFT_HZ + 1) /* time offset scale (shift) */ #define SHIFT_USEC 16 /* frequency offset scale (shift) */ -#define SHIFT_NSEC 12 /* kernel frequency offset scale */ +#define PPM_SCALE (NSEC_PER_USEC << (TICK_LENGTH_SHIFT - SHIFT_USEC)) +#define PPM_SCALE_INV_SHIFT 20 +#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + TICK_LENGTH_SHIFT)) / \ + PPM_SCALE + 1) #define MAXPHASE 512000L /* max phase error (us) */ -#define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */ -#define MAXFREQ_NSEC (512000L << SHIFT_NSEC) /* max frequency error (ppb) */ +#define MAXFREQ 500000 /* max frequency error (ns/s) */ +#define MAXFREQ_SCALED ((s64)MAXFREQ << TICK_LENGTH_SHIFT) #define MINSEC 256 /* min interval between updates (s) */ #define MAXSEC 2048 /* max interval between updates (s) */ #define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */ @@ -209,8 +212,6 @@ extern int time_status; /* clock synchronization status bits */ extern long time_maxerror; /* maximum error */ extern long time_esterror; /* estimated error */ -extern long time_freq; /* frequency offset (scaled ppm) */ - extern long time_adjust; /* The amount of adjtime left */ extern void ntp_clear(void); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 3fc81066d7f1..c6ae0c249891 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -39,7 +39,7 @@ static s64 time_offset; /* time adjustment (ns) */ static long time_constant = 2; /* pll time constant */ long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */ long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ -long time_freq; /* frequency offset (scaled ppm)*/ +static s64 time_freq; /* frequency offset (scaled ns/s)*/ static long time_reftime; /* time at last adjustment (s) */ long time_adjust; static long ntp_tick_adj; @@ -49,7 +49,7 @@ static void ntp_update_frequency(void) u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; second_length += (s64)ntp_tick_adj << TICK_LENGTH_SHIFT; - second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); + second_length += time_freq; tick_length_base = second_length; @@ -86,16 +86,16 @@ static void ntp_update_offset(long offset) time_reftime = xtime.tv_sec; freq_adj = time_offset * mtemp; - freq_adj = shift_right(freq_adj, time_constant * 2 + - (SHIFT_PLL + 2) * 2 - SHIFT_NSEC); + freq_adj <<= TICK_LENGTH_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant); time_status &= ~STA_MODE; if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) { - freq_adj += div_s64(time_offset << (SHIFT_NSEC - SHIFT_FLL), mtemp); + freq_adj += div_s64(time_offset << (TICK_LENGTH_SHIFT - SHIFT_FLL), + mtemp); time_status |= STA_MODE; } freq_adj += time_freq; - freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); - time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC); + freq_adj = min(freq_adj, MAXFREQ_SCALED); + time_freq = max(freq_adj, -MAXFREQ_SCALED); time_offset = div_s64(time_offset, NTP_INTERVAL_FREQ); time_offset <<= SHIFT_UPDATE; } @@ -131,7 +131,7 @@ void second_overflow(void) long time_adj; /* Bump the maxerror field */ - time_maxerror += MAXFREQ >> SHIFT_USEC; + time_maxerror += MAXFREQ / NSEC_PER_USEC; if (time_maxerror > NTP_PHASE_LIMIT) { time_maxerror = NTP_PHASE_LIMIT; time_status |= STA_UNSYNC; @@ -323,10 +323,9 @@ int do_adjtimex(struct timex *txc) time_status &= ~STA_NANO; if (txc->modes & ADJ_FREQUENCY) { - time_freq = min(txc->freq, MAXFREQ); - time_freq = min(time_freq, -MAXFREQ); - time_freq = ((s64)time_freq * NSEC_PER_USEC) - >> (SHIFT_USEC - SHIFT_NSEC); + time_freq = (s64)txc->freq * PPM_SCALE; + time_freq = min(time_freq, MAXFREQ_SCALED); + time_freq = max(time_freq, -MAXFREQ_SCALED); } if (txc->modes & ADJ_MAXERROR) @@ -369,14 +368,15 @@ int do_adjtimex(struct timex *txc) if (!(time_status & STA_NANO)) txc->offset /= NSEC_PER_USEC; } - txc->freq = (time_freq / NSEC_PER_USEC) << - (SHIFT_USEC - SHIFT_NSEC); + txc->freq = shift_right((s32)(time_freq >> PPM_SCALE_INV_SHIFT) * + (s64)PPM_SCALE_INV, + TICK_LENGTH_SHIFT); txc->maxerror = time_maxerror; txc->esterror = time_esterror; txc->status = time_status; txc->constant = time_constant; txc->precision = 1; - txc->tolerance = MAXFREQ; + txc->tolerance = MAXFREQ_SCALED / PPM_SCALE; txc->tick = tick_usec; /* PPS is not implemented, so these are zero */ -- cgit v1.2.3 From 7fc5c78409479d826341b103bdf734cb4fb02436 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Thu, 1 May 2008 04:34:38 -0700 Subject: ntp: rename TICK_LENGTH_SHIFT to NTP_SCALE_SHIFT As TICK_LENGTH_SHIFT is used for more than just the tick length, the name isn't quite approriate anymore, so this renames it to NTP_SCALE_SHIFT. Signed-off-by: Roman Zippel Cc: john stultz Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/time.c | 2 +- include/linux/timex.h | 8 ++++---- kernel/time/ntp.c | 20 ++++++++++---------- kernel/time/timekeeping.c | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index c146af995854..73401e83739a 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -149,7 +149,7 @@ EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ u64 tb_to_xs; unsigned tb_to_us; -#define TICKLEN_SCALE TICK_LENGTH_SHIFT +#define TICKLEN_SCALE NTP_SCALE_SHIFT u64 last_tick_len; /* units are ns / 2^TICKLEN_SCALE */ u64 ticklen_to_xs; /* 0.64 fraction */ diff --git a/include/linux/timex.h b/include/linux/timex.h index 6ff92237759a..5994d39de778 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -81,14 +81,14 @@ * offset and maximum frequency tolerance. */ #define SHIFT_USEC 16 /* frequency offset scale (shift) */ -#define PPM_SCALE (NSEC_PER_USEC << (TICK_LENGTH_SHIFT - SHIFT_USEC)) +#define PPM_SCALE (NSEC_PER_USEC << (NTP_SCALE_SHIFT - SHIFT_USEC)) #define PPM_SCALE_INV_SHIFT 20 -#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + TICK_LENGTH_SHIFT)) / \ +#define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + NTP_SCALE_SHIFT)) / \ PPM_SCALE + 1) #define MAXPHASE 500000000l /* max phase error (ns) */ #define MAXFREQ 500000 /* max frequency error (ns/s) */ -#define MAXFREQ_SCALED ((s64)MAXFREQ << TICK_LENGTH_SHIFT) +#define MAXFREQ_SCALED ((s64)MAXFREQ << NTP_SCALE_SHIFT) #define MINSEC 256 /* min interval between updates (s) */ #define MAXSEC 2048 /* max interval between updates (s) */ #define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */ @@ -230,7 +230,7 @@ static inline int ntp_synced(void) __x < 0 ? -(-__x >> __s) : __x >> __s; \ }) -#define TICK_LENGTH_SHIFT 32 +#define NTP_SCALE_SHIFT 32 #ifdef CONFIG_NO_HZ #define NTP_INTERVAL_FREQ (2) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 10fe17df45a0..a8fd1ba1ef19 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -27,7 +27,7 @@ static u64 tick_length, tick_length_base; #define MAX_TICKADJ 500 /* microsecs */ #define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ - TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ) + NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ) /* * phase-lock loop variables @@ -48,13 +48,13 @@ static long ntp_tick_adj; static void ntp_update_frequency(void) { u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) - << TICK_LENGTH_SHIFT; - second_length += (s64)ntp_tick_adj << TICK_LENGTH_SHIFT; + << NTP_SCALE_SHIFT; + second_length += (s64)ntp_tick_adj << NTP_SCALE_SHIFT; second_length += time_freq; tick_length_base = second_length; - tick_nsec = div_u64(second_length, HZ) >> TICK_LENGTH_SHIFT; + tick_nsec = div_u64(second_length, HZ) >> NTP_SCALE_SHIFT; tick_length_base = div_u64(tick_length_base, NTP_INTERVAL_FREQ); } @@ -86,10 +86,10 @@ static void ntp_update_offset(long offset) time_reftime = xtime.tv_sec; freq_adj = (s64)offset * mtemp; - freq_adj <<= TICK_LENGTH_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant); + freq_adj <<= NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant); time_status &= ~STA_MODE; if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) { - freq_adj += div_s64((s64)offset << (TICK_LENGTH_SHIFT - SHIFT_FLL), + freq_adj += div_s64((s64)offset << (NTP_SCALE_SHIFT - SHIFT_FLL), mtemp); time_status |= STA_MODE; } @@ -97,7 +97,7 @@ static void ntp_update_offset(long offset) freq_adj = min(freq_adj, MAXFREQ_SCALED); time_freq = max(freq_adj, -MAXFREQ_SCALED); - time_offset = div_s64((s64)offset << TICK_LENGTH_SHIFT, NTP_INTERVAL_FREQ); + time_offset = div_s64((s64)offset << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ); } /** @@ -197,7 +197,7 @@ void second_overflow(void) tick_length -= MAX_TICKADJ_SCALED; } else { tick_length += (s64)(time_adjust * NSEC_PER_USEC / - NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT; + NTP_INTERVAL_FREQ) << NTP_SCALE_SHIFT; time_adjust = 0; } } @@ -369,13 +369,13 @@ int do_adjtimex(struct timex *txc) txc->offset = save_adjust; else { txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, - TICK_LENGTH_SHIFT); + NTP_SCALE_SHIFT); if (!(time_status & STA_NANO)) txc->offset /= NSEC_PER_USEC; } txc->freq = shift_right((s32)(time_freq >> PPM_SCALE_INV_SHIFT) * (s64)PPM_SCALE_INV, - TICK_LENGTH_SHIFT); + NTP_SCALE_SHIFT); txc->maxerror = time_maxerror; txc->esterror = time_esterror; txc->status = time_status; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2d6087c7cf98..a26429bc772a 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -371,7 +371,7 @@ static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, * here. This is tuned so that an error of about 1 msec is adjusted * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks). */ - error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ); + error2 = clock->error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ); error2 = abs(error2); for (look_ahead = 0; error2 > 0; look_ahead++) error2 >>= 2; @@ -381,7 +381,7 @@ static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, * remove the single look ahead already included in the error. */ tick_error = current_tick_length() >> - (TICK_LENGTH_SHIFT - clock->shift + 1); + (NTP_SCALE_SHIFT - clock->shift + 1); tick_error -= clock->xtime_interval >> 1; error = ((error - tick_error) >> look_ahead) + tick_error; @@ -412,7 +412,7 @@ static void clocksource_adjust(s64 offset) s64 error, interval = clock->cycle_interval; int adj; - error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1); + error = clock->error >> (NTP_SCALE_SHIFT - clock->shift - 1); if (error > interval) { error >>= 2; if (likely(error <= interval)) @@ -434,7 +434,7 @@ static void clocksource_adjust(s64 offset) clock->xtime_interval += interval; clock->xtime_nsec -= offset; clock->error -= (interval - offset) << - (TICK_LENGTH_SHIFT - clock->shift); + (NTP_SCALE_SHIFT - clock->shift); } /** @@ -474,7 +474,7 @@ void update_wall_time(void) /* accumulate error between NTP and clock interval */ clock->error += current_tick_length(); - clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); + clock->error -= clock->xtime_interval << (NTP_SCALE_SHIFT - clock->shift); } /* correct the clock when NTP error is too big */ -- cgit v1.2.3 From 9f3acc3140444a900ab280de942291959f0f615d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Apr 2008 07:44:08 -0400 Subject: [PATCH] split linux/file.h Initial splitoff of the low-level stuff; taken to fdtable.h Signed-off-by: Al Viro --- arch/mips/kernel/kspd.c | 1 + arch/powerpc/platforms/cell/spufs/coredump.c | 1 + drivers/char/tty_audit.c | 1 + drivers/char/tty_io.c | 1 + fs/compat.c | 1 + fs/dnotify.c | 2 +- fs/exec.c | 1 + fs/fcntl.c | 1 + fs/file.c | 1 + fs/file_table.c | 1 + fs/locks.c | 1 + fs/open.c | 1 + fs/proc/array.c | 1 + fs/proc/base.c | 1 + fs/select.c | 1 + include/linux/fdtable.h | 99 ++++++++++++++++++++++++++++ include/linux/file.h | 86 +----------------------- include/linux/init_task.h | 2 +- kernel/exit.c | 1 + kernel/fork.c | 1 + kernel/kmod.c | 1 + security/selinux/hooks.c | 1 + 22 files changed, 121 insertions(+), 86 deletions(-) create mode 100644 include/linux/fdtable.h (limited to 'arch/powerpc') diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 998c4efcce88..ceb62dce1c9c 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index b962c3ab470c..af116aadba10 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 6342b0534f4d..3582f43345a8 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c @@ -11,6 +11,7 @@ #include #include +#include #include struct tty_audit_buf { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 1d298c2cf930..49c1a2267a55 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -78,6 +78,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/compat.c b/fs/compat.c index 139dc93c092d..332a869d2c53 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/dnotify.c b/fs/dnotify.c index eaecc4cfe540..676073b8dda5 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include int dir_notify_enable __read_mostly = 1; diff --git a/fs/exec.c b/fs/exec.c index 9f9f931ef949..aeaa9791d8be 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/fs/fcntl.c b/fs/fcntl.c index 3f3ac630ccde..bfd776509a72 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/file.c b/fs/file.c index 5110acb1c9ef..f6fbcb49faf7 100644 --- a/fs/file.c +++ b/fs/file.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/file_table.c b/fs/file_table.c index 7a0a9b872251..83084225b4c3 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/locks.c b/fs/locks.c index 44d9a6a7ec50..663c069b59b3 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -116,6 +116,7 @@ #include #include +#include #include #include #include diff --git a/fs/open.c b/fs/open.c index 7af1f05d5978..a1450086e92f 100644 --- a/fs/open.c +++ b/fs/open.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/proc/array.c b/fs/proc/array.c index c135cbdd9127..dca997a93bff 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/proc/base.c b/fs/proc/base.c index fcf02f2deeba..808cbdc193d3 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/select.c b/fs/select.c index 80d70387e790..8dda969614a9 100644 --- a/fs/select.c +++ b/fs/select.c @@ -21,6 +21,7 @@ #include #include /* for STICKY_TIMEOUTS */ #include +#include #include #include diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h new file mode 100644 index 000000000000..a118f3c0b240 --- /dev/null +++ b/include/linux/fdtable.h @@ -0,0 +1,99 @@ +/* + * descriptor table internals; you almost certainly want file.h instead. + */ + +#ifndef __LINUX_FDTABLE_H +#define __LINUX_FDTABLE_H + +#include +#include +#include +#include +#include +#include + +/* + * The default fd array needs to be at least BITS_PER_LONG, + * as this is the granularity returned by copy_fdset(). + */ +#define NR_OPEN_DEFAULT BITS_PER_LONG + +/* + * The embedded_fd_set is a small fd_set, + * suitable for most tasks (which open <= BITS_PER_LONG files) + */ +struct embedded_fd_set { + unsigned long fds_bits[1]; +}; + +struct fdtable { + unsigned int max_fds; + struct file ** fd; /* current fd array */ + fd_set *close_on_exec; + fd_set *open_fds; + struct rcu_head rcu; + struct fdtable *next; +}; + +/* + * Open file table structure + */ +struct files_struct { + /* + * read mostly part + */ + atomic_t count; + struct fdtable *fdt; + struct fdtable fdtab; + /* + * written part on a separate cache line in SMP + */ + spinlock_t file_lock ____cacheline_aligned_in_smp; + int next_fd; + struct embedded_fd_set close_on_exec_init; + struct embedded_fd_set open_fds_init; + struct file * fd_array[NR_OPEN_DEFAULT]; +}; + +#define files_fdtable(files) (rcu_dereference((files)->fdt)) + +extern struct kmem_cache *filp_cachep; + +struct file_operations; +struct vfsmount; +struct dentry; + +extern int expand_files(struct files_struct *, int nr); +extern void free_fdtable_rcu(struct rcu_head *rcu); +extern void __init files_defer_init(void); + +static inline void free_fdtable(struct fdtable *fdt) +{ + call_rcu(&fdt->rcu, free_fdtable_rcu); +} + +static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) +{ + struct file * file = NULL; + struct fdtable *fdt = files_fdtable(files); + + if (fd < fdt->max_fds) + file = rcu_dereference(fdt->fd[fd]); + return file; +} + +/* + * Check whether the specified fd has an open file. + */ +#define fcheck(fd) fcheck_files(current->files, fd) + +struct task_struct; + +struct files_struct *get_files_struct(struct task_struct *); +void put_files_struct(struct files_struct *fs); +void reset_files_struct(struct files_struct *); +int unshare_files(struct files_struct **); + +extern struct kmem_cache *files_cachep; + +#endif /* __LINUX_FDTABLE_H */ diff --git a/include/linux/file.h b/include/linux/file.h index 69baf5a4f0a5..27c64bdc68c9 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -5,59 +5,11 @@ #ifndef __LINUX_FILE_H #define __LINUX_FILE_H -#include -#include #include -#include -#include #include +#include -/* - * The default fd array needs to be at least BITS_PER_LONG, - * as this is the granularity returned by copy_fdset(). - */ -#define NR_OPEN_DEFAULT BITS_PER_LONG - -/* - * The embedded_fd_set is a small fd_set, - * suitable for most tasks (which open <= BITS_PER_LONG files) - */ -struct embedded_fd_set { - unsigned long fds_bits[1]; -}; - -struct fdtable { - unsigned int max_fds; - struct file ** fd; /* current fd array */ - fd_set *close_on_exec; - fd_set *open_fds; - struct rcu_head rcu; - struct fdtable *next; -}; - -/* - * Open file table structure - */ -struct files_struct { - /* - * read mostly part - */ - atomic_t count; - struct fdtable *fdt; - struct fdtable fdtab; - /* - * written part on a separate cache line in SMP - */ - spinlock_t file_lock ____cacheline_aligned_in_smp; - int next_fd; - struct embedded_fd_set close_on_exec_init; - struct embedded_fd_set open_fds_init; - struct file * fd_array[NR_OPEN_DEFAULT]; -}; - -#define files_fdtable(files) (rcu_dereference((files)->fdt)) - -extern struct kmem_cache *filp_cachep; +struct file; extern void __fput(struct file *); extern void fput(struct file *); @@ -85,41 +37,7 @@ extern void put_filp(struct file *); extern int get_unused_fd(void); extern int get_unused_fd_flags(int flags); extern void put_unused_fd(unsigned int fd); -struct kmem_cache; - -extern int expand_files(struct files_struct *, int nr); -extern void free_fdtable_rcu(struct rcu_head *rcu); -extern void __init files_defer_init(void); - -static inline void free_fdtable(struct fdtable *fdt) -{ - call_rcu(&fdt->rcu, free_fdtable_rcu); -} - -static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) -{ - struct file * file = NULL; - struct fdtable *fdt = files_fdtable(files); - - if (fd < fdt->max_fds) - file = rcu_dereference(fdt->fd[fd]); - return file; -} - -/* - * Check whether the specified fd has an open file. - */ -#define fcheck(fd) fcheck_files(current->files, fd) extern void fd_install(unsigned int fd, struct file *file); -struct task_struct; - -struct files_struct *get_files_struct(struct task_struct *); -void put_files_struct(struct files_struct *fs); -void reset_files_struct(struct files_struct *); -int unshare_files(struct files_struct **); - -extern struct kmem_cache *files_cachep; - #endif /* __LINUX_FILE_H */ diff --git a/include/linux/init_task.h b/include/linux/init_task.h index bf6b8a61f8db..b24c2875aa05 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -1,7 +1,7 @@ #ifndef _LINUX__INIT_TASK_H #define _LINUX__INIT_TASK_H -#include +#include #include #include #include diff --git a/kernel/exit.c b/kernel/exit.c index d3ad54677f9c..1510f78a0ffa 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/kernel/fork.c b/kernel/fork.c index 2bb675af4de3..933e60ebccae 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/kernel/kmod.c b/kernel/kmod.c index e2764047ec03..8df97d3dfda8 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1b50a6ebc55f..1c864c0efe2b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From d35c7b0e54a596c5a8134d75999b7f391a9c6550 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 3 May 2008 15:10:37 -0400 Subject: unified (weak) sys_pipe implementation This replaces the duplicated arch-specific versions of "sys_pipe()" with one unified implementation. This removes almost 250 lines of duplicated code. It's marked __weak, so that *if* an architecture wants to override the default implementation it can do so by simply having its own replacement version, since many architectures use alternate calling conventions for the 'pipe()' system call for legacy reasons (ie traditional UNIX implementations often return the two file descriptors in registers) I still haven't changed the cris version even though Linus says the BKL isn't needed. The arch maintainer can easily do it if there are really no obstacles. Signed-off-by: Ulrich Drepper Signed-off-by: Linus Torvalds --- arch/arm/kernel/sys_arm.c | 17 ----------------- arch/avr32/kernel/sys_avr32.c | 13 ------------- arch/blackfin/kernel/sys_bfin.c | 17 ----------------- arch/frv/kernel/sys_frv.c | 17 ----------------- arch/h8300/kernel/sys_h8300.c | 17 ----------------- arch/m68k/kernel/sys_m68k.c | 17 ----------------- arch/m68knommu/kernel/sys_m68k.c | 17 ----------------- arch/mn10300/kernel/sys_mn10300.c | 17 ----------------- arch/parisc/kernel/sys_parisc.c | 13 ------------- arch/powerpc/kernel/syscalls.c | 17 ----------------- arch/s390/kernel/sys_s390.c | 17 ----------------- arch/sh/kernel/sys_sh64.c | 17 ----------------- arch/um/kernel/syscall.c | 17 ----------------- arch/v850/kernel/syscalls.c | 17 ----------------- arch/x86/kernel/sys_i386_32.c | 17 ----------------- arch/x86/kernel/sys_x86_64.c | 17 ----------------- fs/pipe.c | 17 +++++++++++++++++ include/asm-powerpc/syscalls.h | 2 +- 18 files changed, 18 insertions(+), 265 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 9bd1870d980e..0128687ba0f7 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -34,23 +34,6 @@ extern unsigned long do_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr); -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ inline long do_mmap2( unsigned long addr, unsigned long len, diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c index 8deb6003ee62..8e8911e55c8f 100644 --- a/arch/avr32/kernel/sys_avr32.c +++ b/arch/avr32/kernel/sys_avr32.c @@ -14,19 +14,6 @@ #include #include -asmlinkage int sys_pipe(unsigned long __user *filedes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(filedes, fd, sizeof(fd))) - error = -EFAULT; - } - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t offset) diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index efb7b25a2633..fce49d7cf001 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c @@ -45,23 +45,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2 * sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2(unsigned long addr, unsigned long len, diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 04c6b1677ccf..49b2cf2c38f3 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c @@ -28,23 +28,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage long sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index 00608be6d567..2745656dcc52 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c @@ -27,23 +27,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2( unsigned long addr, unsigned long len, diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index e892f17ba3fa..7f54efaf60bb 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -30,23 +30,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2( unsigned long addr, unsigned long len, diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c index 65f7a95f056e..700281638629 100644 --- a/arch/m68knommu/kernel/sys_m68k.c +++ b/arch/m68knommu/kernel/sys_m68k.c @@ -28,23 +28,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2( unsigned long addr, unsigned long len, diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c index 5f17a1ebc825..bca5a84dc72c 100644 --- a/arch/mn10300/kernel/sys_mn10300.c +++ b/arch/mn10300/kernel/sys_mn10300.c @@ -28,23 +28,6 @@ #define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */ -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage long sys_pipe(unsigned long __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2 * sizeof(int))) - error = -EFAULT; - } - return error; -} - /* * memory mapping syscall */ diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 4f589216b39e..71b31957c8f1 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -33,19 +33,6 @@ #include #include -int sys_pipe(int __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - static unsigned long get_unshared_area(unsigned long addr, unsigned long len) { struct vm_area_struct *vma; diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index e722a4eeb5d0..4fe69ca24481 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -136,23 +136,6 @@ int sys_ipc(uint call, int first, unsigned long second, long third, return ret; } -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -int sys_pipe(int __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - static inline unsigned long do_mmap2(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off, int shift) diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 988d0d64c2c8..5fdb799062b7 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -32,23 +32,6 @@ #include #include "entry.h" -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage long sys_pipe(unsigned long __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2( unsigned long addr, unsigned long len, diff --git a/arch/sh/kernel/sys_sh64.c b/arch/sh/kernel/sys_sh64.c index 578004d71e02..91fb8445a5a0 100644 --- a/arch/sh/kernel/sys_sh64.c +++ b/arch/sh/kernel/sys_sh64.c @@ -30,23 +30,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* * Do a system call from kernel instead of calling sys_execve so we * end up with proper pt_regs. diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 9cffc628a37e..128ee85bc8d9 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -73,23 +73,6 @@ long old_mmap(unsigned long addr, unsigned long len, out: return err; } -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -long sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - long error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, sizeof(fd))) - error = -EFAULT; - } - return error; -} - long sys_uname(struct old_utsname __user * name) { diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c index 003db9c8c44a..1a83daf8e24f 100644 --- a/arch/v850/kernel/syscalls.c +++ b/arch/v850/kernel/syscalls.c @@ -132,23 +132,6 @@ sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) return ret; } -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -int sys_pipe (int *fildes) -{ - int fd[2]; - int error; - - error = do_pipe (fd); - if (!error) { - if (copy_to_user (fildes, fd, 2*sizeof (int))) - error = -EFAULT; - } - return error; -} - static inline unsigned long do_mmap2 (unsigned long addr, size_t len, unsigned long prot, unsigned long flags, diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index a86d26f036e1..d2ab52cc1d6b 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -22,23 +22,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index bd802a5e1aa3..3b360ef33817 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -17,23 +17,6 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage long sys_pipe(int __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off) { diff --git a/fs/pipe.c b/fs/pipe.c index f73492b6817e..3499f9ff6316 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1075,6 +1075,23 @@ int do_pipe(int *fd) return error; } +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way Unix traditionally does this, though. + */ +asmlinkage long __weak sys_pipe(int __user *fildes) +{ + int fd[2]; + int error; + + error = do_pipe(fd); + if (!error) { + if (copy_to_user(fildes, fd, sizeof(fd))) + error = -EFAULT; + } + return error; +} + /* * pipefs should _never_ be mounted by userland - too much of security hassle, * no real gain from having the whole whorehouse mounted. So we don't need diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h index b3ca41fc8bb1..2b8a458f990a 100644 --- a/include/asm-powerpc/syscalls.h +++ b/include/asm-powerpc/syscalls.h @@ -30,7 +30,7 @@ asmlinkage int sys_fork(unsigned long p1, unsigned long p2, asmlinkage int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs); -asmlinkage int sys_pipe(int __user *fildes); +asmlinkage long sys_pipe(int __user *fildes); asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, size_t sigsetsize); -- cgit v1.2.3 From 45c5eb67da5a668abe79c23a7e64dbc87a600f90 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Fri, 25 Apr 2008 17:55:49 -0500 Subject: KVM: ppc: Handle guest idle by emulating MSR[WE] writes This reduces host CPU usage when the guest is idle. However, the guest must set MSR[WE] in its idle loop, which Linux did not do until 2.6.26. Signed-off-by: Hollis Blanchard Signed-off-by: Jerone Young Signed-off-by: Avi Kivity --- arch/powerpc/kvm/booke_guest.c | 1 + arch/powerpc/kvm/powerpc.c | 20 +++++++++++++++++--- include/asm-powerpc/kvm_host.h | 1 + include/asm-powerpc/kvm_ppc.h | 5 +++++ 4 files changed, 24 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c index 6d9884a6884a..b3db6f4576ad 100644 --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -49,6 +49,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "inst_emu", VCPU_STAT(emulated_inst_exits) }, { "dec", VCPU_STAT(dec_exits) }, { "ext_intr", VCPU_STAT(ext_intr_exits) }, + { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { NULL } }; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index bad40bd2d3ac..777e0f34e0ea 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -36,13 +36,12 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) int kvm_cpu_has_interrupt(struct kvm_vcpu *v) { - /* XXX implement me */ - return 0; + return !!(v->arch.pending_exceptions); } int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) { - return 1; + return !(v->arch.msr & MSR_WE); } @@ -214,6 +213,11 @@ static void kvmppc_decrementer_func(unsigned long data) struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); + + if (waitqueue_active(&vcpu->wq)) { + wake_up_interruptible(&vcpu->wq); + vcpu->stat.halt_wakeup++; + } } int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) @@ -339,6 +343,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) int r; sigset_t sigsaved; + vcpu_load(vcpu); + if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); @@ -363,12 +369,20 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &sigsaved, NULL); + vcpu_put(vcpu); + return r; } int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) { kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); + + if (waitqueue_active(&vcpu->wq)) { + wake_up_interruptible(&vcpu->wq); + vcpu->stat.halt_wakeup++; + } + return 0; } diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h index 04ffbb8e0a35..81a69d711017 100644 --- a/include/asm-powerpc/kvm_host.h +++ b/include/asm-powerpc/kvm_host.h @@ -59,6 +59,7 @@ struct kvm_vcpu_stat { u32 emulated_inst_exits; u32 dec_exits; u32 ext_intr_exits; + u32 halt_wakeup; }; struct tlbe { diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h index 7ac820308a7e..b35a7e3ef978 100644 --- a/include/asm-powerpc/kvm_ppc.h +++ b/include/asm-powerpc/kvm_ppc.h @@ -77,12 +77,17 @@ static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception) clear_bit(priority, &vcpu->arch.pending_exceptions); } +/* Helper function for "full" MSR writes. No need to call this if only EE is + * changing. */ static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) { if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR)) kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR); vcpu->arch.msr = new_msr; + + if (vcpu->arch.msr & MSR_WE) + kvm_vcpu_block(vcpu); } #endif /* __POWERPC_KVM_PPC_H__ */ -- cgit v1.2.3 From de368dceb33c3c068dbde1407aff75cd8e126f04 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Tue, 29 Apr 2008 18:18:23 +0200 Subject: KVM: ppc: deliver INTERRUPT_FP_UNAVAIL to the guest This patch adds the delivery of INTERRUPT_FP_UNAVAIL exceptions to the guest. It's needed if a guest uses ppc binaries using the Floating point instructions. Signed-off-by: Christian Ehrhardt Acked-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/booke_guest.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c index b3db6f4576ad..712d89a28c46 100644 --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -339,6 +339,11 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, } break; + case BOOKE_INTERRUPT_FP_UNAVAIL: + kvmppc_queue_exception(vcpu, exit_nr); + r = RESUME_GUEST; + break; + case BOOKE_INTERRUPT_DATA_STORAGE: vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; -- cgit v1.2.3 From b41e5fffe8b81fc939067d8c1c195cc79115d5a3 Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Sat, 3 May 2008 06:34:04 +1000 Subject: [POWERPC] devres: Add devm_ioremap_prot() We provide an ioremap_flags, so this provides a corresponding devm_ioremap_prot. The slight name difference is at Ben Herrenschmidt's request as he plans on changing ioremap_flags to ioremap_prot in the future. Signed-off-by: Emil Medve Signed-off-by: Kumar Gala Acked-by: Tejun Heo Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/lib/Makefile | 1 + arch/powerpc/lib/devres.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/io.h | 8 +++++++- include/linux/io.h | 1 + lib/devres.c | 2 +- 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/lib/devres.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 4bb023f4c869..f1d2cdc5331b 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_SMP) += locks.o endif obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o +obj-$(CONFIG_HAS_IOMEM) += devres.o diff --git a/arch/powerpc/lib/devres.c b/arch/powerpc/lib/devres.c new file mode 100644 index 000000000000..292115d98ea9 --- /dev/null +++ b/arch/powerpc/lib/devres.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include /* devres_*(), devm_ioremap_release() */ +#include /* ioremap_flags() */ +#include /* EXPORT_SYMBOL() */ + +/** + * devm_ioremap_prot - Managed ioremap_flags() + * @dev: Generic device to remap IO address for + * @offset: BUS offset to map + * @size: Size of map + * @flags: Page flags + * + * Managed ioremap_prot(). Map is automatically unmapped on driver + * detach. + */ +void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset, + size_t size, unsigned long flags) +{ + void __iomem **ptr, *addr; + + ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + addr = ioremap_flags(offset, size, flags); + if (addr) { + *ptr = addr; + devres_add(dev, ptr); + } else + devres_free(ptr); + + return addr; +} +EXPORT_SYMBOL(devm_ioremap_prot); diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index afae0697e8ce..e0062d73db1c 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -2,7 +2,7 @@ #define _ASM_POWERPC_IO_H #ifdef __KERNEL__ -/* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -18,6 +18,9 @@ extern int check_legacy_ioport(unsigned long base_port); #define _PNPWRP 0xa79 #define PNPBIOS_BASE 0xf000 +#include +#include + #include #include #include @@ -744,6 +747,9 @@ static inline void * bus_to_virt(unsigned long address) #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) +void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset, + size_t size, unsigned long flags); + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_IO_H */ diff --git a/include/linux/io.h b/include/linux/io.h index 3a03a3604cce..6c7f0ba0d5fa 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -65,5 +65,6 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, void devm_iounmap(struct device *dev, void __iomem *addr); int check_signature(const volatile void __iomem *io_addr, const unsigned char *signature, int length); +void devm_ioremap_release(struct device *dev, void *res); #endif /* _LINUX_IO_H */ diff --git a/lib/devres.c b/lib/devres.c index 26c87c49d776..72c8909006da 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -2,7 +2,7 @@ #include #include -static void devm_ioremap_release(struct device *dev, void *res) +void devm_ioremap_release(struct device *dev, void *res) { iounmap(*(void __iomem **)res); } -- cgit v1.2.3 From 9185ef6787f1c8f1c06aa0cb3c7746fb4f101f50 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Sat, 3 May 2008 06:34:05 +1000 Subject: [POWERPC] Assign PDE->data before gluing PDE into /proc tree Simply replace proc_create and further data assigned with proc_create_data. No need to check for data!=NULL after that. Signed-off-by: Denis V. Lunev Cc: Alexey Dobriyan Cc: Eric W. Biederman Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/scanlog.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index bec3803f0618..417eca79df69 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -55,11 +55,6 @@ static ssize_t scanlog_read(struct file *file, char __user *buf, dp = PDE(inode); data = (unsigned int *)dp->data; - if (!data) { - printk(KERN_ERR "scanlog: read failed no data\n"); - return -EIO; - } - if (count > RTAS_DATA_BUF_SIZE) count = RTAS_DATA_BUF_SIZE; @@ -146,11 +141,6 @@ static int scanlog_open(struct inode * inode, struct file * file) struct proc_dir_entry *dp = PDE(inode); unsigned int *data = (unsigned int *)dp->data; - if (!data) { - printk(KERN_ERR "scanlog: open failed no data\n"); - return -EIO; - } - if (data[0] != 0) { /* This imperfect test stops a second copy of the * data (or a reset while data is being copied) @@ -168,10 +158,6 @@ static int scanlog_release(struct inode * inode, struct file * file) struct proc_dir_entry *dp = PDE(inode); unsigned int *data = (unsigned int *)dp->data; - if (!data) { - printk(KERN_ERR "scanlog: release failed no data\n"); - return -EIO; - } data[0] = 0; return 0; @@ -200,12 +186,11 @@ static int __init scanlog_init(void) if (!data) goto err; - ent = proc_create("ppc64/rtas/scan-log-dump", S_IRUSR, NULL, - &scanlog_fops); + ent = proc_create_data("ppc64/rtas/scan-log-dump", S_IRUSR, NULL, + &scanlog_fops, data); if (!ent) goto err; - ent->data = data; proc_ppc64_scan_log_dump = ent; return 0; -- cgit v1.2.3 From a96df496ed1496f3e52a9b3c860cf967aa48adda Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 5 May 2008 16:53:19 +1000 Subject: [POWERPC] 4xx: Fix problem with new TLB storage attibute fields on 440x6 core The new 440x6 core used on AMCC 460EX/GT introduces new storage attibure fields to the TLB2 word. Those are: Bit 11 12 13 14 15 WL1 IL1I IL1D IL2I IL2D With these bits the cache (L1 and L2) can be configured in a more flexible way, instruction- and data-cache independently now. The "old" I and W bits are still available and setting these old bits will automically set these new bits too (for backward compatibilty). The current code does not clear these fields resulting in disabling the cache by chance. This patch now makes sure that these new bits are cleared when the TLB2 word is written. Signed-off-by: Stefan Roese Signed-off-by: Josh Boyer --- arch/powerpc/kernel/head_44x.S | 9 ++++++++- include/asm-powerpc/pgtable-ppc32.h | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index b84ec6a2fc94..c2b9dc4fce5d 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -653,7 +653,14 @@ finish_tlb_load: rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ - rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ + + /* + * Clear U0-U3 and WL1 IL1I IL1D IL2I IL2D bits which are added + * on newer 440 cores like the 440x6 used on AMCC 460EX/460GT (see + * include/asm-powerpc/pgtable-ppc32.h for details). + */ + rlwinm r12, r12, 0, 20, 10 + tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h index 7c97b5a08d08..c08e714d0c42 100644 --- a/include/asm-powerpc/pgtable-ppc32.h +++ b/include/asm-powerpc/pgtable-ppc32.h @@ -209,6 +209,13 @@ extern int icache_44x_need_flush; * 0 1 2 3 4 ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 * - - - - - - U0 U1 U2 U3 W I M G E - UX UW UR SX SW SR * + * Newer 440 cores (440x6 as used on AMCC 460EX/460GT) have additional + * TLB2 storage attibute fields. Those are: + * + * TLB2: + * 0...10 11 12 13 14 15 16...31 + * no change WL1 IL1I IL1D IL2I IL2D no change + * * There are some constrains and options, to decide mapping software bits * into TLB entry. * -- cgit v1.2.3 From 80daac3f86d4f5aafc9d3e79addb90fa118244e2 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 22 Apr 2008 00:54:30 +1000 Subject: [POWERPC] 4xx: Add endpoint support to 4xx PCIe driver This patch adds basic endpoint support to the 4xx PCIe driver. This is done by checking the device_type property of the PCIe device node ("pci" for root-complex and "pci-endpoint" for endpoint configuration). Note: Currently we map a fixed 64MByte window to PLB address 0 (SDRAM). This should probably be configurable via a dts property. Signed-off-by: Stefan Roese Acked-by: Benjamin Herrenschmidt Signed-off-by: Josh Boyer --- arch/powerpc/sysdev/ppc4xx_pci.c | 180 ++++++++++++++++++++++++++++----------- 1 file changed, 131 insertions(+), 49 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 1814adbd2236..b4a54c52e880 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1387,28 +1387,59 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, resource_size_t size = res->end - res->start + 1; u64 sa; - /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(size));; - if (res->flags & IORESOURCE_PREFETCH) - sa |= 0x8; + if (port->endpoint) { + resource_size_t ep_addr = 0; + resource_size_t ep_size = 32 << 20; + + /* Currently we map a fixed 64MByte window to PLB address + * 0 (SDRAM). This should probably be configurable via a dts + * property. + */ + + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(ep_size));; + + /* Setup BAR0 */ + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa) | + PCI_BASE_ADDRESS_MEM_TYPE_64); - out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); - out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + /* Disable BAR1 & BAR2 */ + out_le32(mbase + PECFG_BAR1MPA, 0); + out_le32(mbase + PECFG_BAR2HMPA, 0); + out_le32(mbase + PECFG_BAR2LMPA, 0); - /* The setup of the split looks weird to me ... let's see if it works */ - out_le32(mbase + PECFG_PIM0LAL, 0x00000000); - out_le32(mbase + PECFG_PIM0LAH, 0x00000000); - out_le32(mbase + PECFG_PIM1LAL, 0x00000000); - out_le32(mbase + PECFG_PIM1LAH, 0x00000000); - out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); - out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_PIM01SAL, RES_TO_U32_LOW(sa)); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(ep_addr)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr)); + } else { + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(size));; + if (res->flags & IORESOURCE_PREFETCH) + sa |= 0x8; + + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + + /* The setup of the split looks weird to me ... let's see + * if it works + */ + out_le32(mbase + PECFG_PIM0LAL, 0x00000000); + out_le32(mbase + PECFG_PIM0LAH, 0x00000000); + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); + out_le32(mbase + PECFG_PIM1LAH, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); + out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); + } /* Enable inbound mapping */ out_le32(mbase + PECFG_PIMEN, 0x1); - out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); - out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); - /* Enable I/O, Mem, and Busmaster cycles */ out_le16(mbase + PCI_COMMAND, in_le16(mbase + PCI_COMMAND) | @@ -1422,13 +1453,8 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) const int *bus_range; int primary = 0, busses; void __iomem *mbase = NULL, *cfg_data = NULL; - - /* XXX FIXME: Handle endpoint mode properly */ - if (port->endpoint) { - printk(KERN_WARNING "PCIE%d: Port in endpoint mode !\n", - port->index); - return; - } + const u32 *pval; + u32 val; /* Check if primary bridge */ if (of_get_property(port->node, "primary", NULL)) @@ -1462,21 +1488,30 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) hose->last_busno = hose->first_busno + busses; } - /* We map the external config space in cfg_data and the host config - * space in cfg_addr. External space is 1M per bus, internal space - * is 4K + if (!port->endpoint) { + /* Only map the external config space in cfg_data for + * PCIe root-complexes. External space is 1M per bus + */ + cfg_data = ioremap(port->cfg_space.start + + (hose->first_busno + 1) * 0x100000, + busses * 0x100000); + if (cfg_data == NULL) { + printk(KERN_ERR "%s: Can't map external config space !", + port->node->full_name); + goto fail; + } + hose->cfg_data = cfg_data; + } + + /* Always map the host config space in cfg_addr. + * Internal space is 4K */ - cfg_data = ioremap(port->cfg_space.start + - (hose->first_busno + 1) * 0x100000, - busses * 0x100000); mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); - if (cfg_data == NULL || mbase == NULL) { - printk(KERN_ERR "%s: Can't map config space !", + if (mbase == NULL) { + printk(KERN_ERR "%s: Can't map internal config space !", port->node->full_name); goto fail; } - - hose->cfg_data = cfg_data; hose->cfg_addr = mbase; pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name, @@ -1489,12 +1524,14 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) port->hose = hose; mbase = (void __iomem *)hose->cfg_addr; - /* - * Set bus numbers on our root port - */ - out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); - out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); - out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + if (!port->endpoint) { + /* + * Set bus numbers on our root port + */ + out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); + out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); + out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + } /* * OMRs are already reset, also disable PIMs @@ -1515,17 +1552,49 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window); /* The root complex doesn't show up if we don't set some vendor - * and device IDs into it. Those are the same bogus one that the - * initial code in arch/ppc add. We might want to change that. + * and device IDs into it. The defaults below are the same bogus + * one that the initial code in arch/ppc had. This can be + * overwritten by setting the "vendor-id/device-id" properties + * in the pciex node. */ - out_le16(mbase + 0x200, 0xaaa0 + port->index); - out_le16(mbase + 0x202, 0xbed0 + port->index); - /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ - out_le32(mbase + 0x208, 0x06040001); + /* Get the (optional) vendor-/device-id from the device-tree */ + pval = of_get_property(port->node, "vendor-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xaaa0 + port->index; + else + val = 0xeee0 + port->index; + } + out_le16(mbase + 0x200, val); + + pval = of_get_property(port->node, "device-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xbed0 + port->index; + else + val = 0xfed0 + port->index; + } + out_le16(mbase + 0x202, val); + + if (!port->endpoint) { + /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ + out_le32(mbase + 0x208, 0x06040001); + + printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", + port->index); + } else { + /* Set Class Code to Processor/PPC */ + out_le32(mbase + 0x208, 0x0b200001); + + printk(KERN_INFO "PCIE%d: successfully set as endpoint\n", + port->index); + } - printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", - port->index); return; fail: if (hose) @@ -1542,6 +1611,7 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) const u32 *pval; int portno; unsigned int dcrs; + const char *val; /* First, proceed to core initialization as we assume there's * only one PCIe core in the system @@ -1573,8 +1643,20 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) } port->sdr_base = *pval; - /* XXX Currently, we only support root complex mode */ - port->endpoint = 0; + /* Check if device_type property is set to "pci" or "pci-endpoint". + * Resulting from this setup this PCIe port will be configured + * as root-complex or as endpoint. + */ + val = of_get_property(port->node, "device_type", NULL); + if (!strcmp(val, "pci-endpoint")) { + port->endpoint = 1; + } else if (!strcmp(val, "pci")) { + port->endpoint = 0; + } else { + printk(KERN_ERR "PCIE: missing or incorrect device_type for %s\n", + np->full_name); + return; + } /* Fetch config space registers address */ if (of_address_to_resource(np, 0, &port->cfg_space)) { -- cgit v1.2.3 From 78be76476a34a77f0ea9db2f78ba46a2b0fd5ab5 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Tue, 6 May 2008 12:37:15 -0500 Subject: [POWERPC] 4xx: Fix PCI mem in sequoia DTS This patch is fixes the sequoia.dts device tree file to use the values defined in the 440Epx data sheet from AMCC. That fixes an issue where some devices, including graphics cards, would not initialize properly because the PCI resource space was not big enough. Signed-off-by: Christian Ehrhardt Signed-off-by: Josh Boyer --- arch/powerpc/boot/dts/sequoia.dts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts index a1ae4d6ec990..72d67564bdfc 100644 --- a/arch/powerpc/boot/dts/sequoia.dts +++ b/arch/powerpc/boot/dts/sequoia.dts @@ -342,9 +342,14 @@ /* Outbound ranges, one memory and one IO, * later cannot be changed. Chip supports a second * IO range but we don't use it for now + * From the 440EPx user manual: + * PCI 1 Memory 1 8000 0000 1 BFFF FFFF 1GB + * I/O 1 E800 0000 1 E800 FFFF 64KB + * I/O 1 E880 0000 1 EBFF FFFF 56MB */ - ranges = <02000000 0 80000000 1 80000000 0 10000000 - 01000000 0 00000000 1 e8000000 0 00100000>; + ranges = <02000000 0 80000000 1 80000000 0 40000000 + 01000000 0 00000000 1 e8000000 0 00010000 + 01000000 0 00000000 1 e8800000 0 03800000>; /* Inbound 2GB range starting at 0 */ dma-ranges = <42000000 0 0 0 0 0 80000000>; -- cgit v1.2.3