diff options
558 files changed, 8315 insertions, 5247 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index db9499adbed..36526a1e76d 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -190,9 +190,13 @@ quiet_cmd_fig2png = FIG2PNG $@ ### # Help targets as used by the top-level makefile dochelp: - @echo ' Linux kernel internal documentation in different formats:' - @echo ' xmldocs (XML DocBook), psdocs (Postscript), pdfdocs (PDF)' - @echo ' htmldocs (HTML), mandocs (man pages, use installmandocs to install)' + @echo ' Linux kernel internal documentation in different formats:' + @echo ' htmldocs - HTML' + @echo ' installmandocs - install man pages generated by mandocs' + @echo ' mandocs - man pages' + @echo ' pdfdocs - PDF' + @echo ' psdocs - Postscript' + @echo ' xmldocs - XML DocBook' ### # Temporary files left by various tools @@ -1,4 +1,4 @@ - Linux kernel release 2.6.xx <http://kernel.org> + Linux kernel release 2.6.xx <http://kernel.org/> These are the release notes for Linux version 2.6. Read them carefully, as they tell you what this is all about, explain how to install the @@ -22,15 +22,17 @@ ON WHAT HARDWARE DOES IT RUN? Although originally developed first for 32-bit x86-based PCs (386 or higher), today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and - UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, + UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell, IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS, - and Renesas M32R architectures. + Cris, Xtensa, AVR32 and Renesas M32R architectures. Linux is easily portable to most general-purpose 32- or 64-bit architectures as long as they have a paged memory management unit (PMMU) and a port of the GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has also been ported to a number of architectures without a PMMU, although functionality is then obviously somewhat limited. + Linux has also been ported to itself. You can now run the kernel as a + userspace application - this is called UserMode Linux (UML). DOCUMENTATION: @@ -113,6 +115,7 @@ INSTALLING the kernel: version 2.6.12.2 and want to jump to 2.6.12.3, you must first reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying the 2.6.12.3 patch. + You can read more on this in Documentation/applying-patches.txt - Make sure you have no stale .o files and dependencies lying around: @@ -161,6 +164,7 @@ CONFIGURING the kernel: only ask you for the answers to new questions. - Alternate configuration commands are: + "make config" Plain text interface. "make menuconfig" Text based color menus, radiolists & dialogs. "make xconfig" X windows (Qt) based configuration tool. "make gconfig" X windows (Gtk) based configuration tool. @@ -303,8 +307,9 @@ IF SOMETHING GOES WRONG: - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump as is, otherwise you will have to use the "ksymoops" program to make - sense of the dump. This utility can be downloaded from - ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops. + sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred). + This utility can be downloaded from + ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ . Alternately you can do the dump lookup by hand: - In debugging dumps like the above, it helps enormously if you can @@ -336,7 +341,7 @@ IF SOMETHING GOES WRONG: If you for some reason cannot do the above (you have a pre-compiled kernel image or similar), telling me as much about your setup as - possible will help. + possible will help. Please read the REPORTING-BUGS document for details. - Alternately, you can use gdb on a running kernel. (read-only; i.e. you cannot change values or set break points.) To do this, first compile the diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 605dedf9679..b3599743093 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -60,16 +60,16 @@ static int sharpsl_ac_check(void); static int sharpsl_fatal_check(void); static int sharpsl_average_value(int ad); static void sharpsl_average_clear(void); -static void sharpsl_charge_toggle(void *private_); -static void sharpsl_battery_thread(void *private_); +static void sharpsl_charge_toggle(struct work_struct *private_); +static void sharpsl_battery_thread(struct work_struct *private_); /* * Variables */ struct sharpsl_pm_status sharpsl_pm; -DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL); -DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL); +DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle); +DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread); DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger); @@ -116,7 +116,7 @@ void sharpsl_battery_kick(void) EXPORT_SYMBOL(sharpsl_battery_kick); -static void sharpsl_battery_thread(void *private_) +static void sharpsl_battery_thread(struct work_struct *private_) { int voltage, percent, apm_status, i = 0; @@ -128,7 +128,7 @@ static void sharpsl_battery_thread(void *private_) /* Corgi cannot confirm when battery fully charged so periodically kick! */ if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) - schedule_work(&toggle_charger); + schedule_delayed_work(&toggle_charger, 0); while(1) { voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); @@ -212,7 +212,7 @@ static void sharpsl_charge_off(void) sharpsl_pm_led(SHARPSL_LED_OFF); sharpsl_pm.charge_mode = CHRG_OFF; - schedule_work(&sharpsl_bat); + schedule_delayed_work(&sharpsl_bat, 0); } static void sharpsl_charge_error(void) @@ -222,7 +222,7 @@ static void sharpsl_charge_error(void) sharpsl_pm.charge_mode = CHRG_ERROR; } -static void sharpsl_charge_toggle(void *private_) +static void sharpsl_charge_toggle(struct work_struct *private_) { dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); @@ -254,7 +254,7 @@ static void sharpsl_ac_timer(unsigned long data) else if (sharpsl_pm.charge_mode == CHRG_ON) sharpsl_charge_off(); - schedule_work(&sharpsl_bat); + schedule_delayed_work(&sharpsl_bat, 0); } @@ -279,10 +279,10 @@ static void sharpsl_chrg_full_timer(unsigned long data) sharpsl_charge_off(); } else if (sharpsl_pm.full_count < 2) { dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n"); - schedule_work(&toggle_charger); + schedule_delayed_work(&toggle_charger, 0); } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) { dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n"); - schedule_work(&toggle_charger); + schedule_delayed_work(&toggle_charger, 0); } else { sharpsl_charge_off(); sharpsl_pm.charge_mode = CHRG_DONE; diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index f225a083dee..9d2346fb68f 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -323,7 +323,8 @@ static int h3_transceiver_mode(struct device *dev, int mode) cancel_delayed_work(&irda_config->gpio_expa); PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); - schedule_work(&irda_config->gpio_expa); +#error this is not permitted - mode is an argument variable + schedule_delayed_work(&irda_config->gpio_expa, 0); return 0; } diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index dbc555d209f..cbe909bad79 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -74,7 +74,7 @@ static struct omap_kp_platform_data nokia770_kp_data = { .rows = 8, .cols = 8, .keymap = nokia770_keymap, - .keymapsize = ARRAY_SIZE(nokia770_keymap) + .keymapsize = ARRAY_SIZE(nokia770_keymap), .delay = 4, }; @@ -191,7 +191,7 @@ static void nokia770_audio_pwr_up(void) printk("HP connected\n"); } -static void codec_delayed_power_down(void *arg) +static void codec_delayed_power_down(struct work_struct *work) { down(&audio_pwr_sem); if (audio_pwr_state == -1) @@ -200,7 +200,7 @@ static void codec_delayed_power_down(void *arg) up(&audio_pwr_sem); } -static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL); +static DECLARE_DELAYED_WORK(codec_power_down_work, codec_delayed_power_down); static void nokia770_audio_pwr_down(void) { diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c index 3b29e59b0e6..0cbf1b0071f 100644 --- a/arch/arm/mach-omap1/leds-osk.c +++ b/arch/arm/mach-omap1/leds-osk.c @@ -35,7 +35,7 @@ static u8 hw_led_state; static u8 tps_leds_change; -static void tps_work(void *unused) +static void tps_work(struct work_struct *unused) { for (;;) { u8 leds; @@ -61,7 +61,7 @@ static void tps_work(void *unused) } } -static DECLARE_WORK(work, tps_work, NULL); +static DECLARE_WORK(work, tps_work); #ifdef CONFIG_OMAP_OSK_MISTRAL diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 26a95a642ad..3b1ad1d981a 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -206,7 +206,8 @@ static int h4_transceiver_mode(struct device *dev, int mode) cancel_delayed_work(&irda_config->gpio_expa); PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); - schedule_work(&irda_config->gpio_expa); +#error this is not permitted - mode is an argument variable + schedule_delayed_work(&irda_config->gpio_expa, 0); return 0; } diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c index 1b398742ab5..12d2fe0ceff 100644 --- a/arch/arm/mach-pxa/akita-ioexp.c +++ b/arch/arm/mach-pxa/akita-ioexp.c @@ -36,11 +36,11 @@ I2C_CLIENT_INSMOD; static int max7310_write(struct i2c_client *client, int address, int data); static struct i2c_client max7310_template; -static void akita_ioexp_work(void *private_); +static void akita_ioexp_work(struct work_struct *private_); static struct device *akita_ioexp_device; static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT; -DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL); +DECLARE_WORK(akita_ioexp, akita_ioexp_work); /* @@ -158,7 +158,7 @@ void akita_reset_ioexp(struct device *dev, unsigned char bit) EXPORT_SYMBOL(akita_set_ioexp); EXPORT_SYMBOL(akita_reset_ioexp); -static void akita_ioexp_work(void *private_) +static void akita_ioexp_work(struct work_struct *private_) { if (akita_ioexp_device) max7310_set_ouputs(akita_ioexp_device, ioexp_output_value); diff --git a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c index 1f9153ae5b0..6b5d3518a1c 100644 --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c @@ -51,10 +51,10 @@ static void mce_checkregs (void *info) } } -static void mce_work_fn(void *data); -static DECLARE_WORK(mce_work, mce_work_fn, NULL); +static void mce_work_fn(struct work_struct *work); +static DECLARE_DELAYED_WORK(mce_work, mce_work_fn); -static void mce_work_fn(void *data) +static void mce_work_fn(struct work_struct *work) { on_each_cpu(mce_checkregs, NULL, 1, 1); schedule_delayed_work(&mce_work, MCE_RATE); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 4bb8b77cd65..02a9b66b6ac 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1049,13 +1049,15 @@ void cpu_exit_clear(void) struct warm_boot_cpu_info { struct completion *complete; + struct work_struct task; int apicid; int cpu; }; -static void __cpuinit do_warm_boot_cpu(void *p) +static void __cpuinit do_warm_boot_cpu(struct work_struct *work) { - struct warm_boot_cpu_info *info = p; + struct warm_boot_cpu_info *info = + container_of(work, struct warm_boot_cpu_info, task); do_boot_cpu(info->apicid, info->cpu); complete(info->complete); } @@ -1064,7 +1066,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu) { DECLARE_COMPLETION_ONSTACK(done); struct warm_boot_cpu_info info; - struct work_struct task; int apicid, ret; struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); @@ -1089,7 +1090,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu) info.complete = &done; info.apicid = apicid; info.cpu = cpu; - INIT_WORK(&task, do_warm_boot_cpu, &info); + INIT_WORK(&info.task, do_warm_boot_cpu); tsc_sync_disabled = 1; @@ -1097,7 +1098,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu) clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, KERNEL_PGD_PTRS); flush_tlb_all(); - schedule_work(&task); + schedule_work(&info.task); wait_for_completion(&done); tsc_sync_disabled = 0; diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index fbc95828cd7..9810c8c9075 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c @@ -217,7 +217,7 @@ static unsigned int cpufreq_delayed_issched = 0; static unsigned int cpufreq_init = 0; static struct work_struct cpufreq_delayed_get_work; -static void handle_cpufreq_delayed_get(void *v) +static void handle_cpufreq_delayed_get(struct work_struct *work) { unsigned int cpu; @@ -306,7 +306,7 @@ static int __init cpufreq_tsc(void) { int ret; - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); if (!ret) diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index caab986af70..b62f0c4d2c7 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -209,7 +209,7 @@ static void do_serial_bh(void) } #endif -static void do_softint(void *private_) +static void do_softint(struct work_struct *private_) { printk(KERN_ERR "simserial: do_softint called\n"); } @@ -698,7 +698,7 @@ static int get_async_struct(int line, struct async_struct **ret_info) info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; - INIT_WORK(&info->work, do_softint, info); + INIT_WORK(&info->work, do_softint); info->state = sstate; if (sstate->info) { kfree(info); diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 7cfa63a98cb..6bedd97570c 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -678,7 +678,7 @@ ia64_mca_cmc_vector_enable (void *dummy) * disable the cmc interrupt vector. */ static void -ia64_mca_cmc_vector_disable_keventd(void *unused) +ia64_mca_cmc_vector_disable_keventd(struct work_struct *unused) { on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 1, 0); } @@ -690,7 +690,7 @@ ia64_mca_cmc_vector_disable_keventd(void *unused) * enable the cmc interrupt vector. */ static void -ia64_mca_cmc_vector_enable_keventd(void *unused) +ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused) { on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0); } @@ -1247,8 +1247,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, monarch_cpu = -1; } -static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL); -static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd, NULL); +static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd); +static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd); /* * ia64_mca_cmc_int_handler diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index f7d7f566814..b21ddecea94 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -463,15 +463,17 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs) } struct create_idle { + struct work_struct work; struct task_struct *idle; struct completion done; int cpu; }; void -do_fork_idle(void *_c_idle) +do_fork_idle(struct work_struct *work) { - struct create_idle *c_idle = _c_idle; + struct create_idle *c_idle = + container_of(work, struct create_idle, work); c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); @@ -482,10 +484,10 @@ do_boot_cpu (int sapicid, int cpu) { int timeout; struct create_idle c_idle = { + .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, .done = COMPLETION_INITIALIZER(c_idle.done), }; - DECLARE_WORK(work, do_fork_idle, &c_idle); c_idle.idle = get_idle_for_cpu(cpu); if (c_idle.idle) { @@ -497,9 +499,9 @@ do_boot_cpu (int sapicid, int cpu) * We can't use kernel_thread since we must avoid to reschedule the child. */ if (!keventd_up() || current_is_keventd()) - work.func(work.data); + c_idle.work.func(&c_idle.work); else { - schedule_work(&work); + schedule_work(&c_idle.work); wait_for_completion(&c_idle.done); } diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index f4edfbf2713..eb92cef9cd0 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -564,8 +564,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask) void pcibios_disable_device (struct pci_dev *dev) { - if (dev->is_enabled) - acpi_pci_irq_disable(dev); + BUG_ON(atomic_read(&dev->enable_cnt)); + acpi_pci_irq_disable(dev); } void diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c index 24781f00933..e5668af1978 100644 --- a/arch/m68knommu/platform/5307/timers.c +++ b/arch/m68knommu/platform/5307/timers.c @@ -3,7 +3,7 @@ /* * timers.c -- generic ColdFire hardware timer support. * - * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1999-2006, Greg Ungerer (gerg@snapgear.com) */ /***************************************************************************/ @@ -44,6 +44,14 @@ unsigned int mcf_timerlevel = 5; extern void mcf_settimericr(int timer, int level); extern int mcf_timerirqpending(int timer); +#if defined(CONFIG_M532x) +#define __raw_readtrr __raw_readl +#define __raw_writetrr __raw_writel +#else +#define __raw_readtrr __raw_readw +#define __raw_writetrr __raw_writew +#endif + /***************************************************************************/ void coldfire_tick(void) @@ -57,7 +65,7 @@ void coldfire_tick(void) void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) { __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); - __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); + __raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); @@ -76,7 +84,7 @@ unsigned long coldfire_timer_offset(void) unsigned long trr, tcn, offset; tcn = __raw_readw(TA(MCFTIMER_TCN)); - trr = __raw_readw(TA(MCFTIMER_TRR)); + trr = __raw_readtrr(TA(MCFTIMER_TRR)); offset = (tcn * (1000000 / HZ)) / trr; /* Check if we just wrapped the counters and maybe missed a tick */ @@ -120,7 +128,7 @@ void coldfire_profile_init(void) /* Set up TIMER 2 as high speed profile clock */ __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); - __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); + __raw_writetrr(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); diff --git a/arch/m68knommu/platform/68360/config.c b/arch/m68knommu/platform/68360/config.c index c5482e3622e..1b36f626176 100644 --- a/arch/m68knommu/platform/68360/config.c +++ b/arch/m68knommu/platform/68360/config.c @@ -114,7 +114,7 @@ void BSP_gettod (int *yearp, int *monp, int *dayp, { } -int BSP_hwclk(int op, struct hwclk_time *t) +int BSP_hwclk(int op, struct rtc_time *t) { if (!op) { /* read */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4d64960be03..d8af858fe3f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -242,6 +242,7 @@ config LASAT select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config MIPS_ATLAS bool "MIPS Atlas board" @@ -265,6 +266,7 @@ config MIPS_ATLAS select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_MULTITHREADING if EXPERIMENTAL + select GENERIC_HARDIRQS_NO__DO_IRQ help This enables support for the MIPS Technologies Atlas evaluation board. @@ -419,6 +421,7 @@ config MOMENCO_OCELOT_C select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer <http://www.momenco.com/>. @@ -569,6 +572,7 @@ config SGI_IP27 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_SMP + select GENERIC_HARDIRQS_NO__DO_IRQ help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -835,6 +839,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER bool default y +config GENERIC_HARDIRQS_NO__DO_IRQ + bool + default n + # # Select some configuration options automatically based on user selections. # @@ -996,6 +1004,7 @@ config SOC_PNX8550 select HW_HAS_PCI select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL + select GENERIC_HARDIRQS_NO__DO_IRQ config SWAP_IO_SPACE bool diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c index c8430c07355..6d55e8aab66 100644 --- a/arch/mips/dec/ecc-berr.c +++ b/arch/mips/dec/ecc-berr.c @@ -25,6 +25,7 @@ #include <asm/cpu.h> #include <asm/irq_regs.h> #include <asm/processor.h> +#include <asm/ptrace.h> #include <asm/system.h> #include <asm/traps.h> diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c index 269b22b3431..4c7cb4048d3 100644 --- a/arch/mips/dec/ioasic-irq.c +++ b/arch/mips/dec/ioasic-irq.c @@ -67,7 +67,6 @@ static struct irq_chip ioasic_irq_type = { .mask = mask_ioasic_irq, .mask_ack = ack_ioasic_irq, .unmask = unmask_ioasic_irq, - .end = end_ioasic_irq, }; @@ -106,8 +105,7 @@ void __init init_ioasic_irqs(int base) set_irq_chip_and_handler(i, &ioasic_irq_type, handle_level_irq); for (; i < base + IO_IRQ_LINES; i++) - set_irq_chip_and_handler(i, &ioasic_dma_irq_type, - handle_level_irq); + set_irq_chip(i, &ioasic_dma_irq_type); ioasic_irq_base = base; } diff --git a/arch/mips/dec/kn01-berr.c b/arch/mips/dec/kn01-berr.c index f19b4617a0a..d3b8002bf1e 100644 --- a/arch/mips/dec/kn01-berr.c +++ b/arch/mips/dec/kn01-berr.c @@ -20,8 +20,10 @@ #include <linux/types.h> #include <asm/inst.h> +#include <asm/irq_regs.h> #include <asm/mipsregs.h> #include <asm/page.h> +#include <asm/ptrace.h> #include <asm/system.h> #include <asm/traps.h> #include <asm/uaccess.h> diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c index 5a9be4c9358..916e46b8ccd 100644 --- a/arch/mips/dec/kn02-irq.c +++ b/arch/mips/dec/kn02-irq.c @@ -57,19 +57,12 @@ static void ack_kn02_irq(unsigned int irq) iob(); } -static void end_kn02_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_kn02_irq(irq); -} - static struct irq_chip kn02_irq_type = { .typename = "KN02-CSR", .ack = ack_kn02_irq, .mask = mask_kn02_irq, .mask_ack = ack_kn02_irq, .unmask = unmask_kn02_irq, - .end = end_kn02_irq, }; diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c index 59b98299c89..8d880f0b06e 100644 --- a/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -56,19 +56,12 @@ static void emma2rh_irq_disable(unsigned int irq) ll_emma2rh_irq_disable(irq - emma2rh_irq_base); } -static void emma2rh_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - ll_emma2rh_irq_enable(irq - emma2rh_irq_base); -} - struct irq_chip emma2rh_irq_controller = { .typename = "emma2rh_irq", .ack = emma2rh_irq_disable, .mask = emma2rh_irq_disable, .mask_ack = emma2rh_irq_disable, .unmask = emma2rh_irq_enable, - .end = emma2rh_irq_end, }; void emma2rh_irq_init(u32 irq_base) diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c index 3ac4e405ecd..2116d9be5fa 100644 --- a/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -48,19 +48,12 @@ static void emma2rh_sw_irq_disable(unsigned int irq) ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); } -static void emma2rh_sw_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base); -} - struct irq_chip emma2rh_sw_irq_controller = { .typename = "emma2rh_sw_irq", .ack = emma2rh_sw_irq_disable, .mask = emma2rh_sw_irq_disable, .mask_ack = emma2rh_sw_irq_disable, .unmask = emma2rh_sw_irq_enable, - .end = emma2rh_sw_irq_end, }; void emma2rh_sw_irq_init(u32 irq_base) diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index 5c4f50cdf15..f8d417b5c2b 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -39,19 +39,12 @@ void disable_r4030_irq(unsigned int irq) spin_unlock_irqrestore(&r4030_lock, flags); } -static void end_r4030_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_r4030_irq(irq); -} - static struct irq_chip r4030_irq_type = { .typename = "R4030", .ack = disable_r4030_irq, .mask = disable_r4030_irq, .mask_ack = disable_r4030_irq, .unmask = enable_r4030_irq, - .end = end_r4030_irq, }; void __init init_r4030_ints(void) diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 2526c0ca4d8..b59a676c6d0 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -19,9 +19,6 @@ #include <asm/i8259.h> #include <asm/io.h> -void enable_8259A_irq(unsigned int irq); -void disable_8259A_irq(unsigned int irq); - /* * This is the 'legacy' 8259A Programmable Interrupt Controller, * present in the majority of PC/AT boxes. @@ -31,23 +28,16 @@ void disable_8259A_irq(unsigned int irq); * moves to arch independent land */ +static int i8259A_auto_eoi; DEFINE_SPINLOCK(i8259A_lock); - -static void end_8259A_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && - irq_desc[irq].action) - enable_8259A_irq(irq); -} - +/* some platforms call this... */ void mask_and_ack_8259A(unsigned int); -static struct irq_chip i8259A_irq_type = { - .typename = "XT-PIC", - .enable = enable_8259A_irq, - .disable = disable_8259A_irq, - .ack = mask_and_ack_8259A, - .end = end_8259A_irq, +static struct irq_chip i8259A_chip = { + .name = "XT-PIC", + .mask = disable_8259A_irq, + .unmask = enable_8259A_irq, + .mask_ack = mask_and_ack_8259A, }; /* @@ -59,8 +49,8 @@ static struct irq_chip i8259A_irq_type = { */ static unsigned int cached_irq_mask = 0xffff; -#define cached_21 (cached_irq_mask) -#define cached_A1 (cached_irq_mask >> 8) +#define cached_master_mask (cached_irq_mask) +#define cached_slave_mask (cached_irq_mask >> 8) void disable_8259A_irq(unsigned int irq) { @@ -70,9 +60,9 @@ void disable_8259A_irq(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask |= mask; if (irq & 8) - outb(cached_A1,0xA1); + outb(cached_slave_mask, PIC_SLAVE_IMR); else - outb(cached_21,0x21); + outb(cached_master_mask, PIC_MASTER_IMR); spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -84,9 +74,9 @@ void enable_8259A_irq(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask &= mask; if (irq & 8) - outb(cached_A1,0xA1); + outb(cached_slave_mask, PIC_SLAVE_IMR); else - outb(cached_21,0x21); + outb(cached_master_mask, PIC_MASTER_IMR); spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -98,9 +88,9 @@ int i8259A_irq_pending(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); if (irq < 8) - ret = inb(0x20) & mask; + ret = inb(PIC_MASTER_CMD) & mask; else - ret = inb(0xA0) & (mask >> 8); + ret = inb(PIC_SLAVE_CMD) & (mask >> 8); spin_unlock_irqrestore(&i8259A_lock, flags); return ret; @@ -109,7 +99,7 @@ int i8259A_irq_pending(unsigned int irq) void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); - set_irq_chip(irq, &i8259A_irq_type); + set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq); enable_irq(irq); } @@ -125,14 +115,14 @@ static inline int i8259A_irq_real(unsigned int irq) int irqmask = 1 << irq; if (irq < 8) { - outb(0x0B,0x20); /* ISR register */ - value = inb(0x20) & irqmask; - outb(0x0A,0x20); /* back to the IRR register */ + outb(0x0B,PIC_MASTER_CMD); /* ISR register */ + value = inb(PIC_MASTER_CMD) & irqmask; + outb(0x0A,PIC_MASTER_CMD); /* back to the IRR register */ return value; } - outb(0x0B,0xA0); /* ISR register */ - value = inb(0xA0) & (irqmask >> 8); - outb(0x0A,0xA0); /* back to the IRR register */ + outb(0x0B,PIC_SLAVE_CMD); /* ISR register */ + value = inb(PIC_SLAVE_CMD) & (irqmask >> 8); + outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */ return value; } @@ -149,17 +139,19 @@ void mask_and_ack_8259A(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); /* - * Lightweight spurious IRQ detection. We do not want to overdo - * spurious IRQ handling - it's usually a sign of hardware problems, so - * we only do the checks we can do without slowing down good hardware - * nnecesserily. + * Lightweight spurious IRQ detection. We do not want + * to overdo spurious IRQ handling - it's usually a sign + * of hardware problems, so we only do the checks we can + * do without slowing down good hardware unnecessarily. * - * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting - * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A. - * Thus we can check spurious 8259A IRQs without doing the quite slow - * i8259A_irq_real() call for every IRQ. This does not cover 100% of - * spurious interrupts, but should be enough to warn the user that - * there is something bad going on ... + * Note that IRQ7 and IRQ15 (the two spurious IRQs + * usually resulting from the 8259A-1|2 PICs) occur + * even if the IRQ is masked in the 8259A. Thus we + * can check spurious 8259A IRQs without doing the + * quite slow i8259A_irq_real() call for every IRQ. + * This does not cover 100% of spurious interrupts, + * but should be enough to warn the user that there + * is something bad going on ... */ if (cached_irq_mask & irqmask) goto spurious_8259A_irq; @@ -167,14 +159,14 @@ void mask_and_ack_8259A(unsigned int irq) handle_real_irq: if (irq & 8) { - inb(0xA1); /* DUMMY - (do we need this?) */ - outb(cached_A1,0xA1); - outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */ - outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ + inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */ + outb(cached_slave_mask, PIC_SLAVE_IMR); + outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */ + outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */ } else { - inb(0x21); /* DUMMY - (do we need this?) */ - outb(cached_21,0x21); - outb(0x60+irq,0x20); /* 'Specific EOI' to master */ + inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */ + outb(cached_master_mask, PIC_MASTER_IMR); + outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */ } #ifdef CONFIG_MIPS_MT_SMTC if (irq_hwmask[irq] & ST0_IM) @@ -195,7 +187,7 @@ spurious_8259A_irq: goto handle_real_irq; { - static int spurious_irq_mask = 0; + static int spurious_irq_mask; /* * At this point we can be sure the IRQ is spurious, * lets ACK and report it. [once per IRQ] @@ -216,13 +208,25 @@ spurious_8259A_irq: static int i8259A_resume(struct sys_device *dev) { - init_8259A(0); + init_8259A(i8259A_auto_eoi); + return 0; +} + +static int i8259A_shutdown(struct sys_device *dev) +{ + /* Put the i8259A into a quiescent state that + * the kernel initialization code can get it + * out of. + */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ return 0; } static struct sysdev_class i8259_sysdev_class = { set_kset_name("i8259"), .resume = i8259A_resume, + .shutdown = i8259A_shutdown, }; static struct sys_device device_i8259A = { @@ -244,41 +248,41 @@ void __init init_8259A(int auto_eoi) { unsigned long flags; + i8259A_auto_eoi = auto_eoi; + spin_lock_irqsave(&i8259A_lock, flags); - outb(0xff, 0x21); /* mask all of 8259A-1 */ - outb(0xff, 0xA1); /* mask all of 8259A-2 */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ /* * outb_p - this has to work on a wide range of PC hardware. */ - outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ - outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */ - outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ - if (auto_eoi) - outb_p(0x03, 0x21); /* master does Auto EOI */ - else - outb_p(0x01, 0x21); /* master expects normal EOI */ - - outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ - outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */ - outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ - outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode - is to be investigated) */ - + outb_p(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */ + outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0 mapped to I8259A_IRQ_BASE + 0x00 */ + outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */ + if (auto_eoi) /* master does Auto EOI */ + outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR); + else /* master expects normal EOI */ + outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR); + + outb_p(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */ + outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0 mapped to I8259A_IRQ_BASE + 0x08 */ + outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */ + outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */ if (auto_eoi) /* - * in AEOI mode we just have to mask the interrupt + * In AEOI mode we just have to mask the interrupt * when acking. */ - i8259A_irq_type.ack = disable_8259A_irq; + i8259A_chip.mask_ack = disable_8259A_irq; else - i8259A_irq_type.ack = mask_and_ack_8259A; + i8259A_chip.mask_ack = mask_and_ack_8259A; udelay(100); /* wait for 8259A to initialize */ - outb(cached_21, 0x21); /* restore master IRQ mask */ - outb(cached_A1, 0xA1); /* restore slave IRQ mask */ + outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ + outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -291,11 +295,17 @@ static struct irqaction irq2 = { }; static struct resource pic1_io_resource = { - .name = "pic1", .start = 0x20, .end = 0x21, .flags = IORESOURCE_BUSY + .name = "pic1", + .start = PIC_MASTER_CMD, + .end = PIC_MASTER_IMR, + .flags = IORESOURCE_BUSY }; static struct resource pic2_io_resource = { - .name = "pic2", .start = 0xa0, .end = 0xa1, .flags = IORESOURCE_BUSY + .name = "pic2", + .start = PIC_SLAVE_CMD, + .end = PIC_SLAVE_IMR, + .flags = IORESOURCE_BUSY }; /* @@ -313,7 +323,7 @@ void __init init_i8259_irqs (void) init_8259A(0); for (i = 0; i < 16; i++) - set_irq_chip(i, &i8259A_irq_type); + set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq); - setup_irq(2, &irq2); + setup_irq(PIC_CASCADE_IR, &irq2); } diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c index 6cfb31cafde..efbd219845b 100644 --- a/arch/mips/kernel/irq-mv6434x.c +++ b/arch/mips/kernel/irq-mv6434x.c @@ -67,15 +67,6 @@ static inline void unmask_mv64340_irq(unsigned int irq) } /* - * End IRQ processing - */ -static void end_mv64340_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_mv64340_irq(irq); -} - -/* * Interrupt handler for interrupts coming from the Marvell chip. * It could be built in ethernet ports etc... */ @@ -106,7 +97,6 @@ struct irq_chip mv64340_irq_type = { .mask = mask_mv64340_irq, .mask_ack = mask_mv64340_irq, .unmask = unmask_mv64340_irq, - .end = end_mv64340_irq, }; void __init mv64340_irq_init(unsigned int base) diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c index ddcc2a5f8a0..123324ba8c1 100644 --- a/arch/mips/kernel/irq-rm7000.c +++ b/arch/mips/kernel/irq-rm7000.c @@ -29,19 +29,12 @@ static inline void mask_rm7k_irq(unsigned int irq) clear_c0_intcontrol(0x100 << (irq - irq_base)); } -static void rm7k_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_rm7k_irq(irq); -} - static struct irq_chip rm7k_irq_controller = { .typename = "RM7000", .ack = mask_rm7k_irq, .mask = mask_rm7k_irq, .mask_ack = mask_rm7k_irq, .unmask = unmask_rm7k_irq, - .end = rm7k_cpu_irq_end, }; void __init rm7k_cpu_irq_init(int base) diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c index ba6440c88ab..0e6f4c5349d 100644 --- a/arch/mips/kernel/irq-rm9000.c +++ b/arch/mips/kernel/irq-rm9000.c @@ -80,19 +80,12 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq) on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1); } -static void rm9k_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_rm9k_irq(irq); -} - static struct irq_chip rm9k_irq_controller = { .typename = "RM9000", .ack = mask_rm9k_irq, .mask = mask_rm9k_irq, .mask_ack = mask_rm9k_irq, .unmask = unmask_rm9k_irq, - .end = rm9k_cpu_irq_end, }; static struct irq_chip rm9k_perfcounter_irq = { @@ -103,7 +96,6 @@ static struct irq_chip rm9k_perfcounter_irq = { .mask = mask_rm9k_irq, .mask_ack = mask_rm9k_irq, .unmask = unmask_rm9k_irq, - .end = rm9k_cpu_irq_end, }; unsigned int rm9000_perfcount_irq; diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index b339798b317..2fe4c868a80 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -117,7 +117,7 @@ int show_interrupts(struct seq_file *p, void *v) for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif - seq_printf(p, " %14s", irq_desc[i].chip->typename); + seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index be5ac23d381..fcc86b96ccf 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -50,12 +50,6 @@ static inline void mask_mips_irq(unsigned int irq) irq_disable_hazard(); } -static void mips_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_mips_irq(irq); -} - static struct irq_chip mips_cpu_irq_controller = { .typename = "MIPS", .ack = mask_mips_irq, @@ -63,7 +57,6 @@ static struct irq_chip mips_cpu_irq_controller = { .mask_ack = mask_mips_irq, .unmask = unmask_mips_irq, .eoi = unmask_mips_irq, - .end = mips_cpu_irq_end, }; /* @@ -96,8 +89,6 @@ static void mips_mt_cpu_irq_ack(unsigned int irq) mask_mips_mt_irq(irq); } -#define mips_mt_cpu_irq_end mips_cpu_irq_end - static struct irq_chip mips_mt_cpu_irq_controller = { .typename = "MIPS", .startup = mips_mt_cpu_irq_startup, @@ -106,7 +97,6 @@ static struct irq_chip mips_mt_cpu_irq_controller = { .mask_ack = mips_mt_cpu_irq_ack, .unmask = unmask_mips_mt_irq, .eoi = unmask_mips_mt_irq, - .end = mips_mt_cpu_irq_end, }; void __init mips_cpu_irq_init(int irq_base) diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index f06a144c788..2c82412b9ef 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -319,7 +319,7 @@ static void sp_cleanup(void) static int channel_open = 0; /* the work handler */ -static void sp_work(void *data) +static void sp_work(struct work_struct *unused) { if (!channel_open) { if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) { @@ -354,7 +354,7 @@ static void startwork(int vpe) return; } - INIT_WORK(&work, sp_work, NULL); + INIT_WORK(&work, sp_work); queue_work(workqueue, &work); } else queue_work(workqueue, &work); diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index 4a84a7beac5..2affa5ff171 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -44,19 +44,12 @@ void enable_lasat_irq(unsigned int irq_nr) *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; } -static void end_lasat_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_lasat_irq(irq); -} - static struct irq_chip lasat_irq_type = { .typename = "Lasat", .ack = disable_lasat_irq, .mask = disable_lasat_irq, .mask_ack = disable_lasat_irq, .unmask = enable_lasat_irq, - .end = end_lasat_irq, }; static inline int ls1bit32(unsigned int x) diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c index e5a4a0a8a7f..bb11fef0847 100644 --- a/arch/mips/momentum/ocelot_c/cpci-irq.c +++ b/arch/mips/momentum/ocelot_c/cpci-irq.c @@ -66,15 +66,6 @@ static inline void unmask_cpci_irq(unsigned int irq) } /* - * End IRQ processing - */ -static void end_cpci_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_cpci_irq(irq); -} - -/* * Interrupt handler for interrupts coming from the FPGA chip. * It could be built in ethernet ports etc... */ @@ -98,7 +89,6 @@ struct irq_chip cpci_irq_type = { .mask = mask_cpci_irq, .mask_ack = mask_cpci_irq, .unmask = unmask_cpci_irq, - .end = end_cpci_irq, }; void cpci_irq_init(void) diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c index 0029f0008de..a7a80c0da56 100644 --- a/arch/mips/momentum/ocelot_c/uart-irq.c +++ b/arch/mips/momentum/ocelot_c/uart-irq.c @@ -60,15 +60,6 @@ static inline void unmask_uart_irq(unsigned int irq) } /* - * End IRQ processing - */ -static void end_uart_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_uart_irq(irq); -} - -/* * Interrupt handler for interrupts coming from the FPGA chip. */ void ll_uart_irq(void) @@ -91,7 +82,6 @@ struct irq_chip uart_irq_type = { .mask = mask_uart_irq, .mask_ack = mask_uart_irq, .unmask = unmask_uart_irq, - .end = end_uart_irq, }; void uart_irq_init(void) diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c index 0dc23930edb..2c36c108c4d 100644 --- a/arch/mips/philips/pnx8550/common/int.c +++ b/arch/mips/philips/pnx8550/common/int.c @@ -158,20 +158,12 @@ int pnx8550_set_gic_priority(int irq, int priority) return prev_priority; } -static void end_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { - unmask_irq(irq); - } -} - static struct irq_chip level_irq_type = { .typename = "PNX Level IRQ", .ack = mask_irq, .mask = mask_irq, .mask_ack = mask_irq, .unmask = unmask_irq, - .end = end_irq, }; static struct irqaction gic_action = { diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index c7b13805315..c44f8be0644 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -51,19 +51,12 @@ static void disable_local0_irq(unsigned int irq) sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); } -static void end_local0_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local0_irq(irq); -} - static struct irq_chip ip22_local0_irq_type = { .typename = "IP22 local 0", .ack = disable_local0_irq, .mask = disable_local0_irq, .mask_ack = disable_local0_irq, .unmask = enable_local0_irq, - .end = end_local0_irq, }; static void enable_local1_irq(unsigned int irq) @@ -79,19 +72,12 @@ void disable_local1_irq(unsigned int irq) sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1)); } -static void end_local1_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local1_irq(irq); -} - static struct irq_chip ip22_local1_irq_type = { .typename = "IP22 local 1", .ack = disable_local1_irq, .mask = disable_local1_irq, .mask_ack = disable_local1_irq, .unmask = enable_local1_irq, - .end = end_local1_irq, }; static void enable_local2_irq(unsigned int irq) @@ -107,19 +93,12 @@ void disable_local2_irq(unsigned int irq) sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); } -static void end_local2_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local2_irq(irq); -} - static struct irq_chip ip22_local2_irq_type = { .typename = "IP22 local 2", .ack = disable_local2_irq, .mask = disable_local2_irq, .mask_ack = disable_local2_irq, .unmask = enable_local2_irq, - .end = end_local2_irq, }; static void enable_local3_irq(unsigned int irq) @@ -135,19 +114,12 @@ void disable_local3_irq(unsigned int irq) sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); } -static void end_local3_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local3_irq(irq); -} - static struct irq_chip ip22_local3_irq_type = { .typename = "IP22 local 3", .ack = disable_local3_irq, .mask = disable_local3_irq, .mask_ack = disable_local3_irq, .unmask = enable_local3_irq, - .end = end_local3_irq, }; static void indy_local0_irqdispatch(void) diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 5f8835b4e84..319f8803ef6 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -332,13 +332,6 @@ static inline void disable_bridge_irq(unsigned int irq) intr_disconnect_level(cpu, swlevel); } -static void end_bridge_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && - irq_desc[irq].action) - enable_bridge_irq(irq); -} - static struct irq_chip bridge_irq_type = { .typename = "bridge", .startup = startup_bridge_irq, @@ -347,7 +340,6 @@ static struct irq_chip bridge_irq_type = { .mask = disable_bridge_irq, .mask_ack = disable_bridge_irq, .unmask = enable_bridge_irq, - .end = end_bridge_irq, }; void __devinit register_bridge_irq(unsigned int irq) diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 7d361726bbf..c20e9899b34 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -180,10 +180,6 @@ static void disable_rt_irq(unsigned int irq) { } -static void end_rt_irq(unsigned int irq) -{ -} - static struct irq_chip rt_irq_type = { .typename = "SN HUB RT timer", .ack = disable_rt_irq, @@ -191,7 +187,6 @@ static struct irq_chip rt_irq_type = { .mask_ack = disable_rt_irq, .unmask = enable_rt_irq, .eoi = enable_rt_irq, - .end = end_rt_irq, }; static struct irqaction rt_irqaction = { diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c index 21873de49aa..ed4a19adf36 100644 --- a/arch/mips/tx4927/common/tx4927_irq.c +++ b/arch/mips/tx4927/common/tx4927_irq.c @@ -66,12 +66,10 @@ #define TX4927_IRQ_CP0_INIT ( 1 << 10 ) #define TX4927_IRQ_CP0_ENABLE ( 1 << 13 ) #define TX4927_IRQ_CP0_DISABLE ( 1 << 14 ) -#define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 ) #define TX4927_IRQ_PIC_INIT ( 1 << 20 ) #define TX4927_IRQ_PIC_ENABLE ( 1 << 23 ) #define TX4927_IRQ_PIC_DISABLE ( 1 << 24 ) -#define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 ) #define TX4927_IRQ_ALL 0xffffffff #endif @@ -82,12 +80,10 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE | TX4927_IRQ_WARN | TX4927_IRQ_EROR // | TX4927_IRQ_CP0_INIT // | TX4927_IRQ_CP0_ENABLE -// | TX4927_IRQ_CP0_DISABLE // | TX4927_IRQ_CP0_ENDIRQ // | TX4927_IRQ_PIC_INIT // | TX4927_IRQ_PIC_ENABLE // | TX4927_IRQ_PIC_DISABLE -// | TX4927_IRQ_PIC_ENDIRQ // | TX4927_IRQ_INIT // | TX4927_IRQ_NEST1 // | TX4927_IRQ_NEST2 @@ -114,11 +110,9 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE static void tx4927_irq_cp0_enable(unsigned int irq); static void tx4927_irq_cp0_disable(unsigned int irq); -static void tx4927_irq_cp0_end(unsigned int irq); static void tx4927_irq_pic_enable(unsigned int irq); static void tx4927_irq_pic_disable(unsigned int irq); -static void tx4927_irq_pic_end(unsigned int irq); /* * Kernel structs for all pic's @@ -131,7 +125,6 @@ static struct irq_chip tx4927_irq_cp0_type = { .mask = tx4927_irq_cp0_disable, .mask_ack = tx4927_irq_cp0_disable, .unmask = tx4927_irq_cp0_enable, - .end = tx4927_irq_cp0_end, }; #define TX4927_PIC_NAME "TX4927-PIC" @@ -141,7 +134,6 @@ static struct irq_chip tx4927_irq_pic_type = { .mask = tx4927_irq_pic_disable, .mask_ack = tx4927_irq_pic_disable, .unmask = tx4927_irq_pic_enable, - .end = tx4927_irq_pic_end, }; #define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL } @@ -214,15 +206,6 @@ static void tx4927_irq_cp0_disable(unsigned int irq) tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0); } -static void tx4927_irq_cp0_end(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq); - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4927_irq_cp0_enable(irq); - } -} - /* * Functions for pic */ @@ -376,15 +359,6 @@ static void tx4927_irq_pic_disable(unsigned int irq) tx4927_irq_pic_mask(irq), 0); } -static void tx4927_irq_pic_end(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq); - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4927_irq_pic_enable(irq); - } -} - /* * Main init functions */ diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index 34cdb2a240e..5a5ea6c0b9f 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -153,7 +153,6 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB #define TOSHIBA_RBTX4927_IRQ_IOC_INIT ( 1 << 10 ) #define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE ( 1 << 13 ) #define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE ( 1 << 14 ) -#define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ ( 1 << 16 ) #define TOSHIBA_RBTX4927_IRQ_ISA_INIT ( 1 << 20 ) #define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 ) @@ -172,7 +171,6 @@ static const u32 toshiba_rbtx4927_irq_debug_flag = // | TOSHIBA_RBTX4927_IRQ_IOC_INIT // | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE // | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE -// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ // | TOSHIBA_RBTX4927_IRQ_ISA_INIT // | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE // | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE @@ -223,7 +221,6 @@ extern void mask_and_ack_8259A(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq); -static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq); #ifdef CONFIG_TOSHIBA_FPCIB0 static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq); @@ -239,7 +236,6 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { .mask = toshiba_rbtx4927_irq_ioc_disable, .mask_ack = toshiba_rbtx4927_irq_ioc_disable, .unmask = toshiba_rbtx4927_irq_ioc_enable, - .end = toshiba_rbtx4927_irq_ioc_end, }; #define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000 #define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006 @@ -388,23 +384,6 @@ static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq) TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v); } -static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG - || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - toshiba_rbtx4927_irq_ioc_enable(irq); - } -} - /**********************************************************************************/ /* Functions for isa */ diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c index 42e127683ae..a347b424d91 100644 --- a/arch/mips/tx4938/common/irq.c +++ b/arch/mips/tx4938/common/irq.c @@ -39,11 +39,9 @@ static void tx4938_irq_cp0_enable(unsigned int irq); static void tx4938_irq_cp0_disable(unsigned int irq); -static void tx4938_irq_cp0_end(unsigned int irq); static void tx4938_irq_pic_enable(unsigned int irq); static void tx4938_irq_pic_disable(unsigned int irq); -static void tx4938_irq_pic_end(unsigned int irq); /**********************************************************************************/ /* Kernel structs for all pic's */ @@ -56,7 +54,6 @@ static struct irq_chip tx4938_irq_cp0_type = { .mask = tx4938_irq_cp0_disable, .mask_ack = tx4938_irq_cp0_disable, .unmask = tx4938_irq_cp0_enable, - .end = tx4938_irq_cp0_end, }; #define TX4938_PIC_NAME "TX4938-PIC" @@ -66,7 +63,6 @@ static struct irq_chip tx4938_irq_pic_type = { .mask = tx4938_irq_pic_disable, .mask_ack = tx4938_irq_pic_disable, .unmask = tx4938_irq_pic_enable, - .end = tx4938_irq_pic_end, }; static struct irqaction tx4938_irq_pic_action = { @@ -104,14 +100,6 @@ tx4938_irq_cp0_disable(unsigned int irq) clear_c0_status(tx4938_irq_cp0_mask(irq)); } -static void -tx4938_irq_cp0_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4938_irq_cp0_enable(irq); - } -} - /**********************************************************************************/ /* Functions for pic */ /**********************************************************************************/ @@ -269,14 +257,6 @@ tx4938_irq_pic_disable(unsigned int irq) tx4938_irq_pic_mask(irq), 0); } -static void -tx4938_irq_pic_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4938_irq_pic_enable(irq); - } -} - /**********************************************************************************/ /* Main init functions */ /**********************************************************************************/ diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 8c87a35f306..b6f363d0801 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -89,7 +89,6 @@ IRQ Device static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq); static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq); -static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq); #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { @@ -98,7 +97,6 @@ static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { .mask = toshiba_rbtx4938_irq_ioc_disable, .mask_ack = toshiba_rbtx4938_irq_ioc_disable, .unmask = toshiba_rbtx4938_irq_ioc_enable, - .end = toshiba_rbtx4938_irq_ioc_end, }; #define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000 @@ -167,14 +165,6 @@ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq) TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); } -static void -toshiba_rbtx4938_irq_ioc_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - toshiba_rbtx4938_irq_ioc_enable(irq); - } -} - extern void __init txx9_spi_irqinit(int irc_irq); void __init arch_init_irq(void) diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig index 92f41f6f934..c8dfd8092ca 100644 --- a/arch/mips/vr41xx/Kconfig +++ b/arch/mips/vr41xx/Kconfig @@ -6,6 +6,7 @@ config CASIO_E55 select ISA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config IBM_WORKPAD bool "Support for IBM WorkPad z50" @@ -15,6 +16,7 @@ config IBM_WORKPAD select ISA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config NEC_CMBVR4133 bool "Support for NEC CMB-VR4133" @@ -39,6 +41,7 @@ config TANBAC_TB022X select IRQ_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ help The TANBAC VR4131 multichip module(TB0225) and the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms @@ -71,6 +74,7 @@ config VICTOR_MPC30X select IRQ_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config ZAO_CAPCELLA bool "Support for ZAO Networks Capcella" @@ -80,6 +84,7 @@ config ZAO_CAPCELLA select IRQ_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config PCI_VR41XX bool "Add PCI control unit support of NEC VR4100 series" diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 54b92a74c7a..c075261976c 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -427,19 +427,12 @@ static void enable_sysint1_irq(unsigned int irq) icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); } -static void end_sysint1_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); -} - static struct irq_chip sysint1_irq_type = { .typename = "SYSINT1", .ack = disable_sysint1_irq, .mask = disable_sysint1_irq, .mask_ack = disable_sysint1_irq, .unmask = enable_sysint1_irq, - .end = end_sysint1_irq, }; static void disable_sysint2_irq(unsigned int irq) @@ -452,19 +445,12 @@ static void enable_sysint2_irq(unsigned int irq) icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); } -static void end_sysint2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); -} - static struct irq_chip sysint2_irq_type = { .typename = "SYSINT2", .ack = disable_sysint2_irq, .mask = disable_sysint2_irq, .mask_ack = disable_sysint2_irq, .unmask = enable_sysint2_irq, - .end = end_sysint2_irq, }; static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c index 31bcdae8482..0e837762cc5 100644 --- a/arch/powerpc/platforms/embedded6xx/ls_uart.c +++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c @@ -14,7 +14,7 @@ static unsigned long avr_clock; static struct work_struct wd_work; -static void wd_stop(void *unused) +static void wd_stop(struct work_struct *unused) { const char string[] = "AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK"; int i = 0, rescue = 8; @@ -122,7 +122,7 @@ static int __init ls_uarts_init(void) ls_uart_init(); - INIT_WORK(&wd_work, wd_stop, NULL); + INIT_WORK(&wd_work, wd_stop); schedule_work(&wd_work); return 0; diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index afa593a8544..c3a89414ddc 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c @@ -18,11 +18,11 @@ #define OLD_BACKLIGHT_MAX 15 -static void pmac_backlight_key_worker(void *data); -static void pmac_backlight_set_legacy_worker(void *data); +static void pmac_backlight_key_worker(struct work_struct *work); +static void pmac_backlight_set_legacy_worker(struct work_struct *work); -static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL); -static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker, NULL); +static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker); +static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker); /* Although these variables are used in interrupt context, it makes no sense to * protect them. No user is able to produce enough key events per second and @@ -94,7 +94,7 @@ int pmac_backlight_curve_lookup(struct fb_info *info, int value) return level; } -static void pmac_backlight_key_worker(void *data) +static void pmac_backlight_key_worker(struct work_struct *work) { if (atomic_read(&kernel_backlight_disabled)) return; @@ -166,7 +166,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness) return error; } -static void pmac_backlight_set_legacy_worker(void *data) +static void pmac_backlight_set_legacy_worker(struct work_struct *work) { if (atomic_read(&kernel_backlight_disabled)) return; diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 13707745131..49037edf7d3 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -37,8 +37,8 @@ /* EEH event workqueue setup. */ static DEFINE_SPINLOCK(eeh_eventlist_lock); LIST_HEAD(eeh_eventlist); -static void eeh_thread_launcher(void *); -DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); +static void eeh_thread_launcher(struct work_struct *); +DECLARE_WORK(eeh_event_wq, eeh_thread_launcher); /* Serialize reset sequences for a given pci device */ DEFINE_MUTEX(eeh_event_mutex); @@ -103,7 +103,7 @@ static int eeh_event_handler(void * dummy) * eeh_thread_launcher * @dummy - unused */ -static void eeh_thread_launcher(void *dummy) +static void eeh_thread_launcher(struct work_struct *dummy) { if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0) printk(KERN_ERR "Failed to start EEH daemon\n"); diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index 2e1943e2781..709952c25f2 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -385,6 +385,7 @@ struct fcc_enet_private { phy_info_t *phy; struct work_struct phy_relink; struct work_struct phy_display_config; + struct net_device *dev; uint sequence_done; @@ -1391,10 +1392,11 @@ static phy_info_t *phy_info[] = { NULL }; -static void mii_display_status(void *data) +static void mii_display_status(struct work_struct *work) { - struct net_device *dev = data; - volatile struct fcc_enet_private *fep = dev->priv; + volatile struct fcc_enet_private *fep = + container_of(work, struct fcc_enet_private, phy_relink); + struct net_device *dev = fep->dev; uint s = fep->phy_status; if (!fep->link && !fep->old_link) { @@ -1428,10 +1430,12 @@ static void mii_display_status(void *data) printk(".\n"); } -static void mii_display_config(void *data) +static void mii_display_config(struct work_struct *work) { - struct net_device *dev = data; - volatile struct fcc_enet_private *fep = dev->priv; + volatile struct fcc_enet_private *fep = + container_of(work, struct fcc_enet_private, + phy_display_config); + struct net_device *dev = fep->dev; uint s = fep->phy_status; printk("%s: config: auto-negotiation ", dev->name); @@ -1758,8 +1762,9 @@ static int __init fec_enet_init(void) cep->phy_id_done = 0; cep->phy_addr = fip->fc_phyaddr; mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy); - INIT_WORK(&cep->phy_relink, mii_display_status, dev); - INIT_WORK(&cep->phy_display_config, mii_display_config, dev); + INIT_WORK(&cep->phy_relink, mii_display_status); + INIT_WORK(&cep->phy_display_config, mii_display_config); + cep->dev = dev; #endif /* CONFIG_USE_MDIO */ fip++; diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 2f9fa9e3d33..e6c28fb423b 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -173,6 +173,7 @@ struct fec_enet_private { uint phy_speed; phy_info_t *phy; struct work_struct phy_task; + struct net_device *dev; uint sequence_done; @@ -1263,10 +1264,11 @@ static void mii_display_status(struct net_device *dev) printk(".\n"); } -static void mii_display_config(void *priv) +static void mii_display_config(struct work_struct *work) { - struct net_device *dev = (struct net_device *)priv; - struct fec_enet_private *fep = dev->priv; + struct fec_enet_private *fep = + container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->dev; volatile uint *s = &(fep->phy_status); printk("%s: config: auto-negotiation ", dev->name); @@ -1295,10 +1297,11 @@ static void mii_display_config(void *priv) fep->sequence_done = 1; } -static void mii_relink(void *priv) +static void mii_relink(struct work_struct *work) { - struct net_device *dev = (struct net_device *)priv; - struct fec_enet_private *fep = dev->priv; + struct fec_enet_private *fep = + container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->dev; int duplex; fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; @@ -1325,7 +1328,8 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = dev->priv; - INIT_WORK(&fep->phy_task, mii_relink, (void *)dev); + fep->dev = dev; + INIT_WORK(&fep->phy_task, mii_relink); schedule_work(&fep->phy_task); } @@ -1333,7 +1337,8 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = dev->priv; - INIT_WORK(&fep->phy_task, mii_display_config, (void *)dev); + fep->dev = dev; + INIT_WORK(&fep->phy_task, mii_display_config); schedule_work(&fep->phy_task); } diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index af1e8fc7d98..67d5cf9cba8 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -92,8 +92,8 @@ static int appldata_timer_active; * Work queue */ static struct workqueue_struct *appldata_wq; -static void appldata_work_fn(void *data); -static DECLARE_WORK(appldata_work, appldata_work_fn, NULL); +static void appldata_work_fn(struct work_struct *work); +static DECLARE_WORK(appldata_work, appldata_work_fn); /* @@ -125,7 +125,7 @@ static void appldata_timer_function(unsigned long data) * * call data gathering function for each (active) module */ -static void appldata_work_fn(void *data) +static void appldata_work_fn(struct work_struct *work) { struct list_head *lh; struct appldata_ops *ops; diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index bffc7e17697..d83d64af31f 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -51,6 +51,14 @@ config GENERIC_TIME config ARCH_MAY_HAVE_PC_FDC bool +config STACKTRACE_SUPPORT + bool + default y + +config LOCKDEP_SUPPORT + bool + default y + source "init/Kconfig" menu "System type" @@ -219,6 +227,20 @@ config SH_SHMIN help Select SHMIN if configuring for the SHMIN board. +config SH_7206_SOLUTION_ENGINE + bool "SolutionEngine7206" + select CPU_SUBTYPE_SH7206 + help + Select 7206 SolutionEngine if configuring for a Hitachi SH7206 + evaluation board. + +config SH_7619_SOLUTION_ENGINE + bool "SolutionEngine7619" + select CPU_SUBTYPE_SH7619 + help + Select 7619 SolutionEngine if configuring for a Hitachi SH7619 + evaluation board. + config SH_UNKNOWN bool "BareCPU" help @@ -280,12 +302,20 @@ config CF_BASE_ADDR menu "Processor features" -config CPU_LITTLE_ENDIAN - bool "Little Endian" +choice + prompt "Endianess selection" + default CPU_LITTLE_ENDIAN help Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. Say Y if - your machine is little endian, N if it's a big endian machine. + endian byte order. These modes require different kernels. + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + +config CPU_BIG_ENDIAN + bool "Big Endian" + +endchoice config SH_FPU bool "FPU support" @@ -345,6 +375,9 @@ config CPU_HAS_MASKREG_IRQ config CPU_HAS_INTC2_IRQ bool +config CPU_HAS_IPR_IRQ + bool + config CPU_HAS_SR_RB bool "CPU has SR.RB" depends on CPU_SH3 || CPU_SH4 @@ -357,6 +390,9 @@ config CPU_HAS_SR_RB See <file:Documentation/sh/register-banks.txt> for further information on SR.RB and register banking in the kernel in general. +config CPU_HAS_PTEA + bool + endmenu menu "Timer support" @@ -364,10 +400,25 @@ depends on !GENERIC_TIME config SH_TMU bool "TMU timer support" + depends on CPU_SH3 || CPU_SH4 default y help This enables the use of the TMU as the system timer. +config SH_CMT + bool "CMT timer support" + depends on CPU_SH2 + default y + help + This enables the use of the CMT as the system timer. + +config SH_MTU2 + bool "MTU2 timer support" + depends on CPU_SH2A + default n + help + This enables the use of the MTU2 as the system timer. + endmenu source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" @@ -376,19 +427,52 @@ source "arch/sh/boards/renesas/rts7751r2d/Kconfig" source "arch/sh/boards/renesas/r7780rp/Kconfig" +config SH_TIMER_IRQ + int + default "28" if CPU_SUBTYPE_SH7780 + default "86" if CPU_SUBTYPE_SH7619 + default "140" if CPU_SUBTYPE_SH7206 + default "16" + +config NO_IDLE_HZ + bool "Dynamic tick timer" + help + Select this option if you want to disable continuous timer ticks + and have them programmed to occur as required. This option saves + power as the system can remain in idle state for longer. + + By default dynamic tick is disabled during the boot, and can be + manually enabled with: + + echo 1 > /sys/devices/system/timer/timer0/dyn_tick + + Alternatively, if you want dynamic tick automatically enabled + during boot, pass "dyntick=enable" via the kernel command string. + + Please note that dynamic tick may affect the accuracy of + timekeeping on some platforms depending on the implementation. + config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" + default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 + default "31250000" if CPU_SUBTYPE_SH7619 + default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \ + CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \ + CPU_SUBTYPE_SH7206 default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 default "60000000" if CPU_SUBTYPE_SH7751 - default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \ - CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 - default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 default "66000000" if CPU_SUBTYPE_SH4_202 help This option is used to specify the peripheral clock frequency. This is necessary for determining the reference clock value on platforms lacking an RTC. +config SH_CLK_MD + int "CPU Mode Pin Setting" + depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206 + help + MD2 - MD0 Setting. + menu "CPU Frequency scaling" source "drivers/cpufreq/Kconfig" @@ -421,6 +505,8 @@ config HEARTBEAT behavior is platform-dependent, but normally the flash frequency is a hyperbolic function of the 5-minute load average. +source "arch/sh/drivers/Kconfig" + endmenu config ISA_DMA_API diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 48479e014da..66a25ef4ef1 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" config SH_STANDARD_BIOS @@ -17,7 +21,18 @@ config SH_STANDARD_BIOS config EARLY_SCIF_CONSOLE bool "Use early SCIF console" - depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS + help + This enables an early console using a fixed SCIF port. This can + be used by platforms that are either not running the SH + standard BIOS, or do not wish to use the BIOS callbacks for the + serial I/O. + +config EARLY_SCIF_CONSOLE_PORT + hex "SCIF port for early console" + depends on EARLY_SCIF_CONSOLE + default "0xffe00000" if CPU_SUBTYPE_SH7780 + default "0xfffe9800" if CPU_SUBTYPE_SH72060 + default "0xffe80000" if CPU_SH4 config EARLY_PRINTK bool "Early printk support" @@ -30,6 +45,11 @@ config EARLY_PRINTK when the kernel may crash or hang before the serial console is initialised. If unsure, say N. + On devices that are running SH-IPL and want to keep the port + initialization consistent while not using the BIOS callbacks, + select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using + the kernel command line option to toggle back and forth. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 26d62ff51a6..d10bba5e107 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -13,10 +13,6 @@ # for "archclean" and "archdep" for cleaning up and making dependencies for # this architecture # - -cflags-y := -mb -cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml - isa-y := any isa-$(CONFIG_SH_DSP) := sh isa-$(CONFIG_CPU_SH2) := sh2 @@ -38,13 +34,16 @@ isa-y := $(isa-y)-nofpu endif endif -cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) - -cflags-$(CONFIG_CPU_SH2) += -m2 -cflags-$(CONFIG_CPU_SH3) += -m3 -cflags-$(CONFIG_CPU_SH4) += -m4 \ +cflags-$(CONFIG_CPU_SH2) := -m2 +cflags-$(CONFIG_CPU_SH3) := -m3 +cflags-$(CONFIG_CPU_SH4) := -m4 \ $(call cc-option,-mno-implicit-fp,-m4-nofpu) -cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) +cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,) + +cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb +cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml + +cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -59,7 +58,9 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S # never be used by anyone. Use a board-specific defconfig that has a # reasonable chance of being current instead. # -KBUILD_DEFCONFIG := rts7751r2d_defconfig +KBUILD_DEFCONFIG := r7780rp_defconfig + +KBUILD_IMAGE := arch/sh/boot/zImage # # Choosing incompatible machines durings configuration will result in @@ -109,6 +110,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev machdir-$(CONFIG_SH_LANDISK) := landisk machdir-$(CONFIG_SH_TITAN) := titan machdir-$(CONFIG_SH_SHMIN) := shmin +machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206 +machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619 machdir-$(CONFIG_SH_UNKNOWN) := unknown incdir-y := $(notdir $(machdir-y)) @@ -124,6 +127,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/ core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 +cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile index f1776d02797..574b0316ed5 100644 --- a/arch/sh/boards/renesas/r7780rp/Makefile +++ b/arch/sh/boards/renesas/r7780rp/Makefile @@ -3,4 +3,6 @@ # obj-y := setup.o io.o irq.o -obj-$(CONFIG_HEARTBEAT) += led.o + +obj-$(CONFIG_HEARTBEAT) += led.o +obj-$(CONFIG_PUSH_SWITCH) += psw.o diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c index aa15ec5bc69..cc381e19778 100644 --- a/arch/sh/boards/renesas/r7780rp/irq.c +++ b/arch/sh/boards/renesas/r7780rp/irq.c @@ -10,6 +10,7 @@ */ #include <linux/init.h> #include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <asm/r7780rp.h> diff --git a/arch/sh/boards/renesas/r7780rp/psw.c b/arch/sh/boards/renesas/r7780rp/psw.c new file mode 100644 index 00000000000..c844dfa5d58 --- /dev/null +++ b/arch/sh/boards/renesas/r7780rp/psw.c @@ -0,0 +1,122 @@ +/* + * arch/sh/boards/renesas/r7780rp/psw.c + * + * push switch support for RDBRP-1/RDBREVRP-1 debug boards. + * + * Copyright (C) 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/io.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <asm/mach/r7780rp.h> +#include <asm/push-switch.h> + +static irqreturn_t psw_irq_handler(int irq, void *arg) +{ + struct platform_device *pdev = arg; + struct push_switch *psw = platform_get_drvdata(pdev); + struct push_switch_platform_info *psw_info = pdev->dev.platform_data; + unsigned int l, mask; + int ret = 0; + + l = ctrl_inw(PA_DBSW); + + /* Nothing to do if there's no state change */ + if (psw->state) { + ret = 1; + goto out; + } + + mask = l & 0x70; + /* Figure out who raised it */ + if (mask & (1 << psw_info->bit)) { + psw->state = !!(mask & (1 << psw_info->bit)); + if (psw->state) /* debounce */ + mod_timer(&psw->debounce, jiffies + 50); + + ret = 1; + } + +out: + /* Clear the switch IRQs */ + l |= (0x7 << 12); + ctrl_outw(l, PA_DBSW); + + return IRQ_RETVAL(ret); +} + +static struct resource psw_resources[] = { + [0] = { + .start = IRQ_PSW, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct push_switch_platform_info s2_platform_data = { + .name = "s2", + .bit = 6, + .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_SHARED, + .irq_handler = psw_irq_handler, +}; + +static struct platform_device s2_switch_device = { + .name = "push-switch", + .id = 0, + .num_resources = ARRAY_SIZE(psw_resources), + .resource = psw_resources, + .dev = { + .platform_data = &s2_platform_data, + }, +}; + +static struct push_switch_platform_info s3_platform_data = { + .name = "s3", + .bit = 5, + .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_SHARED, + .irq_handler = psw_irq_handler, +}; + +static struct platform_device s3_switch_device = { + .name = "push-switch", + .id = 1, + .num_resources = ARRAY_SIZE(psw_resources), + .resource = psw_resources, + .dev = { + .platform_data = &s3_platform_data, + }, +}; + +static struct push_switch_platform_info s4_platform_data = { + .name = "s4", + .bit = 4, + .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_SHARED, + .irq_handler = psw_irq_handler, +}; + +static struct platform_device s4_switch_device = { + .name = "push-switch", + .id = 2, + .num_resources = ARRAY_SIZE(psw_resources), + .resource = psw_resources, + .dev = { + .platform_data = &s4_platform_data, + }, +}; + +static struct platform_device *psw_devices[] = { + &s2_switch_device, &s3_switch_device, &s4_switch_device, +}; + +static int __init psw_init(void) +{ + return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices)); +} +module_init(psw_init); diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index c331caeb694..9f89c8de9db 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -44,8 +44,37 @@ static struct platform_device m66596_usb_host_device = { .resource = m66596_usb_host_resources, }; +static struct resource cf_ide_resources[] = { + [0] = { + .start = 0x1f0, + .end = 0x1f0 + 8, + .flags = IORESOURCE_IO, + }, + [1] = { + .start = 0x1f0 + 0x206, + .end = 0x1f0 + 8 + 0x206 + 8, + .flags = IORESOURCE_IO, + }, + [2] = { +#ifdef CONFIG_SH_R7780MP + .start = 1, +#else + .start = 4, +#endif + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cf_ide_device = { + .name = "pata_platform", + .id = -1, + .num_resources = ARRAY_SIZE(cf_ide_resources), + .resource = cf_ide_resources, +}; + static struct platform_device *r7780rp_devices[] __initdata = { &m66596_usb_host_device, + &cf_ide_device, }; static int __init r7780rp_devices_setup(void) diff --git a/arch/sh/boards/se/7206/Makefile b/arch/sh/boards/se/7206/Makefile new file mode 100644 index 00000000000..63950f4f245 --- /dev/null +++ b/arch/sh/boards/se/7206/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the 7206 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o irq.o +obj-$(CONFIG_HEARTBEAT) += led.o + diff --git a/arch/sh/boards/se/7206/io.c b/arch/sh/boards/se/7206/io.c new file mode 100644 index 00000000000..b557273e0cb --- /dev/null +++ b/arch/sh/boards/se/7206/io.c @@ -0,0 +1,123 @@ +/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $ + * + * linux/arch/sh/boards/se/7206/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7206 SolutionEngine. + * + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/se7206.h> + + +static inline void delay(void) +{ + ctrl_inw(0x20000000); /* P2 ROM Area */ +} + +/* MS7750 requires special versions of in*, out* routines, since + PC-like io ports are located at upper half byte of 16-bit word which + can be accessed only with 16-bit wide. */ + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); + else if (port >= 0x300 || port < 0x310) + return (volatile __u16 *) (PA_SMSC + (port - 0x300)); +} + +unsigned char se7206_inb(unsigned long port) +{ + return (*port2adr(port))&0xff; +} + +unsigned char se7206_inb_p(unsigned long port) +{ + unsigned long v; + + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short se7206_inw(unsigned long port) +{ + return *port2adr(port);; +} + +unsigned int se7206_inl(unsigned long port) +{ + maybebadio(port); + return 0; +} + +void se7206_outb(unsigned char value, unsigned long port) +{ + *(port2adr(port)) = value; +} + +void se7206_outb_p(unsigned char value, unsigned long port) +{ + *(port2adr(port)) = value; + delay(); +} + +void se7206_outw(unsigned short value, unsigned long port) +{ + *port2adr(port) = value; +} + +void se7206_outl(unsigned int value, unsigned long port) +{ + maybebadio(port); +} + +void se7206_insb(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + __u8 *ap = addr; + + while (count--) + *ap++ = *p; +} + +void se7206_insw(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + __u16 *ap = addr; + while (count--) + *ap++ = *p; +} + +void se7206_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(port); +} + +void se7206_outsb(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + const __u8 *ap = addr; + + while (count--) + *p = *ap++; +} + +void se7206_outsw(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + const __u16 *ap = addr; + while (count--) + *p = *ap++; +} + +void se7206_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(port); +} diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c new file mode 100644 index 00000000000..3fb0c5f5b23 --- /dev/null +++ b/arch/sh/boards/se/7206/irq.c @@ -0,0 +1,139 @@ +/* + * linux/arch/sh/boards/se/7206/irq.c + * + * Copyright (C) 2005,2006 Yoshinori Sato + * + * Hitachi SolutionEngine Support. + * + */ +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <asm/se7206.h> + +#define INTSTS0 0x31800000 +#define INTSTS1 0x31800002 +#define INTMSK0 0x31800004 +#define INTMSK1 0x31800006 +#define INTSEL 0x31800008 + +static void disable_se7206_irq(unsigned int irq) +{ + unsigned short val; + unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); + unsigned short msk0,msk1; + + /* Set the priority in IPR to 0 */ + val = ctrl_inw(INTC_IPR01); + val &= mask; + ctrl_outw(val, INTC_IPR01); + /* FPGA mask set */ + msk0 = ctrl_inw(INTMSK0); + msk1 = ctrl_inw(INTMSK1); + + switch (irq) { + case IRQ0_IRQ: + msk0 |= 0x0010; + break; + case IRQ1_IRQ: + msk0 |= 0x000f; + break; + case IRQ2_IRQ: + msk0 |= 0x0f00; + msk1 |= 0x00ff; + break; + } + ctrl_outw(msk0, INTMSK0); + ctrl_outw(msk1, INTMSK1); +} + +static void enable_se7206_irq(unsigned int irq) +{ + unsigned short val; + unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); + unsigned short msk0,msk1; + + /* Set priority in IPR back to original value */ + val = ctrl_inw(INTC_IPR01); + val |= value; + ctrl_outw(val, INTC_IPR01); + + /* FPGA mask reset */ + msk0 = ctrl_inw(INTMSK0); + msk1 = ctrl_inw(INTMSK1); + + switch (irq) { + case IRQ0_IRQ: + msk0 &= ~0x0010; + break; + case IRQ1_IRQ: + msk0 &= ~0x000f; + break; + case IRQ2_IRQ: + msk0 &= ~0x0f00; + msk1 &= ~0x00ff; + break; + } + ctrl_outw(msk0, INTMSK0); + ctrl_outw(msk1, INTMSK1); +} + +static void eoi_se7206_irq(unsigned int irq) +{ + unsigned short sts0,sts1; + + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_se7206_irq(irq); + /* FPGA isr clear */ + sts0 = ctrl_inw(INTSTS0); + sts1 = ctrl_inw(INTSTS1); + + switch (irq) { + case IRQ0_IRQ: + sts0 &= ~0x0010; + break; + case IRQ1_IRQ: + sts0 &= ~0x000f; + break; + case IRQ2_IRQ: + sts0 &= ~0x0f00; + sts1 &= ~0x00ff; + break; + } + ctrl_outw(sts0, INTSTS0); + ctrl_outw(sts1, INTSTS1); +} + +static struct irq_chip se7206_irq_chip __read_mostly = { + .name = "SE7206-FPGA-IRQ", + .mask = disable_se7206_irq, + .unmask = enable_se7206_irq, + .mask_ack = disable_se7206_irq, + .eoi = eoi_se7206_irq, +}; + +static void make_se7206_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + set_irq_chip_and_handler_name(irq, &se7206_irq_chip, + handle_level_irq, "level"); + disable_se7206_irq(irq); +} + +/* + * Initialize IRQ setting + */ +void __init init_se7206_IRQ(void) +{ + make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ + make_se7206_irq(IRQ1_IRQ); /* ATA */ + make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ + ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ + + /* FPGA System register setup*/ + ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */ + ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */ + /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ + ctrl_outw(0x0001,INTSEL); +} diff --git a/arch/sh/boards/se/7206/led.c b/arch/sh/boards/se/7206/led.c new file mode 100644 index 00000000000..ef794601ab8 --- /dev/null +++ b/arch/sh/boards/se/7206/led.c @@ -0,0 +1,57 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com> + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include <linux/config.h> +#include <asm/se7206.h> + +#ifdef CONFIG_HEARTBEAT + +#include <linux/sched.h> + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300<<FSHIFT)/ + ((avenrun[0]/5) + (3<<FSHIFT)) ); + + if (up) { + if (bit == 7) { + bit--; + up=0; + } else { + bit ++; + } + } else { + if (bit == 0) { + bit++; + up=1; + } else { + bit--; + } + } + *p = 1<<(bit+8); + +} +#endif /* CONFIG_HEARTBEAT */ diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c new file mode 100644 index 00000000000..0f42e91a323 --- /dev/null +++ b/arch/sh/boards/se/7206/setup.c @@ -0,0 +1,79 @@ +/* + * + * linux/arch/sh/boards/se/7206/setup.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * Hitachi 7206 SolutionEngine Support. + * + */ + +#include <linux/init.h> +#include <linux/platform_device.h> +#include <asm/se7206.h> +#include <asm/io.h> +#include <asm/machvec.h> + +static struct resource smc91x_resources[] = { + [0] = { + .start = 0x300, + .end = 0x300 + 0x020 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 64, + .end = 64, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static int __init se7206_devices_setup(void) +{ + return platform_device_register(&smc91x_device); +} + +__initcall(se7206_devices_setup); + +void heartbeat_se(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + .mv_name = "SolutionEngine", + .mv_nr_irqs = 256, + .mv_inb = se7206_inb, + .mv_inw = se7206_inw, + .mv_inl = se7206_inl, + .mv_outb = se7206_outb, + .mv_outw = se7206_outw, + .mv_outl = se7206_outl, + + .mv_inb_p = se7206_inb_p, + .mv_inw_p = se7206_inw, + .mv_inl_p = se7206_inl, + .mv_outb_p = se7206_outb_p, + .mv_outw_p = se7206_outw, + .mv_outl_p = se7206_outl, + + .mv_insb = se7206_insb, + .mv_insw = se7206_insw, + .mv_insl = se7206_insl, + .mv_outsb = se7206_outsb, + .mv_outsw = se7206_outsw, + .mv_outsl = se7206_outsl, + + .mv_init_irq = init_se7206_IRQ, +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_se, +#endif +}; +ALIAS_MV(se) diff --git a/arch/sh/boards/se/7619/Makefile b/arch/sh/boards/se/7619/Makefile new file mode 100644 index 00000000000..3666eca8a65 --- /dev/null +++ b/arch/sh/boards/se/7619/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the 7619 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o diff --git a/arch/sh/boards/se/7619/io.c b/arch/sh/boards/se/7619/io.c new file mode 100644 index 00000000000..176f1f39cd9 --- /dev/null +++ b/arch/sh/boards/se/7619/io.c @@ -0,0 +1,102 @@ +/* + * + * linux/arch/sh/boards/se/7619/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7619 SolutionEngine. + * + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/se7619.h> +#include <asm/irq.h> + +/* FIXME: M3A-ZAB7 Compact Flash Slot support */ + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */ +} + +#define badio(name,port) \ + printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +unsigned char se7619___inb(unsigned long port) +{ + badio(inb, port); + return 0; +} + +unsigned char se7619___inb_p(unsigned long port) +{ + badio(inb_p, port); + delay(); + return 0; +} + +unsigned short se7619___inw(unsigned long port) +{ + badio(inw, port); + return 0; +} + +unsigned int se7619___inl(unsigned long port) +{ + badio(inl, port); + return 0; +} + +void se7619___outb(unsigned char value, unsigned long port) +{ + badio(outb, port); +} + +void se7619___outb_p(unsigned char value, unsigned long port) +{ + badio(outb_p, port); + delay(); +} + +void se7619___outw(unsigned short value, unsigned long port) +{ + badio(outw, port); +} + +void se7619___outl(unsigned int value, unsigned long port) +{ + badio(outl, port); +} + +void se7619___insb(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insw(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insl(unsigned long port, void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsb(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsw(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsl(unsigned long port, const void *addr, unsigned long count) +{ + badio(outsw, port); +} diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c new file mode 100644 index 00000000000..e627b26de0d --- /dev/null +++ b/arch/sh/boards/se/7619/setup.c @@ -0,0 +1,43 @@ +/* + * arch/sh/boards/se/7619/setup.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * Hitachi SH7619 SolutionEngine Support. + */ + +#include <linux/init.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <asm/se7619.h> +#include <asm/machvec.h> + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + .mv_name = "SolutionEngine", + .mv_nr_irqs = 108, + .mv_inb = se7619___inb, + .mv_inw = se7619___inw, + .mv_inl = se7619___inl, + .mv_outb = se7619___outb, + .mv_outw = se7619___outw, + .mv_outl = se7619___outl, + + .mv_inb_p = se7619___inb_p, + .mv_inw_p = se7619___inw, + .mv_inl_p = se7619___inl, + .mv_outb_p = se7619___outb_p, + .mv_outw_p = se7619___outw, + .mv_outl_p = se7619___outl, + + .mv_insb = se7619___insb, + .mv_insw = se7619___insw, + .mv_insl = se7619___insl, + .mv_outsb = se7619___outsb, + .mv_outsw = se7619___outsw, + .mv_outsl = se7619___outsl, +}; +ALIAS_MV(se) diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c index a6046d93758..6bcd939bfae 100644 --- a/arch/sh/boards/titan/setup.c +++ b/arch/sh/boards/titan/setup.c @@ -1,26 +1,30 @@ /* - * Setup for Titan + * arch/sh/boards/titan/setup.c - Setup for Titan + * + * Copyright (C) 2006 Jamie Lenehan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ - #include <linux/init.h> -#include <asm/irq.h> +#include <linux/irq.h> #include <asm/titan.h> #include <asm/io.h> -extern void __init pcibios_init_platform(void); - static struct ipr_data titan_ipr_map[] = { - { TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, - { TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, - { TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, - { TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, + /* IRQ, IPR idx, shift, prio */ + { TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */ + { TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */ + { TITAN_IRQ_MPCIA, 3, 4, 8 }, /* mPCI A (top) */ + { TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */ }; static void __init init_titan_irq(void) { /* enable individual interrupt mode for externals */ - ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); - + ipr_irq_enable_irlm(); + /* register ipr irqs */ make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map)); } @@ -47,6 +51,5 @@ struct sh_machine_vector mv_titan __initmv = { .mv_ioport_map = titan_ioport_map, .mv_init_irq = init_titan_irq, - .mv_init_pci = pcibios_init_platform, }; ALIAS_MV(titan) diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c index f2fed5ce5cc..35452d85b7f 100644 --- a/arch/sh/boot/compressed/misc.c +++ b/arch/sh/boot/compressed/misc.c @@ -12,6 +12,7 @@ */ #include <asm/uaccess.h> +#include <asm/addrspace.h> #ifdef CONFIG_SH_STANDARD_BIOS #include <asm/sh_bios.h> #endif @@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE]; void decompress_kernel(void) { output_data = 0; - output_ptr = (unsigned long)&_text+0x20001000; + output_ptr = P2SEGADDR((unsigned long)&_text+0x1000); free_mem_ptr = (unsigned long)&_end; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig index 34e2046c321..2b75b4896ba 100644 --- a/arch/sh/configs/r7780rp_defconfig +++ b/arch/sh/configs/r7780rp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc3 -# Tue Oct 31 12:32:06 2006 +# Linux kernel version: 2.6.19 +# Wed Dec 6 11:59:38 2006 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_GENERIC_TIME is not set +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -37,6 +39,7 @@ CONFIG_BSD_PROCESS_ACCT=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -118,6 +121,8 @@ CONFIG_SH_R7780RP=y # CONFIG_SH_LANDISK is not set # CONFIG_SH_TITAN is not set # CONFIG_SH_SHMIN is not set +# CONFIG_SH_7206_SOLUTION_ENGINE is not set +# CONFIG_SH_7619_SOLUTION_ENGINE is not set # CONFIG_SH_UNKNOWN is not set # @@ -130,6 +135,12 @@ CONFIG_CPU_SH4A=y # SH-2 Processor Support # # CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7619 is not set + +# +# SH-2A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7206 is not set # # SH-3 Processor Support @@ -165,6 +176,7 @@ CONFIG_CPU_SH4A=y # # CONFIG_CPU_SUBTYPE_SH7770 is not set CONFIG_CPU_SUBTYPE_SH7780=y +# CONFIG_CPU_SUBTYPE_SH7785 is not set # # SH4AL-DSP Processor Support @@ -181,8 +193,14 @@ CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 # CONFIG_32BIT is not set CONFIG_VSYSCALL=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_64KB is not set CONFIG_HUGETLB_PAGE_SIZE_64K=y +# CONFIG_HUGETLB_PAGE_SIZE_256K is not set # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -204,12 +222,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # Processor features # CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y # CONFIG_SH_DSP is not set CONFIG_SH_STORE_QUEUES=y CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_INTC2_IRQ=y CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_PTEA=y # # Timer support @@ -220,6 +240,8 @@ CONFIG_SH_TMU=y # R7780RP options # CONFIG_SH_R7780MP=y +CONFIG_SH_TIMER_IRQ=28 +CONFIG_NO_IDLE_HZ=y CONFIG_SH_PCLK_FREQ=32000000 # @@ -238,13 +260,18 @@ CONFIG_SH_PCLK_FREQ=32000000 # CONFIG_HD6446X_SERIES is not set # +# Additional SuperH Device Drivers +# +CONFIG_PUSH_SWITCH=y + +# # Kernel features # # CONFIG_HZ_100 is not set CONFIG_HZ_250=y # CONFIG_HZ_1000 is not set CONFIG_HZ=250 -# CONFIG_KEXEC is not set +CONFIG_KEXEC=y # CONFIG_SMP is not set # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set @@ -278,10 +305,7 @@ CONFIG_PCI_AUTO_UPDATE_RESOURCES=y # # PCI Hotplug Support # -CONFIG_HOTPLUG_PCI=y -# CONFIG_HOTPLUG_PCI_FAKE is not set -# CONFIG_HOTPLUG_PCI_CPCI is not set -# CONFIG_HOTPLUG_PCI_SHPC is not set +# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -341,6 +365,7 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set @@ -556,6 +581,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_JMICRON is not set # CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set @@ -572,6 +598,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_SIS is not set # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set +CONFIG_PATA_PLATFORM=y # # Multi-device support (RAID and LVM) @@ -688,6 +715,7 @@ CONFIG_R8169=y # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -830,10 +858,6 @@ CONFIG_HW_RANDOM=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -1020,7 +1044,7 @@ CONFIG_INOTIFY_USER=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +CONFIG_FUSE_FS=m # # CD-ROM/DVD Filesystems @@ -1052,7 +1076,7 @@ CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -1153,28 +1177,33 @@ CONFIG_NLS_ISO8859_1=y # # Profiling support # -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m # # Kernel hacking # -# CONFIG_PRINTK_TIME is not set +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_PRINTK_TIME=y CONFIG_ENABLE_MUST_CHECK=y -# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set @@ -1184,7 +1213,7 @@ CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_EARLY_SCIF_CONSOLE is not set -# CONFIG_DEBUG_STACKOVERFLOW is not set +CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_4KSTACKS is not set # CONFIG_KGDB is not set diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig new file mode 100644 index 00000000000..36cec0b6e7c --- /dev/null +++ b/arch/sh/configs/se7206_defconfig @@ -0,0 +1,826 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc4 +# Sun Nov 5 16:20:10 2006 +# +CONFIG_SUPERH=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_7300_SOLUTION_ENGINE is not set +# CONFIG_SH_7343_SOLUTION_ENGINE is not set +# CONFIG_SH_73180_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SYSTEMH is not set +# CONFIG_SH_HP6XX is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SH03 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_HS7751RVOIP is not set +# CONFIG_SH_7710VOIPGW is not set +# CONFIG_SH_RTS7751R2D is not set +# CONFIG_SH_R7780RP is not set +# CONFIG_SH_EDOSK7705 is not set +# CONFIG_SH_SH4202_MICRODEV is not set +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set +# CONFIG_SH_SHMIN is not set +CONFIG_SH_7206_SOLUTION_ENGINE=y +# CONFIG_SH_7619_SOLUTION_ENGINE is not set +# CONFIG_SH_UNKNOWN is not set + +# +# Processor selection +# +CONFIG_CPU_SH2=y +CONFIG_CPU_SH2A=y + +# +# SH-2 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7619 is not set + +# +# SH-2A Processor Support +# +CONFIG_CPU_SUBTYPE_SH7206=y + +# +# SH-3 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set + +# +# SH-4 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# ST40 Processor Support +# +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +# CONFIG_CPU_SUBTYPE_ST40GX1 is not set + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# SH4AL-DSP Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set + +# +# Memory management options +# +CONFIG_PAGE_OFFSET=0x00000000 +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x02000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set + +# +# Processor features +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_SH_FPU is not set +# CONFIG_SH_FPU_EMU is not set +# CONFIG_SH_DSP is not set + +# +# Timer support +# +CONFIG_SH_CMT=y +# CONFIG_SH_MTU2 is not set +CONFIG_SH_PCLK_FREQ=33333333 +CONFIG_SH_CLK_MD=6 + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# +# CONFIG_HD6446X_SERIES is not set + +# +# Kernel features +# +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +# CONFIG_KEXEC is not set +# CONFIG_SMP is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +# CONFIG_PCI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_ZFLAT=y +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x20000000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 +# CONFIG_MTD_SOLUTIONENGINE is not set +# CONFIG_MTD_UCLINUX is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +# CONFIG_NETDEVICES is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=4 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +# CONFIG_SYSFS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_UNWIND_INFO is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set +# CONFIG_KGDB is not set + +# +# Security options +# +# CONFIG_KEYS is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/arch/sh/drivers/Kconfig b/arch/sh/drivers/Kconfig new file mode 100644 index 00000000000..c54c758e624 --- /dev/null +++ b/arch/sh/drivers/Kconfig @@ -0,0 +1,9 @@ +menu "Additional SuperH Device Drivers" + +config PUSH_SWITCH + tristate "Push switch support" + help + This enables support for the push switch framework, a simple + framework that allows for sysfs driven switch status reporting. + +endmenu diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile index 338c3729d27..bf18dbfb678 100644 --- a/arch/sh/drivers/Makefile +++ b/arch/sh/drivers/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_SH_DMA) += dma/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ - +obj-$(CONFIG_PUSH_SWITCH) += push-switch.o diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile index 065d4c90970..db1295d3226 100644 --- a/arch/sh/drivers/dma/Makefile +++ b/arch/sh/drivers/dma/Makefile @@ -2,8 +2,8 @@ # Makefile for the SuperH DMA specific kernel interface routines under Linux. # -obj-y += dma-api.o dma-isa.o +obj-y += dma-api.o +obj-$(CONFIG_ISA_DMA_API) += dma-isa.o obj-$(CONFIG_SYSFS) += dma-sysfs.o obj-$(CONFIG_SH_DMA) += dma-sh.o obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o - diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 47c3e837599..e062067edd2 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -11,61 +11,27 @@ */ #include <linux/init.h> #include <linux/module.h> -#include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/proc_fs.h> #include <linux/list.h> #include <linux/platform_device.h> +#include <linux/mm.h> #include <asm/dma.h> DEFINE_SPINLOCK(dma_spin_lock); static LIST_HEAD(registered_dmac_list); -/* - * A brief note about the reasons for this API as it stands. - * - * For starters, the old ISA DMA API didn't work for us for a number of - * reasons, for one, the vast majority of channels on the SH DMAC are - * dual-address mode only, and both the new and the old DMA APIs are after the - * concept of managing a DMA buffer, which doesn't overly fit this model very - * well. In addition to which, the new API is largely geared at IOMMUs and - * GARTs, and doesn't even support the channel notion very well. - * - * The other thing that's a marginal issue, is the sheer number of random DMA - * engines that are present (ie, in boards like the Dreamcast), some of which - * cascade off of the SH DMAC, and others do not. As such, there was a real - * need for a scalable subsystem that could deal with both single and - * dual-address mode usage, in addition to interoperating with cascaded DMACs. - * - * There really isn't any reason why this needs to be SH specific, though I'm - * not aware of too many other processors (with the exception of some MIPS) - * that have the same concept of a dual address mode, or any real desire to - * actually make use of the DMAC even if such a subsystem were exposed - * elsewhere. - * - * The idea for this was derived from the ARM port, which acted as an excellent - * reference when trying to address these issues. - * - * It should also be noted that the decision to add Yet Another DMA API(tm) to - * the kernel wasn't made easily, and was only decided upon after conferring - * with jejb with regards to the state of the old and new APIs as they applied - * to these circumstances. Philip Blundell was also a great help in figuring - * out some single-address mode DMA semantics that were otherwise rather - * confusing. - */ - struct dma_info *get_dma_info(unsigned int chan) { struct dma_info *info; - unsigned int total = 0; /* * Look for each DMAC's range to determine who the owner of * the channel is. */ list_for_each_entry(info, ®istered_dmac_list, list) { - total += info->nr_channels; - if (chan > total) + if ((chan < info->first_channel_nr) || + (chan >= info->first_channel_nr + info->nr_channels)) continue; return info; @@ -73,6 +39,22 @@ struct dma_info *get_dma_info(unsigned int chan) return NULL; } +EXPORT_SYMBOL(get_dma_info); + +struct dma_info *get_dma_info_by_name(const char *dmac_name) +{ + struct dma_info *info; + + list_for_each_entry(info, ®istered_dmac_list, list) { + if (dmac_name && (strcmp(dmac_name, info->name) != 0)) + continue; + else + return info; + } + + return NULL; +} +EXPORT_SYMBOL(get_dma_info_by_name); static unsigned int get_nr_channels(void) { @@ -91,63 +73,161 @@ static unsigned int get_nr_channels(void) struct dma_channel *get_dma_channel(unsigned int chan) { struct dma_info *info = get_dma_info(chan); + struct dma_channel *channel; + int i; - if (!info) + if (unlikely(!info)) return ERR_PTR(-EINVAL); - return info->channels + chan; + for (i = 0; i < info->nr_channels; i++) { + channel = &info->channels[i]; + if (channel->chan == chan) + return channel; + } + + return NULL; } +EXPORT_SYMBOL(get_dma_channel); int get_dma_residue(unsigned int chan) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (info->ops->get_residue) return info->ops->get_residue(channel); return 0; } +EXPORT_SYMBOL(get_dma_residue); -int request_dma(unsigned int chan, const char *dev_id) +static int search_cap(const char **haystack, const char *needle) { - struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + const char **p; + + for (p = haystack; *p; p++) + if (strcmp(*p, needle) == 0) + return 1; + + return 0; +} + +/** + * request_dma_bycap - Allocate a DMA channel based on its capabilities + * @dmac: List of DMA controllers to search + * @caps: List of capabilites + * + * Search all channels of all DMA controllers to find a channel which + * matches the requested capabilities. The result is the channel + * number if a match is found, or %-ENODEV if no match is found. + * + * Note that not all DMA controllers export capabilities, in which + * case they can never be allocated using this API, and so + * request_dma() must be used specifying the channel number. + */ +int request_dma_bycap(const char **dmac, const char **caps, const char *dev_id) +{ + unsigned int found = 0; + struct dma_info *info; + const char **p; + int i; + + BUG_ON(!dmac || !caps); + + list_for_each_entry(info, ®istered_dmac_list, list) + if (strcmp(*dmac, info->name) == 0) { + found = 1; + break; + } + + if (!found) + return -ENODEV; + + for (i = 0; i < info->nr_channels; i++) { + struct dma_channel *channel = &info->channels[i]; + + if (unlikely(!channel->caps)) + continue; + + for (p = caps; *p; p++) { + if (!search_cap(channel->caps, *p)) + break; + if (request_dma(channel->chan, dev_id) == 0) + return channel->chan; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL(request_dma_bycap); + +int dmac_search_free_channel(const char *dev_id) +{ + struct dma_channel *channel = { 0 }; + struct dma_info *info = get_dma_info(0); + int i; + + for (i = 0; i < info->nr_channels; i++) { + channel = &info->channels[i]; + if (unlikely(!channel)) + return -ENODEV; + + if (atomic_read(&channel->busy) == 0) + break; + } - down(&channel->sem); + if (info->ops->request) { + int result = info->ops->request(channel); + if (result) + return result; - if (!info->ops || chan >= MAX_DMA_CHANNELS) { - up(&channel->sem); - return -EINVAL; + atomic_set(&channel->busy, 1); + return channel->chan; } - atomic_set(&channel->busy, 1); + return -ENOSYS; +} + +int request_dma(unsigned int chan, const char *dev_id) +{ + struct dma_channel *channel = { 0 }; + struct dma_info *info = get_dma_info(chan); + int result; + + channel = get_dma_channel(chan); + if (atomic_xchg(&channel->busy, 1)) + return -EBUSY; strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id)); - up(&channel->sem); + if (info->ops->request) { + result = info->ops->request(channel); + if (result) + atomic_set(&channel->busy, 0); - if (info->ops->request) - return info->ops->request(channel); + return result; + } return 0; } +EXPORT_SYMBOL(request_dma); void free_dma(unsigned int chan) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (info->ops->free) info->ops->free(channel); atomic_set(&channel->busy, 0); } +EXPORT_SYMBOL(free_dma); void dma_wait_for_completion(unsigned int chan) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (channel->flags & DMA_TEI_CAPABLE) { wait_event(channel->wait_queue, @@ -158,21 +238,52 @@ void dma_wait_for_completion(unsigned int chan) while (info->ops->get_residue(channel)) cpu_relax(); } +EXPORT_SYMBOL(dma_wait_for_completion); + +int register_chan_caps(const char *dmac, struct dma_chan_caps *caps) +{ + struct dma_info *info; + unsigned int found = 0; + int i; + + list_for_each_entry(info, ®istered_dmac_list, list) + if (strcmp(dmac, info->name) == 0) { + found = 1; + break; + } + + if (unlikely(!found)) + return -ENODEV; + + for (i = 0; i < info->nr_channels; i++, caps++) { + struct dma_channel *channel; + + if ((info->first_channel_nr + i) != caps->ch_num) + return -EINVAL; + + channel = &info->channels[i]; + channel->caps = caps->caplist; + } + + return 0; +} +EXPORT_SYMBOL(register_chan_caps); void dma_configure_channel(unsigned int chan, unsigned long flags) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (info->ops->configure) info->ops->configure(channel, flags); } +EXPORT_SYMBOL(dma_configure_channel); int dma_xfer(unsigned int chan, unsigned long from, unsigned long to, size_t size, unsigned int mode) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); channel->sar = from; channel->dar = to; @@ -181,8 +292,20 @@ int dma_xfer(unsigned int chan, unsigned long from, return info->ops->xfer(channel); } +EXPORT_SYMBOL(dma_xfer); + +int dma_extend(unsigned int chan, unsigned long op, void *param) +{ + struct dma_info *info = get_dma_info(chan); + struct dma_channel *channel = get_dma_channel(chan); + + if (info->ops->extend) + return info->ops->extend(channel, op, param); + + return -ENOSYS; +} +EXPORT_SYMBOL(dma_extend); -#ifdef CONFIG_PROC_FS static int dma_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data) { @@ -214,8 +337,6 @@ static int dma_read_proc(char *buf, char **start, off_t off, return p - buf; } -#endif - int register_dmac(struct dma_info *info) { @@ -224,8 +345,7 @@ int register_dmac(struct dma_info *info) INIT_LIST_HEAD(&info->list); printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n", - info->name, info->nr_channels, - info->nr_channels > 1 ? "s" : ""); + info->name, info->nr_channels, info->nr_channels > 1 ? "s" : ""); BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); @@ -242,28 +362,26 @@ int register_dmac(struct dma_info *info) size = sizeof(struct dma_channel) * info->nr_channels; - info->channels = kmalloc(size, GFP_KERNEL); + info->channels = kzalloc(size, GFP_KERNEL); if (!info->channels) return -ENOMEM; - - memset(info->channels, 0, size); } total_channels = get_nr_channels(); for (i = 0; i < info->nr_channels; i++) { - struct dma_channel *chan = info->channels + i; + struct dma_channel *chan = &info->channels[i]; + + atomic_set(&chan->busy, 0); - chan->chan = i; - chan->vchan = i + total_channels; + chan->chan = info->first_channel_nr + i; + chan->vchan = info->first_channel_nr + i + total_channels; memcpy(chan->dev_id, "Unused", 7); if (info->flags & DMAC_CHANNELS_TEI_CAPABLE) chan->flags |= DMA_TEI_CAPABLE; - init_MUTEX(&chan->sem); init_waitqueue_head(&chan->wait_queue); - dma_create_sysfs_files(chan, info); } @@ -271,6 +389,7 @@ int register_dmac(struct dma_info *info) return 0; } +EXPORT_SYMBOL(register_dmac); void unregister_dmac(struct dma_info *info) { @@ -285,31 +404,16 @@ void unregister_dmac(struct dma_info *info) list_del(&info->list); platform_device_unregister(info->pdev); } +EXPORT_SYMBOL(unregister_dmac); static int __init dma_api_init(void) { - printk("DMA: Registering DMA API.\n"); - -#ifdef CONFIG_PROC_FS + printk(KERN_NOTICE "DMA: Registering DMA API.\n"); create_proc_read_entry("dma", 0, 0, dma_read_proc, 0); -#endif - return 0; } - subsys_initcall(dma_api_init); MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); MODULE_DESCRIPTION("DMA API for SuperH"); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(request_dma); -EXPORT_SYMBOL(free_dma); -EXPORT_SYMBOL(register_dmac); -EXPORT_SYMBOL(get_dma_residue); -EXPORT_SYMBOL(get_dma_info); -EXPORT_SYMBOL(get_dma_channel); -EXPORT_SYMBOL(dma_xfer); -EXPORT_SYMBOL(dma_wait_for_completion); -EXPORT_SYMBOL(dma_configure_channel); - diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 66078601335..f63721ed86c 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -94,20 +94,13 @@ static int sh_dmac_request_dma(struct dma_channel *chan) if (unlikely(!chan->flags & DMA_TEI_CAPABLE)) return 0; - chan->name = kzalloc(32, GFP_KERNEL); - if (unlikely(chan->name == NULL)) - return -ENOMEM; - snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)", - chan->chan); - return request_irq(get_dmte_irq(chan->chan), dma_tei, - IRQF_DISABLED, chan->name, chan); + IRQF_DISABLED, chan->dev_id, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) { free_irq(get_dmte_irq(chan->chan), chan); - kfree(chan->name); } static void diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 29b8ef9873d..eebcd4768bb 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -3,7 +3,7 @@ * * sysfs interface for SH DMA API * - * Copyright (C) 2004, 2005 Paul Mundt + * Copyright (C) 2004 - 2006 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -21,7 +21,6 @@ static struct sysdev_class dma_sysclass = { set_kset_name("dma"), }; - EXPORT_SYMBOL(dma_sysclass); static ssize_t dma_show_devices(struct sys_device *dev, char *buf) @@ -31,7 +30,10 @@ static ssize_t dma_show_devices(struct sys_device *dev, char *buf) for (i = 0; i < MAX_DMA_CHANNELS; i++) { struct dma_info *info = get_dma_info(i); - struct dma_channel *channel = &info->channels[i]; + struct dma_channel *channel = get_dma_channel(i); + + if (unlikely(!info) || !channel) + continue; len += sprintf(buf + len, "%2d: %14s %s\n", channel->chan, info->name, @@ -125,11 +127,16 @@ int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) if (ret) return ret; - sysdev_create_file(dev, &attr_dev_id); - sysdev_create_file(dev, &attr_count); - sysdev_create_file(dev, &attr_mode); - sysdev_create_file(dev, &attr_flags); - sysdev_create_file(dev, &attr_config); + ret |= sysdev_create_file(dev, &attr_dev_id); + ret |= sysdev_create_file(dev, &attr_count); + ret |= sysdev_create_file(dev, &attr_mode); + ret |= sysdev_create_file(dev, &attr_flags); + ret |= sysdev_create_file(dev, &attr_config); + + if (unlikely(ret)) { + dev_err(&info->pdev->dev, "Failed creating attrs\n"); + return ret; + } snprintf(name, sizeof(name), "dma%d", chan->chan); return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c index cd56d53375e..ac8ee2312cd 100644 --- a/arch/sh/drivers/pci/ops-titan.c +++ b/arch/sh/drivers/pci/ops-titan.c @@ -15,25 +15,21 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/pci.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/titan.h> #include "pci-sh4.h" +static char titan_irq_tab[] __initdata = { + TITAN_IRQ_WAN, + TITAN_IRQ_LAN, + TITAN_IRQ_MPCIA, + TITAN_IRQ_MPCIB, + TITAN_IRQ_USB, +}; + int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { - int irq = -1; - - switch (slot) { - case 0: irq = TITAN_IRQ_WAN; break; /* eth0 (WAN) */ - case 1: irq = TITAN_IRQ_LAN; break; /* eth1 (LAN) */ - case 2: irq = TITAN_IRQ_MPCIA; break; /* mPCI A */ - case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */ - case 4: irq = TITAN_IRQ_USB; break; /* USB */ - default: - printk(KERN_INFO "PCI: Bad IRQ mapping " - "request for slot %d\n", slot); - return -1; - } + int irq = titan_irq_tab[slot]; printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n", slot, pin - 1 + 'A', irq); diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index d6e63529653..602b644c35a 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c @@ -22,6 +22,20 @@ #include <linux/delay.h> #include "pci-sh4.h" +#define INTC_BASE 0xffd00000 +#define INTC_ICR0 (INTC_BASE+0x0) +#define INTC_ICR1 (INTC_BASE+0x1c) +#define INTC_INTPRI (INTC_BASE+0x10) +#define INTC_INTREQ (INTC_BASE+0x24) +#define INTC_INTMSK0 (INTC_BASE+0x44) +#define INTC_INTMSK1 (INTC_BASE+0x48) +#define INTC_INTMSK2 (INTC_BASE+0x40080) +#define INTC_INTMSKCLR0 (INTC_BASE+0x64) +#define INTC_INTMSKCLR1 (INTC_BASE+0x68) +#define INTC_INTMSKCLR2 (INTC_BASE+0x40084) +#define INTC_INT2MSKR (INTC_BASE+0x40038) +#define INTC_INT2MSKCR (INTC_BASE+0x4003c) + /* * Initialization. Try all known PCI access methods. Note that we support * using both PCI BIOS and direct access: in such cases, we use I/O ports diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c new file mode 100644 index 00000000000..f2b9157c314 --- /dev/null +++ b/arch/sh/drivers/push-switch.c @@ -0,0 +1,138 @@ +/* + * Generic push-switch framework + * + * Copyright (C) 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <asm/push-switch.h> + +#define DRV_NAME "push-switch" +#define DRV_VERSION "0.1.0" + +static ssize_t switch_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct push_switch_platform_info *psw_info = dev->platform_data; + return sprintf(buf, "%s\n", psw_info->name); +} +static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL); + +static void switch_timer(unsigned long data) +{ + struct push_switch *psw = (struct push_switch *)data; + + schedule_work(&psw->work); +} + +static void switch_work_handler(void *data) +{ + struct platform_device *pdev = data; + struct push_switch *psw = platform_get_drvdata(pdev); + + psw->state = 0; + + kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE); +} + +static int switch_drv_probe(struct platform_device *pdev) +{ + struct push_switch_platform_info *psw_info; + struct push_switch *psw; + int ret, irq; + + psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL); + if (unlikely(!psw)) + return -ENOMEM; + + irq = platform_get_irq(pdev, 0); + if (unlikely(irq < 0)) { + ret = -ENODEV; + goto err; + } + + psw_info = pdev->dev.platform_data; + BUG_ON(!psw_info); + + ret = request_irq(irq, psw_info->irq_handler, + IRQF_DISABLED | psw_info->irq_flags, + psw_info->name ? psw_info->name : DRV_NAME, pdev); + if (unlikely(ret < 0)) + goto err; + + if (psw_info->name) { + ret = device_create_file(&pdev->dev, &dev_attr_switch); + if (unlikely(ret)) { + dev_err(&pdev->dev, "Failed creating device attrs\n"); + ret = -EINVAL; + goto err_irq; + } + } + + INIT_WORK(&psw->work, switch_work_handler, pdev); + init_timer(&psw->debounce); + + psw->debounce.function = switch_timer; + psw->debounce.data = (unsigned long)psw; + + platform_set_drvdata(pdev, psw); + + return 0; + +err_irq: + free_irq(irq, pdev); +err: + kfree(psw); + return ret; +} + +static int switch_drv_remove(struct platform_device *pdev) +{ + struct push_switch *psw = platform_get_drvdata(pdev); + struct push_switch_platform_info *psw_info = pdev->dev.platform_data; + int irq = platform_get_irq(pdev, 0); + + if (psw_info->name) + device_remove_file(&pdev->dev, &dev_attr_switch); + + platform_set_drvdata(pdev, NULL); + flush_scheduled_work(); + del_timer_sync(&psw->debounce); + free_irq(irq, pdev); + + kfree(psw); + + return 0; +} + +static struct platform_driver switch_driver = { + .probe = switch_drv_probe, + .remove = switch_drv_remove, + .driver = { + .name = DRV_NAME, + }, +}; + +static int __init switch_init(void) +{ + printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION); + return platform_driver_register(&switch_driver); +} + +static void __exit switch_exit(void) +{ + platform_driver_unregister(&switch_driver); +} +module_init(switch_init); +module_exit(switch_exit); + +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Paul Mundt"); +MODULE_LICENSE("GPLv2"); diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 5da88a43d35..99c7e5249f7 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -4,7 +4,7 @@ extra-y := head.o init_task.o vmlinux.lds -obj-y := process.o signal.o entry.o traps.o irq.o \ +obj-y := process.o signal.o traps.o irq.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ io.o io_generic.o sh_ksyms.o syscalls.o @@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index fb5dac06938..0582e6712b7 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -2,11 +2,12 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y += irq/ init.o clock.o - -obj-$(CONFIG_CPU_SH2) += sh2/ -obj-$(CONFIG_CPU_SH3) += sh3/ -obj-$(CONFIG_CPU_SH4) += sh4/ +obj-$(CONFIG_CPU_SH2) = sh2/ +obj-$(CONFIG_CPU_SH2A) = sh2a/ +obj-$(CONFIG_CPU_SH3) = sh3/ +obj-$(CONFIG_CPU_SH4) = sh4/ obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o + +obj-y += irq/ init.o clock.o diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 51ec64cdf34..abb586b1256 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -5,9 +5,11 @@ * * This clock framework is derived from the OMAP version by: * - * Copyright (C) 2004 Nokia Corporation + * Copyright (C) 2004 - 2005 Nokia Corporation * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> * + * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> + * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -20,6 +22,7 @@ #include <linux/kref.h> #include <linux/seq_file.h> #include <linux/err.h> +#include <linux/platform_device.h> #include <asm/clock.h> #include <asm/timer.h> @@ -195,17 +198,37 @@ void clk_recalc_rate(struct clk *clk) propagate_rate(clk); } -struct clk *clk_get(const char *id) +/* + * Returns a clock. Note that we first try to use device id on the bus + * and clock name. If this fails, we try to use clock name only. + */ +struct clk *clk_get(struct device *dev, const char *id) { struct clk *p, *clk = ERR_PTR(-ENOENT); + int idno; + + if (dev == NULL || dev->bus != &platform_bus_type) + idno = -1; + else + idno = to_platform_device(dev)->id; mutex_lock(&clock_list_sem); list_for_each_entry(p, &clock_list, node) { + if (p->id == idno && + strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + goto found; + } + } + + list_for_each_entry(p, &clock_list, node) { if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; break; } } + +found: mutex_unlock(&clock_list_sem); return clk; diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index bfb90eb0b7a..48121766e8d 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -68,12 +68,14 @@ static void __init cache_init(void) waysize = cpu_data->dcache.sets; +#ifdef CCR_CACHE_ORA /* * If the OC is already in RAM mode, we only have * half of the entries to flush.. */ if (ccr & CCR_CACHE_ORA) waysize >>= 1; +#endif waysize <<= cpu_data->dcache.entry_shift; diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile index 1c034c283f5..0049d217561 100644 --- a/arch/sh/kernel/cpu/irq/Makefile +++ b/arch/sh/kernel/cpu/irq/Makefile @@ -1,8 +1,9 @@ # # Makefile for the Linux/SuperH CPU-specifc IRQ handlers. # -obj-y += ipr.o imask.o +obj-y += imask.o +obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c index a33ae3e0a5a..301b505c427 100644 --- a/arch/sh/kernel/cpu/irq/imask.c +++ b/arch/sh/kernel/cpu/irq/imask.c @@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip) { unsigned long __dummy; - asm volatile("ldc %2, r6_bank\n\t" + asm volatile( +#ifdef CONFIG_CPU_HAS_SR_RB + "ldc %2, r6_bank\n\t" +#endif "stc sr, %0\n\t" "and #0xf0, %0\n\t" "shlr2 %0\n\t" diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index 74ca576a7ce..74defe76a05 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -11,22 +11,29 @@ * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ #include <linux/kernel.h> -#include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/io.h> -#include <asm/system.h> + +#if defined(CONFIG_CPU_SUBTYPE_SH7760) +#define INTC2_BASE 0xfe080000 +#define INTC2_INTMSK (INTC2_BASE + 0x40) +#define INTC2_INTMSKCLR (INTC2_BASE + 0x60) +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +#define INTC2_BASE 0xffd40000 +#define INTC2_INTMSK (INTC2_BASE + 0x38) +#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c) +#endif static void disable_intc2_irq(unsigned int irq) { struct intc2_data *p = get_irq_chip_data(irq); - ctrl_outl(1 << p->msk_shift, - INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); + ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset); } static void enable_intc2_irq(unsigned int irq) { struct intc2_data *p = get_irq_chip_data(irq); - ctrl_outl(1 << p->msk_shift, - INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); + ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset); } static struct irq_chip intc2_irq_chip = { @@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs) /* Set the priority level */ local_irq_save(flags); - ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + - p->ipr_offset); + ipr = ctrl_inl(INTC2_BASE + p->ipr_offset); ipr &= ~(0xf << p->ipr_shift); ipr |= p->priority << p->ipr_shift; - ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + - p->ipr_offset); + ctrl_outl(ipr, INTC2_BASE + p->ipr_offset); local_irq_restore(flags); diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index a0089563cbf..35eb5751a3a 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -19,25 +19,21 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/module.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/machvec.h> - +#include <linux/io.h> +#include <linux/interrupt.h> static void disable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); - int shift = p->shift*4; /* Set the priority in IPR to 0 */ - ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); + ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); } static void enable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); - int shift = p->shift*4; /* Set priority in IPR back to original value */ - ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); + ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); } static struct irq_chip ipr_irq_chip = { @@ -53,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) for (i = 0; i < nr_irqs; i++) { unsigned int irq = table[i].irq; + table[i].addr = map_ipridx_to_addr(table[i].ipr_idx); + /* could the IPR index be mapped, if not we ignore this */ + if (table[i].addr == 0) + continue; disable_irq_nosync(irq); set_irq_chip_and_handler_name(irq, &ipr_irq_chip, handle_level_irq, "level"); @@ -62,83 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) } EXPORT_SYMBOL(make_ipr_irq); -static struct ipr_data sys_ipr_map[] = { -#ifndef CONFIG_CPU_SUBTYPE_SH7780 - { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, - { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY }, -#ifdef RTC_IRQ - { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY }, -#endif -#ifdef SCI_ERI_IRQ - { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, - { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, - { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, -#endif -#ifdef SCIF1_ERI_IRQ - { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) - { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, - { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, - { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, - { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, -#endif -#ifdef SCIF_ERI_IRQ - { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, -#endif -#ifdef IRDA_ERI_IRQ - { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) - /* - * Initialize the Interrupt Controller (INTC) - * registers to their power on values - */ - - /* - * Enable external irq (INTC IRQ mode). - * You should set corresponding bits of PFC to "00" - * to enable these interrupts. - */ - { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY }, - { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, - { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, - { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY }, - { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY }, - { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY }, -#endif -#endif -}; - -void __init init_IRQ(void) -{ - make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map)); - -#ifdef CONFIG_CPU_HAS_PINT_IRQ - init_IRQ_pint(); -#endif - -#ifdef CONFIG_CPU_HAS_INTC2_IRQ - init_IRQ_intc2(); -#endif - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) - sh_mv.mv_init_irq(); - - irq_ctx_init(smp_processor_id()); -} - #if !defined(CONFIG_CPU_HAS_PINT_IRQ) int ipr_irq_demux(int irq) { diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile index 389353fba60..f0f059acfcf 100644 --- a/arch/sh/kernel/cpu/sh2/Makefile +++ b/arch/sh/kernel/cpu/sh2/Makefile @@ -2,5 +2,6 @@ # Makefile for the Linux/SuperH SH-2 backends. # -obj-y := probe.o +obj-y := ex.o probe.o entry.o +obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c new file mode 100644 index 00000000000..d0440b26970 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c @@ -0,0 +1,81 @@ +/* + * arch/sh/kernel/cpu/sh2/clock-sh7619.c + * + * SH7619 support for the clock framework + * + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +const static int pll1rate[]={1,2}; +const static int pfc_divisors[]={1,2,0,4}; + +#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6) +#define PLL2 (2) +#else +#error "Illigal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; +} + +static struct clk_ops sh7619_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7619_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; +} + +static struct clk_ops sh7619_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate; +} + +static struct clk_ops sh7619_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7619_clk_ops[] = { + &sh7619_master_clk_ops, + &sh7619_module_clk_ops, + &sh7619_bus_clk_ops, + &sh7619_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7619_clk_ops)) + *ops = sh7619_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S new file mode 100644 index 00000000000..34d51b3745e --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/entry.S @@ -0,0 +1,341 @@ +/* + * arch/sh/kernel/cpu/sh2/entry.S + * + * The SH-2 exception entry + * + * Copyright (C) 2005,2006 Yoshinori Sato + * Copyright (C) 2005 AXE,Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/thread_info.h> +#include <asm/cpu/mmu_context.h> +#include <asm/unistd.h> +#include <asm/errno.h> +#include <asm/page.h> + +/* Offsets to the stack */ +OFF_R0 = 0 /* Return value. New ABI also arg4 */ +OFF_R1 = 4 /* New ABI: arg5 */ +OFF_R2 = 8 /* New ABI: arg6 */ +OFF_R3 = 12 /* New ABI: syscall_nr */ +OFF_R4 = 16 /* New ABI: arg0 */ +OFF_R5 = 20 /* New ABI: arg1 */ +OFF_R6 = 24 /* New ABI: arg2 */ +OFF_R7 = 28 /* New ABI: arg3 */ +OFF_SP = (15*4) +OFF_PC = (16*4) +OFF_SR = (16*4+2*4) +OFF_TRA = (16*4+6*4) + +#include <asm/entry-macros.S> + +ENTRY(exception_handler) + ! already saved r0/r1 + mov.l r2,@-sp + mov.l r3,@-sp + mov r0,r1 + cli + mov.l $cpu_mode,r2 + mov.l @r2,r0 + mov.l @(5*4,r15),r3 ! previous SR + shll2 r3 ! set "S" flag + rotl r0 ! T <- "S" flag + rotl r0 ! "S" flag is LSB + rotcr r3 ! T -> r3:b30 + shlr r3 + shlr r0 + bt/s 1f + mov.l r3,@(5*4,r15) ! copy cpu mode to SR + ! switch to kernel mode + mov #1,r0 + rotr r0 + rotr r0 + mov.l r0,@r2 ! enter kernel mode + mov.l $current_thread_info,r2 + mov.l @r2,r2 + mov #0x20,r0 + shll8 r0 + add r2,r0 + mov r15,r2 ! r2 = user stack top + mov r0,r15 ! switch kernel stack + add #-4,r15 ! dummy + mov.l r1,@-r15 ! TRA + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + mov.l @(4*4,r2),r0 + mov.l @(5*4,r2),r1 + mov.l r1,@-r15 ! original SR + sts.l pr,@-r15 + mov.l r0,@-r15 ! original PC + mov r2,r3 + add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame + mov.l r3,@-r15 ! original SP + mov.l r14,@-r15 + mov.l r13,@-r15 + mov.l r12,@-r15 + mov.l r11,@-r15 + mov.l r10,@-r15 + mov.l r9,@-r15 + mov.l r8,@-r15 + mov.l r7,@-r15 + mov.l r6,@-r15 + mov.l r5,@-r15 + mov.l r4,@-r15 + mov r2,r8 ! copy user -> kernel stack + mov.l @r8+,r3 + mov.l r3,@-r15 + mov.l @r8+,r2 + mov.l r2,@-r15 + mov.l @r8+,r1 + mov.l r1,@-r15 + mov.l @r8+,r0 + bra 2f + mov.l r0,@-r15 +1: + ! in kernel exception + mov #(22-4-4-1)*4+4,r0 + mov r15,r2 + sub r0,r15 + mov.l @r2+,r0 ! old R3 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R2 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R1 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R0 + mov.l r0,@-r15 + mov.l @r2+,r3 ! old PC + mov.l @r2+,r0 ! old SR + add #-4,r2 ! exception frame stub (sr) + mov.l r1,@-r2 ! TRA + sts.l macl, @-r2 + sts.l mach, @-r2 + stc.l gbr, @-r2 + mov.l r0,@-r2 ! save old SR + sts.l pr,@-r2 + mov.l r3,@-r2 ! save old PC + mov r2,r0 + add #8*4,r0 + mov.l r0,@-r2 ! save old SP + mov.l r14,@-r2 + mov.l r13,@-r2 + mov.l r12,@-r2 + mov.l r11,@-r2 + mov.l r10,@-r2 + mov.l r9,@-r2 + mov.l r8,@-r2 + mov.l r7,@-r2 + mov.l r6,@-r2 + mov.l r5,@-r2 + mov.l r4,@-r2 + mov.l @(OFF_R0,r15),r0 + mov.l @(OFF_R1,r15),r1 + mov.l @(OFF_R2,r15),r2 + mov.l @(OFF_R3,r15),r3 +2: + mov #OFF_TRA,r8 + add r15,r8 + mov.l @r8,r9 + mov #64,r8 + cmp/hs r8,r9 + bt interrupt_entry ! vec >= 64 is interrupt + mov #32,r8 + cmp/hs r8,r9 + bt trap_entry ! 64 > vec >= 32 is trap + mov.l 4f,r8 + mov r9,r4 + shll2 r9 + add r9,r8 + mov.l @r8,r8 + mov #0,r9 + cmp/eq r9,r8 + bf 3f + mov.l 8f,r8 ! unhandled exception +3: + mov.l 5f,r10 + jmp @r8 + lds r10,pr + +interrupt_entry: + mov r9,r4 + mov.l 6f,r9 + mov.l 7f,r8 + jmp @r8 + lds r9,pr + + .align 2 +4: .long exception_handling_table +5: .long ret_from_exception +6: .long ret_from_irq +7: .long do_IRQ +8: .long do_exception_error + +trap_entry: + add #-0x10,r9 + shll2 r9 ! TRA + mov #OFF_TRA,r8 + add r15,r8 + mov.l r9,@r8 + mov r9,r8 +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r9 + jsr @r9 + nop +#endif + sti + bra system_call + nop + + .align 2 +1: .long syscall_exit +2: .long break_point_trap_software +3: .long NR_syscalls +4: .long sys_call_table +#ifdef CONFIG_TRACE_IRQFLAGS +5: .long trace_hardirqs_on +#endif + +#if defined(CONFIG_SH_STANDARD_BIOS) + /* Unwind the stack and jmp to the debug entry */ +debug_kernel_fw: + mov r15,r0 + add #(22-4)*4-4,r0 + ldc.l @r0+,gbr + lds.l @r0+,mach + lds.l @r0+,macl + mov r15,r0 + mov.l @(OFF_SP,r0),r1 + mov #OFF_SR,r2 + mov.l @(r0,r2),r3 + mov.l r3,@-r1 + mov #OFF_SP,r2 + mov.l @(r0,r2),r3 + mov.l r3,@-r1 + mov r15,r0 + add #(22-4)*4-8,r0 + mov.l 1f,r2 + mov.l @r2,r2 + stc sr,r3 + mov.l r2,@r0 + mov.l r3,@r0 + mov.l r1,@(8,r0) + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + add #8,r15 + lds.l @r15+, pr + rte + mov.l @r15+,r15 + .align 2 +1: .long gdb_vbr_vector +#endif /* CONFIG_SH_STANDARD_BIOS */ + +ENTRY(address_error_handler) + mov r15,r4 ! regs + add #4,r4 + mov #OFF_PC,r0 + mov.l @(r0,r15),r6 ! pc + mov.l 1f,r0 + jmp @r0 + mov #0,r5 ! writeaccess is unknown + .align 2 + +1: .long do_address_error + +restore_all: + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 3f, r0 + jsr @r0 + nop +#endif + mov r15,r0 + mov.l $cpu_mode,r2 + mov #OFF_SR,r3 + mov.l @(r0,r3),r1 + mov.l r1,@r2 + shll2 r1 ! clear MD bit + shlr2 r1 + mov.l @(OFF_SP,r0),r2 + add #-8,r2 + mov.l r2,@(OFF_SP,r0) ! point exception frame top + mov.l r1,@(4,r2) ! set sr + mov #OFF_PC,r3 + mov.l @(r0,r3),r1 + mov.l r1,@r2 ! set pc + add #4*16+4,r0 + lds.l @r0+,pr + add #4,r0 ! skip sr + ldc.l @r0+,gbr + lds.l @r0+,mach + lds.l @r0+,macl + get_current_thread_info r0, r1 + mov.l $current_thread_info,r1 + mov.l r0,@r1 + mov.l @r15+,r0 + mov.l @r15+,r1 + mov.l @r15+,r2 + mov.l @r15+,r3 + mov.l @r15+,r4 + mov.l @r15+,r5 + mov.l @r15+,r6 + mov.l @r15+,r7 + mov.l @r15+,r8 + mov.l @r15+,r9 + mov.l @r15+,r10 + mov.l @r15+,r11 + mov.l @r15+,r12 + mov.l @r15+,r13 + mov.l @r15+,r14 + mov.l @r15,r15 + rte + nop +2: + mov.l 1f,r8 + mov.l 2f,r9 + jmp @r9 + lds r8,pr + + .align 2 +$current_thread_info: + .long __current_thread_info +$cpu_mode: + .long __cpu_mode +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_off +#endif + +! common exception handler +#include "../../entry-common.S" + + .data +! cpu operation mode +! bit30 = MD (compatible SH3/4) +__cpu_mode: + .long 0x40000000 + + .section .bss +__current_thread_info: + .long 0 + +ENTRY(exception_handling_table) + .space 4*32 diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S new file mode 100644 index 00000000000..6d285af7846 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/ex.S @@ -0,0 +1,46 @@ +/* + * arch/sh/kernel/cpu/sh2/ex.S + * + * The SH-2 exception vector table + * + * Copyright (C) 2005 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/linkage.h> + +! +! convert Exception Vector to Exception Number +! +exception_entry: +no = 0 + .rept 256 + mov.l r0,@-sp + mov #no,r0 + bra exception_trampoline + and #0xff,r0 +no = no + 1 + .endr +exception_trampoline: + mov.l r1,@-sp + mov.l $exception_handler,r1 + jmp @r1 + + .align 2 +$exception_entry: + .long exception_entry +$exception_handler: + .long exception_handler +! +! Exception Vector Base +! + .align 2 +ENTRY(vbr_base) +vector = 0 + .rept 256 + .long exception_entry + vector * 8 +vector = vector + 1 + .endr diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index f17a2a0d588..ba527d9b502 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -17,17 +17,23 @@ int __init detect_cpu_and_cache_system(void) { - /* - * For now, assume SH7604 .. fix this later. - */ +#if defined(CONFIG_CPU_SUBTYPE_SH7604) cpu_data->type = CPU_SH7604; cpu_data->dcache.ways = 4; - cpu_data->dcache.way_shift = 6; + cpu_data->dcache.way_incr = (1<<10); cpu_data->dcache.sets = 64; cpu_data->dcache.entry_shift = 4; cpu_data->dcache.linesz = L1_CACHE_BYTES; cpu_data->dcache.flags = 0; - +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) + cpu_data->type = CPU_SH7619; + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_incr = (1<<12); + cpu_data->dcache.sets = 256; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; +#endif /* * SH-2 doesn't have separate caches */ diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c new file mode 100644 index 00000000000..82c2d905152 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -0,0 +1,53 @@ +/* + * SH7619 Setup + * + * Copyright (C) 2006 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial.h> +#include <asm/sci.h> + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xf8400000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 88, 89, 91, 90}, + }, { + .mapbase = 0xf8410000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 92, 93, 95, 94}, + }, { + .mapbase = 0xf8420000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 96, 97, 99, 98}, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7619_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7619_devices_setup(void) +{ + return platform_add_devices(sh7619_devices, + ARRAY_SIZE(sh7619_devices)); +} +__initcall(sh7619_devices_setup); diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile new file mode 100644 index 00000000000..350972ae941 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the Linux/SuperH SH-2A backends. +# + +obj-y := common.o probe.o + +common-y += $(addprefix ../sh2/, ex.o) +common-y += $(addprefix ../sh2/, entry.o) + +obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c new file mode 100644 index 00000000000..a9ad309c6a3 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c @@ -0,0 +1,85 @@ +/* + * arch/sh/kernel/cpu/sh2a/clock-sh7206.c + * + * SH7206 support for the clock framework + * + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +const static int pll1rate[]={1,2,3,4,6,8}; +const static int pfc_divisors[]={1,2,3,4,6,8,12}; +#define ifc_divisors pfc_divisors + +#if (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 6) +#define PLL2 (2) +#elif (CONFIG_SH_CLK_MD == 7) +#define PLL2 (1) +#else +#error "Illigal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7206_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7206_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7206_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7206_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7206_clk_ops[] = { + &sh7206_master_clk_ops, + &sh7206_module_clk_ops, + &sh7206_bus_clk_ops, + &sh7206_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7206_clk_ops)) + *ops = sh7206_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c new file mode 100644 index 00000000000..87c6c054208 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/probe.c @@ -0,0 +1,39 @@ +/* + * arch/sh/kernel/cpu/sh2a/probe.c + * + * CPU Subtype Probing for SH-2A. + * + * Copyright (C) 2004, 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/init.h> +#include <asm/processor.h> +#include <asm/cache.h> + +int __init detect_cpu_and_cache_system(void) +{ + /* Just SH7206 for now .. */ + cpu_data->type = CPU_SH7206; + + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_incr = (1 << 11); + cpu_data->dcache.sets = 128; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; + + /* + * The icache is the same as the dcache as far as this setup is + * concerned. The only real difference in hardware is that the icache + * lacks the U bit that the dcache has, none of this has any bearing + * on the cache info. + */ + cpu_data->icache = cpu_data->dcache; + + return 0; +} + diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c new file mode 100644 index 00000000000..cdfeef49e62 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -0,0 +1,58 @@ +/* + * SH7206 Setup + * + * Copyright (C) 2006 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial.h> +#include <asm/sci.h> + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xfffe8000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 240, 241, 242, 243}, + }, { + .mapbase = 0xfffe8800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 244, 245, 246, 247}, + }, { + .mapbase = 0xfffe9000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 248, 249, 250, 251}, + }, { + .mapbase = 0xfffe9800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 252, 253, 254, 255}, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7206_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7206_devices_setup(void) +{ + return platform_add_devices(sh7206_devices, + ARRAY_SIZE(sh7206_devices)); +} +__initcall(sh7206_devices_setup); diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 58d3815695f..83905e4e438 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o probe.o +obj-y := ex.o probe.o entry.o # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c index 10461a745e5..b791a29fdb6 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh7709.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c @@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; static void set_bus_parent(struct clk *clk) { - struct clk *bus_clk = clk_get("bus_clk"); + struct clk *bus_clk = clk_get(NULL, "bus_clk"); clk->parent = bus_clk; clk_put(bus_clk); } diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 39aaefb2d83..8c0dc2700c6 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -1,5 +1,5 @@ /* - * linux/arch/sh/entry.S + * arch/sh/kernel/entry.S * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2003 - 2006 Paul Mundt @@ -7,15 +7,16 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. - * */ #include <linux/sys.h> #include <linux/errno.h> #include <linux/linkage.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> -#include <asm/cpu/mmu_context.h> #include <asm/unistd.h> +#include <asm/cpu/mmu_context.h> +#include <asm/pgtable.h> +#include <asm/page.h> ! NOTE: ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address @@ -81,6 +82,8 @@ OFF_TRA = (16*4+6*4) #define k_g_imask r6_bank /* r6_bank1 */ #define current r7 /* r7_bank1 */ +#include <asm/entry-macros.S> + /* * Kernel mode register usage: * k0 scratch @@ -107,26 +110,6 @@ OFF_TRA = (16*4+6*4) ! this first version depends *much* on C implementation. ! -#define CLI() \ - stc sr, r0; \ - or #0xf0, r0; \ - ldc r0, sr - -#define STI() \ - mov.l __INV_IMASK, r11; \ - stc sr, r10; \ - and r11, r10; \ - stc k_g_imask, r11; \ - or r11, r10; \ - ldc r10, sr - -#if defined(CONFIG_PREEMPT) -# define preempt_stop() CLI() -#else -# define preempt_stop() -# define resume_kernel restore_all -#endif - #if defined(CONFIG_MMU) .align 2 ENTRY(tlb_miss_load) @@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store) call_dpf: mov.l 1f, r0 - mov r5, r8 - mov.l @r0, r6 - mov r6, r9 - mov.l 2f, r0 - sts pr, r10 - jsr @r0 - mov r15, r4 - ! - tst r0, r0 - bf/s 0f - lds r10, pr - rts - nop -0: STI() + mov.l @r0, r6 ! address mov.l 3f, r0 - mov r9, r6 - mov r8, r5 + jmp @r0 - mov r15, r4 + mov r15, r4 ! regs .align 2 1: .long MMU_TEA -2: .long __do_page_fault 3: .long do_page_fault .align 2 @@ -203,32 +171,6 @@ call_dae: 2: .long do_address_error #endif /* CONFIG_MMU */ -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. -! If both are configured, handle the debug traps (breakpoints) in SW, -! but still allow BIOS traps to FW. - - .align 2 -debug_kernel: -#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) - /* Force BIOS call to FW (debug_trap put TRA in r8) */ - mov r8,r0 - shlr2 r0 - cmp/eq #0x3f,r0 - bt debug_kernel_fw -#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ - -debug_enter: -#if defined(CONFIG_SH_KGDB) - /* Jump to kgdb, pass stacked regs as arg */ -debug_kernel_sw: - mov.l 3f, r0 - jmp @r0 - mov r15, r4 - .align 2 -3: .long kgdb_handle_exception -#endif /* CONFIG_SH_KGDB */ - #if defined(CONFIG_SH_STANDARD_BIOS) /* Unwind the stack and jmp to the debug entry */ debug_kernel_fw: @@ -269,276 +211,6 @@ debug_kernel_fw: 2: .long gdb_vbr_vector #endif /* CONFIG_SH_STANDARD_BIOS */ -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ - - - .align 2 -debug_trap: -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s debug_kernel -#endif - mov.l @r15, r0 ! Restore R0 value - mov.l 1f, r8 - jmp @r8 - nop - - .align 2 -ENTRY(exception_error) - ! - STI() - mov.l 2f, r0 - jmp @r0 - nop - -! - .align 2 -1: .long break_point_trap_software -2: .long do_exception_error - - .align 2 -ret_from_exception: - preempt_stop() -ENTRY(ret_from_irq) - ! - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s resume_kernel ! Yes, it's from kernel, go back soon - GET_THREAD_INFO(r8) - -#ifdef CONFIG_PREEMPT - bra resume_userspace - nop -ENTRY(resume_kernel) - mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count - tst r0, r0 - bf noresched -need_resched: - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_NEED_RESCHED, r0 ! need_resched set? - bt noresched - - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - and #0xf0, r0 ! interrupts off (exception path)? - cmp/eq #0xf0, r0 - bt noresched - - mov.l 1f, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - - STI() - mov.l 2f, r0 - jsr @r0 - nop - mov #0, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - CLI() - - bra need_resched - nop -noresched: - bra restore_all - nop - - .align 2 -1: .long PREEMPT_ACTIVE -2: .long schedule -#endif - -ENTRY(resume_userspace) - ! r8: current_thread_info - CLI() - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 - bt/s restore_all - tst #_TIF_NEED_RESCHED, r0 - - .align 2 -work_pending: - ! r0: current_thread_info->flags - ! r8: current_thread_info - ! t: result of "tst #_TIF_NEED_RESCHED, r0" - bf/s work_resched - tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 -work_notifysig: - bt/s restore_all - mov r15, r4 - mov r12, r5 ! set arg1(save_r0) - mov r0, r6 - mov.l 2f, r1 - mova restore_all, r0 - jmp @r1 - lds r0, pr -work_resched: -#ifndef CONFIG_PREEMPT - ! gUSA handling - mov.l @(OFF_SP,r15), r0 ! get user space stack pointer - mov r0, r1 - shll r0 - bf/s 1f - shll r0 - bf/s 1f - mov #OFF_PC, r0 - ! SP >= 0xc0000000 : gUSA mark - mov.l @(r0,r15), r2 ! get user space PC (program counter) - mov.l @(OFF_R0,r15), r3 ! end point - cmp/hs r3, r2 ! r2 >= r3? - bt 1f - add r3, r1 ! rewind point #2 - mov.l r1, @(r0,r15) ! reset PC to rewind point #2 - ! -1: -#endif - mov.l 1f, r1 - jsr @r1 ! schedule - nop - CLI() - ! - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 - bt restore_all - bra work_pending - tst #_TIF_NEED_RESCHED, r0 - - .align 2 -1: .long schedule -2: .long do_notify_resume - - .align 2 -syscall_exit_work: - ! r0: current_thread_info->flags - ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE, r0 - bt/s work_pending - tst #_TIF_NEED_RESCHED, r0 - STI() - ! XXX setup arguments... - mov.l 4f, r0 ! do_syscall_trace - jsr @r0 - nop - bra resume_userspace - nop - - .align 2 -syscall_trace_entry: - ! Yes it is traced. - ! XXX setup arguments... - mov.l 4f, r11 ! Call do_syscall_trace which notifies - jsr @r11 ! superior (will chomp R[0-7]) - nop - ! Reload R0-R4 from kernel stack, where the - ! parent may have modified them using - ! ptrace(POKEUSR). (Note that R0-R2 are - ! used by the system call handler directly - ! from the kernel stack anyway, so don't need - ! to be reloaded here.) This allows the parent - ! to rewrite system calls and args on the fly. - mov.l @(OFF_R4,r15), r4 ! arg0 - mov.l @(OFF_R5,r15), r5 - mov.l @(OFF_R6,r15), r6 - mov.l @(OFF_R7,r15), r7 ! arg3 - mov.l @(OFF_R3,r15), r3 ! syscall_nr - ! Arrange for do_syscall_trace to be called - ! again as the system call returns. - mov.l 2f, r10 ! Number of syscalls - cmp/hs r10, r3 - bf syscall_call - mov #-ENOSYS, r0 - bra syscall_exit - mov.l r0, @(OFF_R0,r15) ! Return value - -/* - * Syscall interface: - * - * Syscall #: R3 - * Arguments #0 to #3: R4--R7 - * Arguments #4 to #6: R0, R1, R2 - * TRA: (number of arguments + 0x10) x 4 - * - * This code also handles delegating other traps to the BIOS/gdb stub - * according to: - * - * Trap number - * (TRA>>2) Purpose - * -------- ------- - * 0x0-0xf old syscall ABI - * 0x10-0x1f new syscall ABI - * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. - * - * Note: When we're first called, the TRA value must be shifted - * right 2 bits in order to get the value that was used as the "trapa" - * argument. - */ - - .align 2 - .globl ret_from_fork -ret_from_fork: - mov.l 1f, r8 - jsr @r8 - mov r0, r4 - bra syscall_exit - nop - .align 2 -1: .long schedule_tail - ! -ENTRY(system_call) - mov.l 1f, r9 - mov.l @r9, r8 ! Read from TRA (Trap Address) Register - ! - ! Is the trap argument >= 0x20? (TRA will be >= 0x80) - mov #0x7f, r9 - cmp/hi r9, r8 - bt/s 0f - mov #OFF_TRA, r9 - add r15, r9 - ! - mov.l r8, @r9 ! set TRA value to tra - STI() - ! Call the system call handler through the table. - ! First check for bad syscall number - mov r3, r9 - mov.l 2f, r8 ! Number of syscalls - cmp/hs r8, r9 - bf/s good_system_call - GET_THREAD_INFO(r8) -syscall_badsys: ! Bad syscall number - mov #-ENOSYS, r0 - bra resume_userspace - mov.l r0, @(OFF_R0,r15) ! Return value - ! -0: - bra debug_trap - nop - ! -good_system_call: ! Good syscall number - mov.l @(TI_FLAGS,r8), r8 - mov #_TIF_SYSCALL_TRACE, r10 - tst r10, r8 - bf syscall_trace_entry - ! -syscall_call: - shll2 r9 ! x4 - mov.l 3f, r8 ! Load the address of sys_call_table - add r8, r9 - mov.l @r9, r8 - jsr @r8 ! jump to specific syscall handler - nop - mov.l @(OFF_R0,r15), r12 ! save r0 - mov.l r0, @(OFF_R0,r15) ! save the return value - ! -syscall_exit: - CLI() - ! - GET_THREAD_INFO(r8) - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_ALLWORK_MASK, r0 - bf syscall_exit_work restore_all: mov.l @r15+, r0 mov.l @r15+, r1 @@ -606,7 +278,9 @@ skip_restore: ! ! Calculate new SR value mov k3, k2 ! original SR value - mov.l 9f, k1 + mov #0xf0, k1 + extu.b k1, k1 + not k1, k1 and k1, k2 ! Mask orignal SR value ! mov k3, k0 ! Calculate IMASK-bits @@ -632,16 +306,12 @@ skip_restore: nop .align 2 -1: .long TRA -2: .long NR_syscalls -3: .long sys_call_table -4: .long do_syscall_trace 5: .long 0x00001000 ! DSP 7: .long 0x30000000 -9: -__INV_IMASK: - .long 0xffffff0f ! ~(IMASK) +! common exception handler +#include "../../entry-common.S" + ! Exception Vector Base ! ! Should be aligned page boundary. @@ -661,9 +331,176 @@ general_exception: 2: .long ret_from_exception ! ! + +/* This code makes some assumptions to improve performance. + * Make sure they are stil true. */ +#if PTRS_PER_PGD != PTRS_PER_PTE +#error PGD and PTE sizes don't match +#endif + +/* gas doesn't flag impossible values for mov #immediate as an error */ +#if (_PAGE_PRESENT >> 2) > 0x7f +#error cannot load PAGE_PRESENT as an immediate +#endif +#if _PAGE_DIRTY > 0x7f +#error cannot load PAGE_DIRTY as an immediate +#endif +#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED +#error cannot derive PAGE_ACCESSED from PAGE_PRESENT +#endif + +#if defined(CONFIG_CPU_SH4) +#define ldmmupteh(r) mov.l 8f, r +#else +#define ldmmupteh(r) mov #MMU_PTEH, r +#endif + .balign 1024,0,1024 tlb_miss: - mov.l 1f, k2 +#ifdef COUNT_EXCEPTIONS + ! Increment the counts + mov.l 9f, k1 + mov.l @k1, k2 + add #1, k2 + mov.l k2, @k1 +#endif + + ! k0 scratch + ! k1 pgd and pte pointers + ! k2 faulting address + ! k3 pgd and pte index masks + ! k4 shift + + ! Load up the pgd entry (k1) + + ldmmupteh(k0) ! 9 LS (latency=2) MMU_PTEH + + mov.w 4f, k3 ! 8 LS (latency=2) (PTRS_PER_PGD-1) << 2 + mov #-(PGDIR_SHIFT-2), k4 ! 6 EX + + mov.l @(MMU_TEA-MMU_PTEH,k0), k2 ! 18 LS (latency=2) + + mov.l @(MMU_TTB-MMU_PTEH,k0), k1 ! 18 LS (latency=2) + + mov k2, k0 ! 5 MT (latency=0) + shld k4, k0 ! 99 EX + + and k3, k0 ! 78 EX + + mov.l @(k0, k1), k1 ! 21 LS (latency=2) + mov #-(PAGE_SHIFT-2), k4 ! 6 EX + + ! Load up the pte entry (k2) + + mov k2, k0 ! 5 MT (latency=0) + shld k4, k0 ! 99 EX + + tst k1, k1 ! 86 MT + + bt 20f ! 110 BR + + and k3, k0 ! 78 EX + mov.w 5f, k4 ! 8 LS (latency=2) _PAGE_PRESENT + + mov.l @(k0, k1), k2 ! 21 LS (latency=2) + add k0, k1 ! 49 EX + +#ifdef CONFIG_CPU_HAS_PTEA + ! Test the entry for present and _PAGE_ACCESSED + + mov #-28, k3 ! 6 EX + mov k2, k0 ! 5 MT (latency=0) + + tst k4, k2 ! 68 MT + shld k3, k0 ! 99 EX + + bt 20f ! 110 BR + + ! Set PTEA register + ! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1) + ! + ! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT + + and #0xe, k0 ! 79 EX + + mov k0, k3 ! 5 MT (latency=0) + mov k2, k0 ! 5 MT (latency=0) + + and #1, k0 ! 79 EX + + or k0, k3 ! 82 EX + + ldmmupteh(k0) ! 9 LS (latency=2) + shll2 k4 ! 101 EX _PAGE_ACCESSED + + tst k4, k2 ! 68 MT + + mov.l k3, @(MMU_PTEA-MMU_PTEH,k0) ! 27 LS + + mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK + + ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED +#else + + ! Test the entry for present and _PAGE_ACCESSED + + mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK + tst k4, k2 ! 68 MT + + shll2 k4 ! 101 EX _PAGE_ACCESSED + ldmmupteh(k0) ! 9 LS (latency=2) + + bt 20f ! 110 BR + tst k4, k2 ! 68 MT + + ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED + +#endif + + ! Set up the entry + + and k2, k3 ! 78 EX + bt/s 10f ! 108 BR + + mov.l k3, @(MMU_PTEL-MMU_PTEH,k0) ! 27 LS + + ldtlb ! 128 CO + + ! At least one instruction between ldtlb and rte + nop ! 119 NOP + + rte ! 126 CO + + nop ! 119 NOP + + +10: or k4, k2 ! 82 EX + + ldtlb ! 128 CO + + ! At least one instruction between ldtlb and rte + mov.l k2, @k1 ! 27 LS + + rte ! 126 CO + + ! Note we cannot execute mov here, because it is executed after + ! restoring SSR, so would be executed in user space. + nop ! 119 NOP + + + .align 5 + ! Once cache line if possible... +1: .long swapper_pg_dir +4: .short (PTRS_PER_PGD-1) << 2 +5: .short _PAGE_PRESENT +7: .long _PAGE_FLAGS_HARDWARE_MASK +8: .long MMU_PTEH +#ifdef COUNT_EXCEPTIONS +9: .long exception_count_miss +#endif + + ! Either pgd or pte not present +20: mov.l 1f, k2 mov.l 4f, k3 bra handle_exception mov.l @k2, k2 @@ -710,8 +547,9 @@ ENTRY(handle_exception) bt/s 1f ! It's a kernel to kernel transition. mov r15, k0 ! save original stack to k0 /* User space to kernel */ - mov #(THREAD_SIZE >> 8), k1 + mov #(THREAD_SIZE >> 10), k1 shll8 k1 ! k1 := THREAD_SIZE + shll2 k1 add current, k1 mov k1, r15 ! change to kernel stack ! @@ -761,7 +599,7 @@ skip_save: ! Save the user registers on the stack. mov.l k2, @-r15 ! EXPEVT - mov #-1, k4 + mov #-1, k4 mov.l k4, @-r15 ! set TRA (default: -1) ! sts.l macl, @-r15 @@ -813,6 +651,15 @@ skip_save: bf interrupt_exception shlr2 r8 shlr r8 + +#ifdef COUNT_EXCEPTIONS + mov.l 5f, r9 + add r8, r9 + mov.l @r9, r10 + add #1, r10 + mov.l r10, @r9 +#endif + mov.l 4f, r9 add r8, r9 mov.l @r9, r9 @@ -826,6 +673,9 @@ skip_save: 2: .long 0x000080f0 ! FD=1, IMASK=15 3: .long 0xcfffffff ! RB=0, BL=0 4: .long exception_handling_table +#ifdef COUNT_EXCEPTIONS +5: .long exception_count_table +#endif interrupt_exception: mov.l 1f, r9 diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 8dbf3895ece..6e415baf04b 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -2,7 +2,8 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := ex.o probe.o +obj-y := ex.o probe.o common.o +common-y += $(addprefix ../sh3/, entry.o) obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index bfdf5fe8d94..fa2019aabd7 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -97,7 +97,7 @@ static void shoc_clk_recalc(struct clk *clk) static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) { - struct clk *bclk = clk_get("bus_clk"); + struct clk *bclk = clk_get(NULL, "bus_clk"); unsigned long bclk_rate = clk_get_rate(bclk); clk_put(bclk); @@ -151,7 +151,7 @@ static struct clk *sh4202_onchip_clocks[] = { static int __init sh4202_clk_init(void) { - struct clk *clk = clk_get("master_clk"); + struct clk *clk = clk_get(NULL, "master_clk"); int i; for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c index 93ad367342c..9e6a216750c 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh7780.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c @@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = { static int __init sh7780_clk_init(void) { - struct clk *clk = clk_get("master_clk"); + struct clk *clk = clk_get(NULL, "master_clk"); int i; for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index f486c07e10e..7624677f662 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs) grab_fpu(regs); restore_fpu(tsk); set_tsk_thread_flag(tsk, TIF_USEDFPU); - } else { - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; + } else force_sig(SIGFPE, tsk); - } regs->pc = nextpc; return 1; @@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs) } asmlinkage void -do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) +do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; - if (ieee_fpe_handler (®s)) + if (ieee_fpe_handler(regs)) return; - regs.pc += 2; - save_fpu(tsk, ®s); - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; + regs->pc += 2; + save_fpu(tsk, regs); force_sig(SIGFPE, tsk); } asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs regs) + unsigned long r7, struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; - grab_fpu(®s); - if (!user_mode(®s)) { + grab_fpu(regs); + if (!user_mode(regs)) { printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); return; } diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index c294de1e14a..afe0f1b1c03 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -79,16 +79,16 @@ int __init detect_cpu_and_cache_system(void) case 0x205: cpu_data->type = CPU_SH7750; cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | - CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; + CPU_HAS_PERF_COUNTER; break; case 0x206: cpu_data->type = CPU_SH7750S; cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | - CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; + CPU_HAS_PERF_COUNTER; break; case 0x1100: cpu_data->type = CPU_SH7751; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x2000: cpu_data->type = CPU_SH73180; @@ -126,23 +126,22 @@ int __init detect_cpu_and_cache_system(void) break; case 0x8000: cpu_data->type = CPU_ST40RA; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x8100: cpu_data->type = CPU_ST40GX1; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x700: cpu_data->type = CPU_SH4_501; cpu_data->icache.ways = 2; cpu_data->dcache.ways = 2; - cpu_data->flags |= CPU_HAS_PTEA; break; case 0x600: cpu_data->type = CPU_SH4_202; cpu_data->icache.ways = 2; cpu_data->dcache.ways = 2; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x500 ... 0x501: switch (prr) { @@ -160,7 +159,7 @@ int __init detect_cpu_and_cache_system(void) cpu_data->icache.ways = 2; cpu_data->dcache.ways = 2; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; default: @@ -173,6 +172,10 @@ int __init detect_cpu_and_cache_system(void) cpu_data->dcache.ways = 1; #endif +#ifdef CONFIG_CPU_HAS_PTEA + cpu_data->flags |= CPU_HAS_PTEA; +#endif + /* * On anything that's not a direct-mapped cache, look to the CVR * for I/D-cache specifics. diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 50812d57c1c..bbcb06f18b0 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -2,6 +2,7 @@ * SH7750/SH7751 Setup * * Copyright (C) 2006 Paul Mundt + * Copyright (C) 2006 Jamie Lenehan * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -10,6 +11,7 @@ #include <linux/platform_device.h> #include <linux/init.h> #include <linux/serial.h> +#include <linux/io.h> #include <asm/sci.h> static struct plat_sci_port sci_platform_data[] = { @@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void) ARRAY_SIZE(sh7750_devices)); } __initcall(sh7750_devices_setup); + +static struct ipr_data sh7750_ipr_map[] = { + /* IRQ, IPR-idx, shift, priority */ + { 16, 0, 12, 2 }, /* TMU0 TUNI*/ + { 17, 0, 12, 2 }, /* TMU1 TUNI */ + { 18, 0, 4, 2 }, /* TMU2 TUNI */ + { 19, 0, 4, 2 }, /* TMU2 TIPCI */ + { 27, 1, 12, 2 }, /* WDT ITI */ + { 20, 0, 0, 2 }, /* RTC ATI (alarm) */ + { 21, 0, 0, 2 }, /* RTC PRI (period) */ + { 22, 0, 0, 2 }, /* RTC CUI (carry) */ + { 23, 1, 4, 3 }, /* SCI ERI */ + { 24, 1, 4, 3 }, /* SCI RXI */ + { 25, 1, 4, 3 }, /* SCI TXI */ + { 40, 2, 4, 3 }, /* SCIF ERI */ + { 41, 2, 4, 3 }, /* SCIF RXI */ + { 42, 2, 4, 3 }, /* SCIF BRI */ + { 43, 2, 4, 3 }, /* SCIF TXI */ + { 34, 2, 8, 7 }, /* DMAC DMTE0 */ + { 35, 2, 8, 7 }, /* DMAC DMTE1 */ + { 36, 2, 8, 7 }, /* DMAC DMTE2 */ + { 37, 2, 8, 7 }, /* DMAC DMTE3 */ + { 28, 2, 8, 7 }, /* DMAC DMAE */ +}; + +static struct ipr_data sh7751_ipr_map[] = { + { 44, 2, 8, 7 }, /* DMAC DMTE4 */ + { 45, 2, 8, 7 }, /* DMAC DMTE5 */ + { 46, 2, 8, 7 }, /* DMAC DMTE6 */ + { 47, 2, 8, 7 }, /* DMAC DMTE7 */ + /* The following use INTC_INPRI00 for masking, which is a 32-bit + register, not a 16-bit register like the IPRx registers, so it + would need special support */ + /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ + /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ +}; + +static unsigned long ipr_offsets[] = { + 0xffd00004UL, /* 0: IPRA */ + 0xffd00008UL, /* 1: IPRB */ + 0xffd0000cUL, /* 2: IPRC */ + 0xffd00010UL, /* 3: IPRD */ +}; + +/* given the IPR index return the address of the IPR register */ +unsigned int map_ipridx_to_addr(int idx) +{ + if (idx >= ARRAY_SIZE(ipr_offsets)) + return 0; + return ipr_offsets[idx]; +} + +#define INTC_ICR 0xffd00000UL +#define INTC_ICR_IRLM (1<<7) + +/* enable individual interrupt mode for external interupts */ +void ipr_irq_enable_irlm(void) +{ + ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); +} + +void __init init_IRQ_ipr() +{ + make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map)); +#ifdef CONFIG_CPU_SUBTYPE_SH7751 + make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map)); +#endif +} diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c index 814ddb22653..9aeaa2ddaa2 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c @@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(void) __initcall(sh7780_devices_setup); static struct intc2_data intc2_irq_table[] = { - { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 }, - { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { 28, 0, 24, 0, 0, 2 }, /* TMU0 */ - { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { 21, 1, 0, 0, 2, 2 }, + { 22, 1, 1, 0, 2, 2 }, + { 23, 1, 2, 0, 2, 2 }, - { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, - { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, - { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, - { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, - { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, + { 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */ + { 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */ + { 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */ + { 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */ + + { 76, 8, 16, 0, 4, 3 }, /* SCIF1 ERI */ + { 77, 8, 16, 0, 4, 3 }, /* SCIF1 RXI */ + { 78, 8, 16, 0, 4, 3 }, /* SCIF1 BRI */ + { 79, 8, 16, 0, 4, 3 }, /* SCIF1 TXI */ + + { 64, 0x10, 8, 0, 14, 2 }, /* PCIC0 */ + { 65, 0x10, 0, 0, 15, 2 }, /* PCIC1 */ + { 66, 0x14, 24, 0, 16, 2 }, /* PCIC2 */ + { 67, 0x14, 16, 0, 17, 2 }, /* PCIC3 */ + { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */ }; void __init init_IRQ_intc2(void) diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 7bcc73f9b8d..55f43506995 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c @@ -19,7 +19,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/mm.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/page.h> #include <asm/cacheflush.h> #include <asm/cpu/sq.h> @@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len) /* Wait for completion */ store_queue_barrier(); } +EXPORT_SYMBOL(sq_flush_range); static inline void sq_mapping_list_add(struct sq_mapping *map) { @@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, map->size = size; map->name = name; - page = bitmap_find_free_region(sq_bitmap, 0x04000000, + page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT, get_order(map->size)); if (unlikely(page < 0)) { ret = -ENOSPC; @@ -193,6 +194,7 @@ out: kmem_cache_free(sq_cache, map); return ret; } +EXPORT_SYMBOL(sq_remap); /** * sq_unmap - Unmap a Store Queue allocation @@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr) kmem_cache_free(sq_cache, map); } +EXPORT_SYMBOL(sq_unmap); /* * Needlessly complex sysfs interface. Unfortunately it doesn't seem like @@ -402,7 +405,3 @@ module_exit(sq_api_exit); MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(sq_remap); -EXPORT_SYMBOL(sq_unmap); -EXPORT_SYMBOL(sq_flush_range); diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index a00022722e9..60340823798 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -12,7 +12,7 @@ #include <linux/console.h> #include <linux/tty.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/io.h> #ifdef CONFIG_SH_STANDARD_BIOS #include <asm/sh_bios.h> @@ -62,17 +62,9 @@ static struct console bios_console = { #include <linux/serial_core.h> #include "../../../drivers/serial/sh-sci.h" -#ifdef CONFIG_CPU_SH4 -#define SCIF_REG 0xffe80000 -#elif defined(CONFIG_CPU_SUBTYPE_SH72060) -#define SCIF_REG 0xfffe9800 -#else -#error "Undefined SCIF for this subtype" -#endif - static struct uart_port scif_port = { - .mapbase = SCIF_REG, - .membase = (char __iomem *)SCIF_REG, + .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT, + .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT, }; static void scif_sercon_putc(int c) @@ -113,23 +105,29 @@ static struct console scif_console = { .index = -1, }; +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS) +/* + * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4 + * devices that aren't using sh-ipl+g. + */ static void scif_sercon_init(int baud) { - ctrl_outw(0, SCIF_REG + 8); - ctrl_outw(0, SCIF_REG); + ctrl_outw(0, scif_port.mapbase + 8); + ctrl_outw(0, scif_port.mapbase); /* Set baud rate */ ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / - (32 * baud) - 1, SCIF_REG + 4); - - ctrl_outw(12, SCIF_REG + 24); - ctrl_outw(8, SCIF_REG + 24); - ctrl_outw(0, SCIF_REG + 32); - ctrl_outw(0x60, SCIF_REG + 16); - ctrl_outw(0, SCIF_REG + 36); - ctrl_outw(0x30, SCIF_REG + 8); + (32 * baud) - 1, scif_port.mapbase + 4); + + ctrl_outw(12, scif_port.mapbase + 24); + ctrl_outw(8, scif_port.mapbase + 24); + ctrl_outw(0, scif_port.mapbase + 32); + ctrl_outw(0x60, scif_port.mapbase + 16); + ctrl_outw(0, scif_port.mapbase + 36); + ctrl_outw(0x30, scif_port.mapbase + 8); } -#endif +#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */ +#endif /* CONFIG_EARLY_SCIF_CONSOLE */ /* * Setup a default console, if more than one is compiled in, rely on the @@ -168,7 +166,7 @@ int __init setup_early_printk(char *opt) if (!strncmp(buf, "serial", 6)) { early_console = &scif_console; -#ifdef CONFIG_CPU_SH4 +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS) scif_sercon_init(115200); #endif } diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S new file mode 100644 index 00000000000..29136a35d7c --- /dev/null +++ b/arch/sh/kernel/entry-common.S @@ -0,0 +1,433 @@ +/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $ + * + * linux/arch/sh/entry.S + * + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +! NOTE: +! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address +! to be jumped is too far, but it causes illegal slot exception. + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * NOTE: This code uses a convention that instructions in the delay slot + * of a transfer-control instruction are indented by an extra space, thus: + * + * jmp @k0 ! control-transfer instruction + * ldc k1, ssr ! delay slot + * + * Stack layout in 'ret_from_syscall': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in ptrace.c and ptrace.h + * + * r0 + * ... + * r15 = stack pointer + * spc + * pr + * ssr + * gbr + * mach + * macl + * syscall # + * + */ + +#if defined(CONFIG_PREEMPT) +# define preempt_stop() cli +#else +# define preempt_stop() +# define resume_kernel __restore_all +#endif + +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) +! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. +! If both are configured, handle the debug traps (breakpoints) in SW, +! but still allow BIOS traps to FW. + + .align 2 +debug_kernel: +#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) + /* Force BIOS call to FW (debug_trap put TRA in r8) */ + mov r8,r0 + shlr2 r0 + cmp/eq #0x3f,r0 + bt debug_kernel_fw +#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ + +debug_enter: +#if defined(CONFIG_SH_KGDB) + /* Jump to kgdb, pass stacked regs as arg */ +debug_kernel_sw: + mov.l 3f, r0 + jmp @r0 + mov r15, r4 + .align 2 +3: .long kgdb_handle_exception +#endif /* CONFIG_SH_KGDB */ + +#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ + + + .align 2 +debug_trap: +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + bt/s debug_kernel +#endif + mov.l @r15, r0 ! Restore R0 value + mov.l 1f, r8 + jmp @r8 + nop + + .align 2 +ENTRY(exception_error) + ! +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 3f, r0 + jsr @r0 + nop +#endif + sti + mov.l 2f, r0 + jmp @r0 + nop + +! + .align 2 +1: .long break_point_trap_software +2: .long do_exception_error +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_on +#endif + + .align 2 +ret_from_exception: + preempt_stop() +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 4f, r0 + jsr @r0 + nop +#endif +ENTRY(ret_from_irq) + ! + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + get_current_thread_info r8, r0 + bt resume_kernel ! Yes, it's from kernel, go back soon + +#ifdef CONFIG_PREEMPT + bra resume_userspace + nop +ENTRY(resume_kernel) + mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count + tst r0, r0 + bf noresched +need_resched: + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_NEED_RESCHED, r0 ! need_resched set? + bt noresched + + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + and #0xf0, r0 ! interrupts off (exception path)? + cmp/eq #0xf0, r0 + bt noresched + + mov.l 1f, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 3f, r0 + jsr @r0 + nop +#endif + sti + mov.l 2f, r0 + jsr @r0 + nop + mov #0, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 4f, r0 + jsr @r0 + nop +#endif + + bra need_resched + nop + +noresched: + bra __restore_all + nop + + .align 2 +1: .long PREEMPT_ACTIVE +2: .long schedule +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_on +4: .long trace_hardirqs_off +#endif +#endif + +ENTRY(resume_userspace) + ! r8: current_thread_info + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt/s __restore_all + tst #_TIF_NEED_RESCHED, r0 + + .align 2 +work_pending: + ! r0: current_thread_info->flags + ! r8: current_thread_info + ! t: result of "tst #_TIF_NEED_RESCHED, r0" + bf/s work_resched + tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 +work_notifysig: + bt/s __restore_all + mov r15, r4 + mov r12, r5 ! set arg1(save_r0) + mov r0, r6 + mov.l 2f, r1 + mov.l 3f, r0 + jmp @r1 + lds r0, pr +work_resched: +#ifndef CONFIG_PREEMPT + ! gUSA handling + mov.l @(OFF_SP,r15), r0 ! get user space stack pointer + mov r0, r1 + shll r0 + bf/s 1f + shll r0 + bf/s 1f + mov #OFF_PC, r0 + ! SP >= 0xc0000000 : gUSA mark + mov.l @(r0,r15), r2 ! get user space PC (program counter) + mov.l @(OFF_R0,r15), r3 ! end point + cmp/hs r3, r2 ! r2 >= r3? + bt 1f + add r3, r1 ! rewind point #2 + mov.l r1, @(r0,r15) ! reset PC to rewind point #2 + ! +1: +#endif + mov.l 1f, r1 + jsr @r1 ! schedule + nop + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif + ! + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt __restore_all + bra work_pending + tst #_TIF_NEED_RESCHED, r0 + + .align 2 +1: .long schedule +2: .long do_notify_resume +3: .long restore_all +#ifdef CONFIG_TRACE_IRQFLAGS +4: .long trace_hardirqs_on +5: .long trace_hardirqs_off +#endif + + .align 2 +syscall_exit_work: + ! r0: current_thread_info->flags + ! r8: current_thread_info + tst #_TIF_SYSCALL_TRACE, r0 + bt/s work_pending + tst #_TIF_NEED_RESCHED, r0 +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif + sti + ! XXX setup arguments... + mov.l 4f, r0 ! do_syscall_trace + jsr @r0 + nop + bra resume_userspace + nop + + .align 2 +syscall_trace_entry: + ! Yes it is traced. + ! XXX setup arguments... + mov.l 4f, r11 ! Call do_syscall_trace which notifies + jsr @r11 ! superior (will chomp R[0-7]) + nop + ! Reload R0-R4 from kernel stack, where the + ! parent may have modified them using + ! ptrace(POKEUSR). (Note that R0-R2 are + ! used by the system call handler directly + ! from the kernel stack anyway, so don't need + ! to be reloaded here.) This allows the parent + ! to rewrite system calls and args on the fly. + mov.l @(OFF_R4,r15), r4 ! arg0 + mov.l @(OFF_R5,r15), r5 + mov.l @(OFF_R6,r15), r6 + mov.l @(OFF_R7,r15), r7 ! arg3 + mov.l @(OFF_R3,r15), r3 ! syscall_nr + ! + mov.l 2f, r10 ! Number of syscalls + cmp/hs r10, r3 + bf syscall_call + mov #-ENOSYS, r0 + bra syscall_exit + mov.l r0, @(OFF_R0,r15) ! Return value + +__restore_all: + mov.l 1f, r0 + jmp @r0 + nop + + .align 2 +1: .long restore_all + + .align 2 +not_syscall_tra: + bra debug_trap + nop + + .align 2 +syscall_badsys: ! Bad syscall number + mov #-ENOSYS, r0 + bra resume_userspace + mov.l r0, @(OFF_R0,r15) ! Return value + + +/* + * Syscall interface: + * + * Syscall #: R3 + * Arguments #0 to #3: R4--R7 + * Arguments #4 to #6: R0, R1, R2 + * TRA: (number of arguments + 0x10) x 4 + * + * This code also handles delegating other traps to the BIOS/gdb stub + * according to: + * + * Trap number + * (TRA>>2) Purpose + * -------- ------- + * 0x0-0xf old syscall ABI + * 0x10-0x1f new syscall ABI + * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. + * + * Note: When we're first called, the TRA value must be shifted + * right 2 bits in order to get the value that was used as the "trapa" + * argument. + */ + + .align 2 + .globl ret_from_fork +ret_from_fork: + mov.l 1f, r8 + jsr @r8 + mov r0, r4 + bra syscall_exit + nop + .align 2 +1: .long schedule_tail + ! +ENTRY(system_call) +#if !defined(CONFIG_CPU_SH2) + mov.l 1f, r9 + mov.l @r9, r8 ! Read from TRA (Trap Address) Register +#endif + ! + ! Is the trap argument >= 0x20? (TRA will be >= 0x80) + mov #0x7f, r9 + cmp/hi r9, r8 + bt/s not_syscall_tra + mov #OFF_TRA, r9 + add r15, r9 + mov.l r8, @r9 ! set TRA value to tra +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r10 + jsr @r10 + nop +#endif + sti + + ! + get_current_thread_info r8, r10 + mov.l @(TI_FLAGS,r8), r8 + mov #_TIF_SYSCALL_TRACE, r10 + tst r10, r8 + bf syscall_trace_entry + ! + mov.l 2f, r8 ! Number of syscalls + cmp/hs r8, r3 + bt syscall_badsys + ! +syscall_call: + shll2 r3 ! x4 + mov.l 3f, r8 ! Load the address of sys_call_table + add r8, r3 + mov.l @r3, r8 + jsr @r8 ! jump to specific syscall handler + nop + mov.l @(OFF_R0,r15), r12 ! save r0 + mov.l r0, @(OFF_R0,r15) ! save the return value + ! +syscall_exit: + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 6f, r0 + jsr @r0 + nop +#endif + ! + get_current_thread_info r8, r0 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_ALLWORK_MASK, r0 + bf syscall_exit_work + bra __restore_all + nop + .align 2 +#if !defined(CONFIG_CPU_SH2) +1: .long TRA +#endif +2: .long NR_syscalls +3: .long sys_call_table +4: .long do_syscall_trace +#ifdef CONFIG_TRACE_IRQFLAGS +5: .long trace_hardirqs_on +6: .long trace_hardirqs_off +#endif diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index f5f53d14f24..6aca4bc6ec5 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -33,7 +33,7 @@ ENTRY(empty_zero_page) .long 0x00360000 /* INITRD_START */ .long 0x000a0000 /* INITRD_SIZE */ .long 0 - .balign 4096,0,4096 + .balign PAGE_SIZE,0,PAGE_SIZE .text /* @@ -53,8 +53,10 @@ ENTRY(_stext) ldc r0, sr ! Initialize global interrupt mask mov #0, r0 +#ifdef CONFIG_CPU_HAS_SR_RB ldc r0, r6_bank - +#endif + /* * Prefetch if possible to reduce cache miss penalty. * @@ -68,11 +70,14 @@ ENTRY(_stext) ! mov.l 2f, r0 mov r0, r15 ! Set initial r15 (stack pointer) - mov #(THREAD_SIZE >> 8), r1 + mov #(THREAD_SIZE >> 10), r1 shll8 r1 ! r1 = THREAD_SIZE + shll2 r1 sub r1, r0 ! +#ifdef CONFIG_CPU_HAS_SR_RB ldc r0, r7_bank ! ... and initial thread_info - +#endif + ! Clear BSS area mov.l 3f, r1 add #4, r1 @@ -95,7 +100,11 @@ ENTRY(_stext) nop .balign 4 +#if defined(CONFIG_CPU_SH2) +1: .long 0x000000F0 ! IMASK=0xF +#else 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF +#endif 2: .long init_thread_union+THREAD_SIZE 3: .long __bss_start 4: .long _end diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 944128ce970..67be2b6e8cd 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -12,7 +12,7 @@ #include <linux/kernel_stat.h> #include <linux/seq_file.h> #include <linux/io.h> -#include <asm/irq.h> +#include <linux/irq.h> #include <asm/processor.h> #include <asm/uaccess.h> #include <asm/thread_info.h> @@ -78,15 +78,16 @@ union irq_ctx { u32 stack[THREAD_SIZE/sizeof(u32)]; }; -static union irq_ctx *hardirq_ctx[NR_CPUS]; -static union irq_ctx *softirq_ctx[NR_CPUS]; +static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; +static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; #endif asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct pt_regs *old_regs = set_irq_regs(®s); + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct pt_regs *old_regs = set_irq_regs(regs); int irq; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; @@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_CPU_HAS_INTEVT - irq = (ctrl_inl(INTEVT) >> 5) - 16; + irq = evt2irq(ctrl_inl(INTEVT)); #else irq = r4; #endif @@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.previous_sp = current_stack_pointer; + /* + * Copy the softirq bits in preempt_count so that the + * softirq checks work in the hardirq context. + */ + irqctx->tinfo.preempt_count = + (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) | + (curctx->tinfo.preempt_count & SOFTIRQ_MASK); + __asm__ __volatile__ ( "mov %0, r4 \n" - "mov r15, r9 \n" + "mov r15, r8 \n" "jsr @%1 \n" /* swith to the irq stack */ " mov %2, r15 \n" /* restore the stack (ring zero) */ - "mov r9, r15 \n" + "mov r8, r15 \n" : /* no outputs */ : "r" (irq), "r" (generic_handle_irq), "r" (isp) - /* XXX: A somewhat excessive clobber list? -PFM */ : "memory", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "t", "pr" ); @@ -193,7 +201,7 @@ void irq_ctx_init(int cpu) irqctx->tinfo.task = NULL; irqctx->tinfo.exec_domain = NULL; irqctx->tinfo.cpu = cpu; - irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; + irqctx->tinfo.preempt_count = 0; irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); softirq_ctx[cpu] = irqctx; @@ -239,13 +247,38 @@ asmlinkage void do_softirq(void) "mov r9, r15 \n" : /* no outputs */ : "r" (__do_softirq), "r" (isp) - /* XXX: A somewhat excessive clobber list? -PFM */ : "memory", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" ); + + /* + * Shouldnt happen, we returned above if in_interrupt(): + */ + WARN_ON_ONCE(softirq_count()); } local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); #endif + +void __init init_IRQ(void) +{ +#ifdef CONFIG_CPU_HAS_PINT_IRQ + init_IRQ_pint(); +#endif + +#ifdef CONFIG_CPU_HAS_INTC2_IRQ + init_IRQ_intc2(); +#endif + +#ifdef CONFIG_CPU_HAS_IPR_IRQ + init_IRQ_ipr(); +#endif + + /* Perform the machine specific initialisation */ + if (sh_mv.mv_init_irq) + sh_mv.mv_init_irq(); + + irq_ctx_init(smp_processor_id()); +} diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index a52b13ac6b7..f3e2631be14 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -385,10 +385,11 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne asmlinkage int sys_fork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); #ifdef CONFIG_MMU - return do_fork(SIGCHLD, regs.regs[15], ®s, 0, NULL, NULL); + return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); #else /* fork almost works, enough to trick you into looking elsewhere :-( */ return -EINVAL; @@ -398,11 +399,12 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5, asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidptr, unsigned long child_tidptr, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); if (!newsp) - newsp = regs.regs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + newsp = regs->regs[15]; + return do_fork(clone_flags, newsp, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -418,9 +420,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, */ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s, + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); } @@ -429,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, */ asmlinkage int sys_execve(char *ufilename, char **uargv, char **uenvp, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); int error; char *filename; @@ -442,7 +446,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv, error = do_execve(filename, (char __user * __user *)uargv, (char __user * __user *)uenvp, - ®s); + regs); if (error == 0) { task_lock(current); current->ptrace &= ~PT_DTRACE; @@ -472,9 +476,7 @@ unsigned long get_wchan(struct task_struct *p) return pc; } -asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs regs) +asmlinkage void break_point_trap(void) { /* Clear tracing. */ #if defined(CONFIG_CPU_SH4A) @@ -492,8 +494,10 @@ asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - regs.pc -= 2; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + regs->pc -= 2; force_sig(SIGTRAP, current); } diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S index 8221b37c977..c66cb3209db 100644 --- a/arch/sh/kernel/relocate_kernel.S +++ b/arch/sh/kernel/relocate_kernel.S @@ -7,11 +7,9 @@ * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ - #include <linux/linkage.h> - -#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */ - +#include <asm/addrspace.h> +#include <asm/page.h> .globl relocate_new_kernel relocate_new_kernel: @@ -20,8 +18,8 @@ relocate_new_kernel: /* r6 = start_address */ /* r7 = vbr_reg */ - mov.l 10f,r8 /* 4096 */ - mov.l 11f,r9 /* 0xa0000000 */ + mov.l 10f,r8 /* PAGE_SIZE */ + mov.l 11f,r9 /* P2SEG */ /* stack setting */ add r8,r5 @@ -32,7 +30,7 @@ relocate_new_kernel: 0: mov.l @r4+,r0 /* cmd = *ind++ */ -1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ +1: /* addr = (cmd | P2SEG) & 0xfffffff0 */ mov r0,r2 or r9,r2 mov #-16,r1 @@ -92,7 +90,7 @@ relocate_new_kernel: 10: .long PAGE_SIZE 11: - .long 0xa0000000 + .long P2SEG relocate_new_kernel_end: diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 36d86f9ac38..696ca75752d 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -392,6 +392,7 @@ static int __init topology_init(void) subsys_initcall(topology_init); static const char *cpu_name[] = { + [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", @@ -404,6 +405,7 @@ static const char *cpu_name[] = { [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", + [CPU_SH7785] = "SH7785", [CPU_SH_NONE] = "Unknown" }; diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 8a2fd19dc9e..c706f3bfd89 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -73,8 +73,6 @@ DECLARE_EXPORT(__lshrdi3); DECLARE_EXPORT(__movstr); DECLARE_EXPORT(__movstrSI16); -EXPORT_SYMBOL(strcpy); - #ifdef CONFIG_CPU_SH4 DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 5213f5bc6ce..50d7c4993be 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -37,7 +37,7 @@ asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); @@ -52,7 +52,7 @@ sys_sigsuspend(old_sigset_t mask, return -ERESTARTNOHAND; } -asmlinkage int +asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { @@ -87,9 +87,11 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - return do_sigaltstack(uss, uoss, regs.regs[15]); + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + return do_sigaltstack(uss, uoss, regs->regs[15]); } @@ -98,7 +100,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, */ #define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ -#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */ +#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) +#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */ +#else +#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */ +#endif #define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ struct sigframe @@ -194,9 +200,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15]; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15]; sigset_t set; int r0; @@ -216,7 +223,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->sc, &r0)) + if (restore_sigcontext(regs, &frame->sc, &r0)) goto badframe; return r0; @@ -227,9 +234,10 @@ badframe: asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15]; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15]; sigset_t set; stack_t st; int r0; @@ -246,14 +254,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->uc.uc_mcontext, &r0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.regs[15]); + do_sigaltstack(&st, NULL, regs->regs[15]); return r0; @@ -350,7 +358,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, } else { /* Generate return code (system call to sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); @@ -430,7 +438,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } else { /* Generate return code (system call to rt_sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c new file mode 100644 index 00000000000..0d5268afe80 --- /dev/null +++ b/arch/sh/kernel/stacktrace.c @@ -0,0 +1,43 @@ +/* + * arch/sh/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/thread_info.h> +#include <asm/ptrace.h> + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) +{ + unsigned long *sp; + + if (!task) + task = current; + if (task == current) + sp = (unsigned long *)current_stack_pointer; + else + sp = (unsigned long *)task->thread.sp; + + while (!kstack_end(sp)) { + unsigned long addr = *sp++; + + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 8fde95001c3..5083b6ed4b3 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -33,14 +33,15 @@ */ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); int fd[2]; int error; error = do_pipe(fd); if (!error) { - regs.regs[1] = fd[1]; + regs->regs[1] = fd[1]; return fd[0]; } return error; @@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ EXPORT_SYMBOL(shm_align_mask); +#ifdef CONFIG_MMU /* * To avoid cache aliases, we map the shared page with same color. */ @@ -135,6 +137,7 @@ full_search: addr = COLOUR_ALIGN(addr, pgoff); } } +#endif /* CONFIG_MMU */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 57e708d7b52..c206c9504c4 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -13,6 +13,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/profile.h> +#include <linux/timex.h> +#include <linux/sched.h> #include <asm/clock.h> #include <asm/rtc.h> #include <asm/timer.h> @@ -50,15 +52,20 @@ unsigned long long __attribute__ ((weak)) sched_clock(void) #ifndef CONFIG_GENERIC_TIME void do_gettimeofday(struct timeval *tv) { + unsigned long flags; unsigned long seq; unsigned long usec, sec; do { - seq = read_seqbegin(&xtime_lock); + /* + * Turn off IRQs when grabbing xtime_lock, so that + * the sys_timer get_offset code doesn't have to handle it. + */ + seq = read_seqbegin_irqsave(&xtime_lock, flags); usec = get_timer_offset(); sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqretry(&xtime_lock, seq)); + usec += xtime.tv_nsec / NSEC_PER_USEC; + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); while (usec >= 1000000) { usec -= 1000000; @@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - nsec -= 1000 * get_timer_offset(); + nsec -= get_timer_offset() * NSEC_PER_USEC; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); @@ -169,6 +176,108 @@ static struct sysdev_class timer_sysclass = { .resume = timer_resume, }; +#ifdef CONFIG_NO_IDLE_HZ +static int timer_dyn_tick_enable(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (!(dyn_tick->state & DYN_TICK_ENABLED)) { + ret = dyn_tick->enable(); + + if (ret == 0) + dyn_tick->state |= DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } + + return ret; +} + +static int timer_dyn_tick_disable(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (dyn_tick->state & DYN_TICK_ENABLED) { + ret = dyn_tick->disable(); + + if (ret == 0) + dyn_tick->state &= ~DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } + + return ret; +} + +/* + * Reprogram the system timer for at least the calculated time interval. + * This function should be called from the idle thread with IRQs disabled, + * immediately before sleeping. + */ +void timer_dyn_reprogram(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long next, seq, flags; + + if (!dyn_tick) + return; + + spin_lock_irqsave(&dyn_tick->lock, flags); + if (dyn_tick->state & DYN_TICK_ENABLED) { + next = next_timer_interrupt(); + do { + seq = read_seqbegin(&xtime_lock); + dyn_tick->reprogram(next - jiffies); + } while (read_seqretry(&xtime_lock, seq)); + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); +} + +static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) +{ + return sprintf(buf, "%i\n", + (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); +} + +static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, + size_t count) +{ + unsigned int enable = simple_strtoul(buf, NULL, 2); + + if (enable) + timer_dyn_tick_enable(); + else + timer_dyn_tick_disable(); + + return count; +} +static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); + +/* + * dyntick=enable|disable + */ +static char dyntick_str[4] __initdata = ""; + +static int __init dyntick_setup(char *str) +{ + if (str) + strlcpy(dyntick_str, str, sizeof(dyntick_str)); + return 1; +} + +__setup("dyntick=", dyntick_setup); +#endif + static int __init timer_init_sysfs(void) { int ret = sysdev_class_register(&timer_sysclass); @@ -176,7 +285,22 @@ static int __init timer_init_sysfs(void) return ret; sys_timer->dev.cls = &timer_sysclass; - return sysdev_register(&sys_timer->dev); + ret = sysdev_register(&sys_timer->dev); + +#ifdef CONFIG_NO_IDLE_HZ + if (ret == 0 && sys_timer->dyn_tick) { + ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick); + + /* + * Turn on dynamic tick after calibrate delay + * for correct bogomips + */ + if (ret == 0 && dyntick_str[0] == 'e') + ret = timer_dyn_tick_enable(); + } +#endif + + return ret; } device_initcall(timer_init_sysfs); @@ -200,6 +324,11 @@ void __init time_init(void) sys_timer = get_sys_timer(); printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); +#ifdef CONFIG_NO_IDLE_HZ + if (sys_timer->dyn_tick) + spin_lock_init(&sys_timer->dyn_tick->lock); +#endif + #if defined(CONFIG_SH_KGDB) /* * Set up kgdb as requested. We do it here because the serial diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile index 151a6a304ce..bcf244ff6a1 100644 --- a/arch/sh/kernel/timers/Makefile +++ b/arch/sh/kernel/timers/Makefile @@ -5,4 +5,6 @@ obj-y := timer.o obj-$(CONFIG_SH_TMU) += timer-tmu.o +obj-$(CONFIG_SH_MTU2) += timer-mtu2.o +obj-$(CONFIG_SH_CMT) += timer-cmt.o diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c new file mode 100644 index 00000000000..a574b93a4e7 --- /dev/null +++ b/arch/sh/kernel/timers/timer-cmt.c @@ -0,0 +1,196 @@ +/* + * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support + * + * Copyright (C) 2005 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/seqlock.h> +#include <asm/timer.h> +#include <asm/rtc.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/clock.h> + +#if defined(CONFIG_CPU_SUBTYPE_SH7619) +#define CMT_CMSTR 0xf84a0070 +#define CMT_CMCSR_0 0xf84a0072 +#define CMT_CMCNT_0 0xf84a0074 +#define CMT_CMCOR_0 0xf84a0076 +#define CMT_CMCSR_1 0xf84a0078 +#define CMT_CMCNT_1 0xf84a007a +#define CMT_CMCOR_1 0xf84a007c + +#define STBCR3 0xf80a0000 +#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0) +#define CMT_CMCSR_INIT 0x0040 +#define CMT_CMCSR_CALIB 0x0000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +#define CMT_CMSTR 0xfffec000 +#define CMT_CMCSR_0 0xfffec002 +#define CMT_CMCNT_0 0xfffec004 +#define CMT_CMCOR_0 0xfffec006 + +#define STBCR4 0xfffe040c +#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0) +#define CMT_CMCSR_INIT 0x0040 +#define CMT_CMCSR_CALIB 0x0000 +#else +#error "Unknown CPU SUBTYPE" +#endif + +static unsigned long cmt_timer_get_offset(void) +{ + int count; + static unsigned short count_p = 0xffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* timer count may underflow right here */ + count = ctrl_inw(CMT_CMCOR_0); + count -= ctrl_inw(CMT_CMCNT_0); + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear CMF bit */ + timer_status = ctrl_inw(CMT_CMCSR_0); + timer_status &= ~0x80; + ctrl_outw(timer_status, CMT_CMCSR_0); + + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction cmt_irq = { + .name = "timer", + .handler = cmt_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .mask = CPU_MASK_NONE, +}; + +static void cmt_clk_init(struct clk *clk) +{ + u8 divisor = CMT_CMCSR_INIT & 0x3; + ctrl_inw(CMT_CMCSR_0); + ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0); + clk->parent = clk_get(NULL, "module_clk"); + clk->rate = clk->parent->rate / (8 << (divisor << 1)); +} + +static void cmt_clk_recalc(struct clk *clk) +{ + u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3; + clk->rate = clk->parent->rate / (8 << (divisor << 1)); +} + +static struct clk_ops cmt_clk_ops = { + .init = cmt_clk_init, + .recalc = cmt_clk_recalc, +}; + +static struct clk cmt0_clk = { + .name = "cmt0_clk", + .ops = &cmt_clk_ops, +}; + +static int cmt_timer_start(void) +{ + ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR); + return 0; +} + +static int cmt_timer_stop(void) +{ + ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR); + return 0; +} + +static int cmt_timer_init(void) +{ + unsigned long interval; + + cmt_clock_enable(); + + setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq); + + cmt0_clk.parent = clk_get(NULL, "module_clk"); + + cmt_timer_stop(); + + interval = cmt0_clk.parent->rate / 8 / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outw(interval, CMT_CMCOR_0); + + clk_register(&cmt0_clk); + clk_enable(&cmt0_clk); + + cmt_timer_start(); + + return 0; +} + +struct sys_timer_ops cmt_timer_ops = { + .init = cmt_timer_init, + .start = cmt_timer_start, + .stop = cmt_timer_stop, +#ifndef CONFIG_GENERIC_TIME + .get_offset = cmt_timer_get_offset, +#endif +}; + +struct sys_timer cmt_timer = { + .name = "cmt", + .ops = &cmt_timer_ops, +}; diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c new file mode 100644 index 00000000000..fffcd1c0987 --- /dev/null +++ b/arch/sh/kernel/timers/timer-mtu2.c @@ -0,0 +1,200 @@ +/* + * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support + * + * Copyright (C) 2005 Paul Mundt + * + * Based off of arch/sh/kernel/timers/timer-tmu.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/seqlock.h> +#include <asm/timer.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/clock.h> + +/* + * We use channel 1 for our lowly system timer. Channel 2 would be the other + * likely candidate, but we leave it alone as it has higher divisors that + * would be of more use to other more interesting applications. + * + * TODO: Presently we only implement a 16-bit single-channel system timer. + * However, we can implement channel cascade if we go the overflow route and + * get away with using 2 MTU2 channels as a 32-bit timer. + */ +#define MTU2_TSTR 0xfffe4280 +#define MTU2_TCR_1 0xfffe4380 +#define MTU2_TMDR_1 0xfffe4381 +#define MTU2_TIOR_1 0xfffe4382 +#define MTU2_TIER_1 0xfffe4384 +#define MTU2_TSR_1 0xfffe4385 +#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ +#define MTU2_TGRA_1 0xfffe438a + +#define STBCR3 0xfffe0408 + +#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */ + +#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */ + +#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */ + +#define MTU2_TCR_INIT 0x22 + +#define MTU2_TCR_CALIB 0x00 + +static unsigned long mtu2_timer_get_offset(void) +{ + int count; + static int count_p = 0x7fff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* timer count may underflow right here */ + count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */ + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) { + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear TGFA bit */ + timer_status = ctrl_inb(MTU2_TSR_1); + timer_status &= ~MTU2_TSR_TGFA; + ctrl_outb(timer_status, MTU2_TSR_1); + + /* Do timer tick */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction mtu2_irq = { + .name = "timer", + .handler = mtu2_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .mask = CPU_MASK_NONE, +}; + +static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 }; + +static void mtu2_clk_init(struct clk *clk) +{ + u8 idx = MTU2_TCR_INIT & 0x7; + + clk->rate = clk->parent->rate / divisors[idx]; + /* Start TCNT counting */ + ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); + +} + +static void mtu2_clk_recalc(struct clk *clk) +{ + u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops mtu2_clk_ops = { + .init = mtu2_clk_init, + .recalc = mtu2_clk_recalc, +}; + +static struct clk mtu2_clk1 = { + .name = "mtu2_clk1", + .ops = &mtu2_clk_ops, +}; + +static int mtu2_timer_start(void) +{ + ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); + return 0; +} + +static int mtu2_timer_stop(void) +{ + ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR); + return 0; +} + +static int mtu2_timer_init(void) +{ + u8 tmp; + unsigned long interval; + + setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq); + + mtu2_clk1.parent = clk_get(NULL, "module_clk"); + + ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3); + + /* Normal operation */ + ctrl_outb(0, MTU2_TMDR_1); + ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1); + ctrl_outb(0x01, MTU2_TIOR_1); + + /* Enable underflow interrupt */ + ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1); + + interval = CONFIG_SH_PCLK_FREQ / 16 / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outw(interval, MTU2_TGRA_1); + ctrl_outw(0, MTU2_TCNT_1); + + clk_register(&mtu2_clk1); + clk_enable(&mtu2_clk1); + + return 0; +} + +struct sys_timer_ops mtu2_timer_ops = { + .init = mtu2_timer_init, + .start = mtu2_timer_start, + .stop = mtu2_timer_stop, +#ifndef CONFIG_GENERIC_TIME + .get_offset = mtu2_timer_get_offset, +#endif +}; + +struct sys_timer mtu2_timer = { + .name = "mtu2", + .ops = &mtu2_timer_ops, +}; diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 24927015dc3..e060e71d078 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -17,7 +17,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/interrupt.h> -#include <linux/spinlock.h> #include <linux/seqlock.h> #include <asm/timer.h> #include <asm/rtc.h> @@ -31,13 +30,9 @@ #define TMU0_TCR_CALIB 0x0000 -static DEFINE_SPINLOCK(tmu0_lock); - static unsigned long tmu_timer_get_offset(void) { int count; - unsigned long flags; - static int count_p = 0x7fffffff; /* for the first call after boot */ static unsigned long jiffies_p = 0; @@ -46,7 +41,6 @@ static unsigned long tmu_timer_get_offset(void) */ unsigned long jiffies_t; - spin_lock_irqsave(&tmu0_lock, flags); /* timer count may underflow right here */ count = ctrl_inl(TMU0_TCNT); /* read the latched count */ @@ -72,7 +66,6 @@ static unsigned long tmu_timer_get_offset(void) jiffies_p = jiffies_t; count_p = count; - spin_unlock_irqrestore(&tmu0_lock, flags); count = ((LATCH-1) - count) * TICK_SIZE; count = (count + LATCH/2) / LATCH; @@ -106,7 +99,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) static struct irqaction tmu_irq = { .name = "timer", .handler = tmu_timer_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_TIMER, .mask = CPU_MASK_NONE, }; @@ -149,9 +142,9 @@ static int tmu_timer_init(void) { unsigned long interval; - setup_irq(TIMER_IRQ, &tmu_irq); + setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); - tmu0_clk.parent = clk_get("module_clk"); + tmu0_clk.parent = clk_get(NULL, "module_clk"); /* Start TMU0 */ tmu_timer_stop(); diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c index dc1f631053a..a6bcc913d25 100644 --- a/arch/sh/kernel/timers/timer.c +++ b/arch/sh/kernel/timers/timer.c @@ -17,6 +17,12 @@ static struct sys_timer *sys_timers[] __initdata = { #ifdef CONFIG_SH_TMU &tmu_timer, #endif +#ifdef CONFIG_SH_MTU2 + &mtu2_timer, +#endif +#ifdef CONFIG_SH_CMT + &cmt_timer, +#endif NULL, }; diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 53dfa55f315..3762d9dc204 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -18,13 +18,14 @@ #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/io.h> +#include <linux/debug_locks.h> #include <asm/system.h> #include <asm/uaccess.h> #ifdef CONFIG_SH_KGDB #include <asm/kgdb.h> -#define CHK_REMOTE_DEBUG(regs) \ -{ \ +#define CHK_REMOTE_DEBUG(regs) \ +{ \ if (kgdb_debug_hook && !user_mode(regs))\ (*kgdb_debug_hook)(regs); \ } @@ -33,8 +34,13 @@ #endif #ifdef CONFIG_CPU_SH2 -#define TRAP_RESERVED_INST 4 -#define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_RESERVED_INST 4 +# define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_ADDRESS_ERROR 9 +# ifdef CONFIG_CPU_SH2A +# define TRAP_DIVZERO_ERROR 17 +# define TRAP_DIVOVF_ERROR 18 +# endif #else #define TRAP_RESERVED_INST 12 #define TRAP_ILLEGAL_SLOT_INST 13 @@ -88,7 +94,7 @@ void die(const char * str, struct pt_regs * regs, long err) if (!user_mode(regs) || in_interrupt()) dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + - (unsigned long)task_stack_page(current)); + (unsigned long)task_stack_page(current)); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -102,8 +108,6 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs, die(str, regs, err); } -static int handle_unaligned_notify_count = 10; - /* * try and fix up kernelspace address errors * - userspace errors just cause EFAULT to be returned, resulting in SEGV @@ -198,7 +202,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) if (copy_to_user(dst,src,4)) goto fetch_fault; ret = 0; - break; + break; case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ if (instruction & 4) @@ -222,7 +226,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) if (copy_from_user(dst,src,4)) goto fetch_fault; ret = 0; - break; + break; case 6: /* mov.[bwl] from memory, possibly with post-increment */ src = (unsigned char*) *rm; @@ -230,7 +234,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) *rm += count; dst = (unsigned char*) rn; *(unsigned long*)dst = 0; - + #ifdef __LITTLE_ENDIAN__ if (copy_from_user(dst, src, count)) goto fetch_fault; @@ -241,7 +245,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) } #else dst += 4-count; - + if (copy_from_user(dst, src, count)) goto fetch_fault; @@ -320,7 +324,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) return -EFAULT; /* kernel */ - die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0); + die("delay-slot-insn faulting in handle_unaligned_delayslot", + regs, 0); } return handle_unaligned_ins(instruction,regs); @@ -342,6 +347,13 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) #define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) +/* + * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit + * opcodes.. + */ +#ifndef CONFIG_CPU_SH2A +static int handle_unaligned_notify_count = 10; + static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) { u_int rm; @@ -354,7 +366,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) if (user_mode(regs) && handle_unaligned_notify_count>0) { handle_unaligned_notify_count--; - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", + printk(KERN_NOTICE "Fixing up unaligned userspace access " + "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", current->comm,current->pid,(u16*)regs->pc,instruction); } @@ -478,32 +491,58 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) regs->pc += 2; return ret; } +#endif /* CONFIG_CPU_SH2A */ + +#ifdef CONFIG_CPU_HAS_SR_RB +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x))) +#else +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x))) +#endif /* - * Handle various address error exceptions + * Handle various address error exceptions: + * - instruction address error: + * misaligned PC + * PC >= 0x80000000 in user mode + * - data address error (read and write) + * misaligned data access + * access to >= 0x80000000 is user mode + * Unfortuntaly we can't distinguish between instruction address error + * and data address errors caused by read acceses. */ -asmlinkage void do_address_error(struct pt_regs *regs, +asmlinkage void do_address_error(struct pt_regs *regs, unsigned long writeaccess, unsigned long address) { - unsigned long error_code; + unsigned long error_code = 0; mm_segment_t oldfs; + siginfo_t info; +#ifndef CONFIG_CPU_SH2A u16 instruction; int tmp; +#endif - asm volatile("stc r2_bank,%0": "=r" (error_code)); + /* Intentional ifdef */ +#ifdef CONFIG_CPU_HAS_SR_RB + lookup_exception_vector(error_code); +#endif oldfs = get_fs(); if (user_mode(regs)) { + int si_code = BUS_ADRERR; + local_irq_enable(); - current->thread.error_code = error_code; - current->thread.trap_no = (writeaccess) ? 8 : 7; /* bad PC is not something we can fix */ - if (regs->pc & 1) + if (regs->pc & 1) { + si_code = BUS_ADRALN; goto uspace_segv; + } +#ifndef CONFIG_CPU_SH2A set_fs(USER_DS); if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { /* Argh. Fault on the instruction itself. @@ -518,14 +557,23 @@ asmlinkage void do_address_error(struct pt_regs *regs, if (tmp==0) return; /* sorted */ +#endif - uspace_segv: - printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm); - force_sig(SIGSEGV, current); +uspace_segv: + printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " + "access (PC %lx PR %lx)\n", current->comm, regs->pc, + regs->pr); + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, current); } else { if (regs->pc & 1) die("unaligned program counter", regs, error_code); +#ifndef CONFIG_CPU_SH2A set_fs(KERNEL_DS); if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { /* Argh. Fault on the instruction itself. @@ -537,6 +585,12 @@ asmlinkage void do_address_error(struct pt_regs *regs, handle_unaligned_access(instruction, regs); set_fs(oldfs); +#else + printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " + "access\n", current->comm); + + force_sig(SIGSEGV, current); +#endif } } @@ -548,7 +602,7 @@ int is_dsp_inst(struct pt_regs *regs) { unsigned short inst; - /* + /* * Safe guard if DSP mode is already enabled or we're lacking * the DSP altogether. */ @@ -569,27 +623,49 @@ int is_dsp_inst(struct pt_regs *regs) #define is_dsp_inst(regs) (0) #endif /* CONFIG_SH_DSP */ +#ifdef CONFIG_CPU_SH2A +asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + siginfo_t info; + + switch (r4) { + case TRAP_DIVZERO_ERROR: + info.si_code = FPE_INTDIV; + break; + case TRAP_DIVOVF_ERROR: + info.si_code = FPE_INTOVF; + break; + } + + force_sig_info(SIGFPE, &info, current); +} +#endif + /* arch/sh/kernel/cpu/sh4/fpu.c */ extern int do_fpu_inst(unsigned short, struct pt_regs *); extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, struct pt_regs regs); + unsigned long r6, unsigned long r7, struct pt_regs __regs); asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); unsigned long error_code; struct task_struct *tsk = current; #ifdef CONFIG_SH_FPU_EMU - unsigned short inst; + unsigned short inst = 0; int err; - get_user(inst, (unsigned short*)regs.pc); + get_user(inst, (unsigned short*)regs->pc); - err = do_fpu_inst(inst, ®s); + err = do_fpu_inst(inst, regs); if (!err) { - regs.pc += 2; + regs->pc += 2; return; } /* not a FPU inst. */ @@ -597,20 +673,19 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, #ifdef CONFIG_SH_DSP /* Check if it's a DSP instruction */ - if (is_dsp_inst(®s)) { + if (is_dsp_inst(regs)) { /* Enable DSP mode, and restart instruction. */ - regs.sr |= SR_DSP; + regs->sr |= SR_DSP; return; } #endif - asm volatile("stc r2_bank, %0": "=r" (error_code)); + lookup_exception_vector(error_code); + local_irq_enable(); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = TRAP_RESERVED_INST; - CHK_REMOTE_DEBUG(®s); + CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); - die_if_no_fixup("reserved instruction", ®s, error_code); + die_if_no_fixup("reserved instruction", regs, error_code); } #ifdef CONFIG_SH_FPU_EMU @@ -658,39 +733,41 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs) asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); unsigned long error_code; struct task_struct *tsk = current; #ifdef CONFIG_SH_FPU_EMU - unsigned short inst; + unsigned short inst = 0; - get_user(inst, (unsigned short *)regs.pc + 1); - if (!do_fpu_inst(inst, ®s)) { - get_user(inst, (unsigned short *)regs.pc); - if (!emulate_branch(inst, ®s)) + get_user(inst, (unsigned short *)regs->pc + 1); + if (!do_fpu_inst(inst, regs)) { + get_user(inst, (unsigned short *)regs->pc); + if (!emulate_branch(inst, regs)) return; /* fault in branch.*/ } /* not a FPU inst. */ #endif - asm volatile("stc r2_bank, %0": "=r" (error_code)); + lookup_exception_vector(error_code); + local_irq_enable(); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = TRAP_RESERVED_INST; - CHK_REMOTE_DEBUG(®s); + CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); - die_if_no_fixup("illegal slot instruction", ®s, error_code); + die_if_no_fixup("illegal slot instruction", regs, error_code); } asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); long ex; - asm volatile("stc r2_bank, %0" : "=r" (ex)); - die_if_kernel("exception", ®s, ex); + + lookup_exception_vector(ex); + die_if_kernel("exception", regs, ex); } #if defined(CONFIG_SH_STANDARD_BIOS) @@ -735,12 +812,16 @@ void *set_exception_table_vec(unsigned int vec, void *handler) { extern void *exception_handling_table[]; void *old_handler; - + old_handler = exception_handling_table[vec]; exception_handling_table[vec] = handler; return old_handler; } +extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs); + void __init trap_init(void) { set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); @@ -759,7 +840,15 @@ void __init trap_init(void) set_exception_table_evt(0x800, do_fpu_state_restore); set_exception_table_evt(0x820, do_fpu_state_restore); #endif - + +#ifdef CONFIG_CPU_SH2 + set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler); +#endif +#ifdef CONFIG_CPU_SH2A + set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); + set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); +#endif + /* Setup VBR for boot cpu */ per_cpu_trap_init(); } @@ -784,6 +873,11 @@ void show_trace(struct task_struct *tsk, unsigned long *sp, } printk("\n"); + + if (!tsk) + tsk = current; + + debug_show_held_locks(tsk); } void show_stack(struct task_struct *tsk, unsigned long *sp) diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 9dd606464d2..4e0362f5038 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -4,8 +4,12 @@ menu "Processor selection" # Processor families # config CPU_SH2 + select SH_WRITETHROUGH if !CPU_SH2A bool - select SH_WRITETHROUGH + +config CPU_SH2A + bool + select CPU_SH2 config CPU_SH3 bool @@ -16,6 +20,7 @@ config CPU_SH4 bool select CPU_HAS_INTEVT select CPU_HAS_SR_RB + select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40 config CPU_SH4A bool @@ -40,6 +45,16 @@ config CPU_SUBTYPE_SH7604 bool "Support SH7604 processor" select CPU_SH2 +config CPU_SUBTYPE_SH7619 + bool "Support SH7619 processor" + select CPU_SH2 + +comment "SH-2A Processor Support" + +config CPU_SUBTYPE_SH7206 + bool "Support SH7206 processor" + select CPU_SH2A + comment "SH-3 Processor Support" config CPU_SUBTYPE_SH7300 @@ -89,6 +104,7 @@ comment "SH-4 Processor Support" config CPU_SUBTYPE_SH7750 bool "Support SH7750 processor" select CPU_SH4 + select CPU_HAS_IPR_IRQ help Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. @@ -104,15 +120,18 @@ config CPU_SUBTYPE_SH7750R bool "Support SH7750R processor" select CPU_SH4 select CPU_SUBTYPE_SH7750 + select CPU_HAS_IPR_IRQ config CPU_SUBTYPE_SH7750S bool "Support SH7750S processor" select CPU_SH4 select CPU_SUBTYPE_SH7750 + select CPU_HAS_IPR_IRQ config CPU_SUBTYPE_SH7751 bool "Support SH7751 processor" select CPU_SH4 + select CPU_HAS_IPR_IRQ help Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, or if you have a HD6417751R CPU. @@ -121,6 +140,7 @@ config CPU_SUBTYPE_SH7751R bool "Support SH7751R processor" select CPU_SH4 select CPU_SUBTYPE_SH7751 + select CPU_HAS_IPR_IRQ config CPU_SUBTYPE_SH7760 bool "Support SH7760 processor" @@ -157,6 +177,11 @@ config CPU_SUBTYPE_SH7780 select CPU_SH4A select CPU_HAS_INTC2_IRQ +config CPU_SUBTYPE_SH7785 + bool "Support SH7785 processor" + select CPU_SH4A + select CPU_HAS_INTC2_IRQ + comment "SH4AL-DSP Processor Support" config CPU_SUBTYPE_SH73180 @@ -216,13 +241,22 @@ config MEMORY_SIZE config 32BIT bool "Support 32-bit physical addressing through PMB" - depends on CPU_SH4A && MMU + depends on CPU_SH4A && MMU && (!X2TLB || BROKEN) default y help If you say Y here, physical addressing will be extended to 32-bits through the SH-4A PMB. If this is not set, legacy 29-bit physical addressing will be used. +config X2TLB + bool "Enable extended TLB mode" + depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL + help + Selecting this option will enable the extended mode of the SH-X2 + TLB. For legacy SH-X behaviour and interoperability, say N. For + all of the fun new features and a willingless to submit bug reports, + say Y. + config VSYSCALL bool "Support vsyscall page" depends on MMU @@ -237,16 +271,52 @@ config VSYSCALL (the default value) say Y. choice + prompt "Kernel page size" + default PAGE_SIZE_4KB + +config PAGE_SIZE_4KB + bool "4kB" + help + This is the default page size used by all SuperH CPUs. + +config PAGE_SIZE_8KB + bool "8kB" + depends on EXPERIMENTAL && X2TLB + help + This enables 8kB pages as supported by SH-X2 and later MMUs. + +config PAGE_SIZE_64KB + bool "64kB" + depends on EXPERIMENTAL && CPU_SH4 + help + This enables support for 64kB pages, possible on all SH-4 + CPUs and later. Highly experimental, not recommended. + +endchoice + +choice prompt "HugeTLB page size" depends on HUGETLB_PAGE && CPU_SH4 && MMU default HUGETLB_PAGE_SIZE_64K config HUGETLB_PAGE_SIZE_64K - bool "64K" + bool "64kB" + +config HUGETLB_PAGE_SIZE_256K + bool "256kB" + depends on X2TLB config HUGETLB_PAGE_SIZE_1MB bool "1MB" +config HUGETLB_PAGE_SIZE_4MB + bool "4MB" + depends on X2TLB + +config HUGETLB_PAGE_SIZE_64MB + bool "64MB" + depends on X2TLB + endchoice source "mm/Kconfig" @@ -274,7 +344,6 @@ config SH_DIRECT_MAPPED config SH_WRITETHROUGH bool "Use write-through caching" - default y if CPU_SH2 help Selecting this option will configure the caches in write-through mode, as opposed to the default write-back configuration. diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c index 2689cb24ea2..6614033f6be 100644 --- a/arch/sh/mm/cache-sh2.c +++ b/arch/sh/mm/cache-sh2.c @@ -5,6 +5,7 @@ * * Released under the terms of the GNU GPL v2.0. */ + #include <linux/init.h> #include <linux/mm.h> @@ -14,37 +15,43 @@ #include <asm/cacheflush.h> #include <asm/io.h> -/* - * Calculate the OC address and set the way bit on the SH-2. - * - * We must have already jump_to_P2()'ed prior to calling this - * function, since we rely on CCR manipulation to do the - * Right Thing(tm). - */ -unsigned long __get_oc_addr(unsigned long set, unsigned long way) +void __flush_wback_region(void *start, int size) { - unsigned long ccr; - - /* - * On SH-2 the way bit isn't tracked in the address field - * if we're doing address array access .. instead, we need - * to manually switch out the way in the CCR. - */ - ccr = ctrl_inl(CCR); - ccr &= ~0x00c0; - ccr |= way << cpu_data->dcache.way_shift; - - /* - * Despite the number of sets being halved, we end up losing - * the first 2 ways to OCRAM instead of the last 2 (if we're - * 4-way). As a result, forcibly setting the W1 bit handily - * bumps us up 2 ways. - */ - if (ccr & CCR_CACHE_ORA) - ccr |= 1 << (cpu_data->dcache.way_shift + 1); - - ctrl_outl(ccr, CCR); - - return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + /* FIXME cache purge */ + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } +} + +void __flush_purge_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } +} + +void __flush_invalidate_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } } diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index e48cc22724d..ae531affccb 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -11,12 +11,8 @@ */ #include <linux/init.h> #include <linux/mm.h> -#include <asm/addrspace.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/cache.h> -#include <asm/io.h> -#include <asm/pgalloc.h> +#include <linux/io.h> +#include <linux/mutex.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h> @@ -83,9 +79,9 @@ static void __init emit_cache_params(void) */ /* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */ -#define MAX_P3_SEMAPHORES 16 +#define MAX_P3_MUTEXES 16 -struct semaphore p3map_sem[MAX_P3_SEMAPHORES]; +struct mutex p3map_mutex[MAX_P3_MUTEXES]; void __init p3_cache_init(void) { @@ -115,7 +111,7 @@ void __init p3_cache_init(void) panic("%s failed.", __FUNCTION__); for (i = 0; i < cpu_data->dcache.n_aliases; i++) - sema_init(&p3map_sem[i], 1); + mutex_init(&p3map_mutex[i]); } /* @@ -229,7 +225,7 @@ static inline void flush_cache_4096(unsigned long start, */ if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) || (start < CACHE_OC_ADDRESS_ARRAY)) - exec_offset = 0x20000000; + exec_offset = 0x20000000; local_irq_save(flags); __flush_cache_4096(start | SH_CACHE_ASSOC, @@ -250,7 +246,7 @@ void flush_dcache_page(struct page *page) /* Loop all the D-cache */ n = cpu_data->dcache.n_aliases; - for (i = 0; i < n; i++, addr += PAGE_SIZE) + for (i = 0; i < n; i++, addr += 4096) flush_cache_4096(addr, phys); } diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S index 7b96425ae27..8a706131e52 100644 --- a/arch/sh/mm/clear_page.S +++ b/arch/sh/mm/clear_page.S @@ -1,12 +1,12 @@ -/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $ - * +/* * __clear_user_page, __clear_user, clear_page implementation of SuperH * * Copyright (C) 2001 Kaz Kojima * Copyright (C) 2001, 2002 Niibe Yutaka - * + * Copyright (C) 2006 Paul Mundt */ #include <linux/linkage.h> +#include <asm/page.h> /* * clear_page_slow @@ -18,11 +18,11 @@ /* * r0 --- scratch * r4 --- to - * r5 --- to + 4096 + * r5 --- to + PAGE_SIZE */ ENTRY(clear_page_slow) mov r4,r5 - mov.w .Llimit,r0 + mov.l .Llimit,r0 add r0,r5 mov #0,r0 ! @@ -50,7 +50,7 @@ ENTRY(clear_page_slow) ! rts nop -.Llimit: .word (4096-28) +.Llimit: .long (PAGE_SIZE-28) ENTRY(__clear_user) ! @@ -164,10 +164,10 @@ ENTRY(__clear_user) * r0 --- scratch * r4 --- to * r5 --- orig_to - * r6 --- to + 4096 + * r6 --- to + PAGE_SIZE */ ENTRY(__clear_user_page) - mov.w .L4096,r0 + mov.l .Lpsz,r0 mov r4,r6 add r0,r6 mov #0,r0 @@ -191,7 +191,7 @@ ENTRY(__clear_user_page) ! rts nop -.L4096: .word 4096 +.Lpsz: .long PAGE_SIZE #endif diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S index 1addffe117c..397c94c9731 100644 --- a/arch/sh/mm/copy_page.S +++ b/arch/sh/mm/copy_page.S @@ -1,12 +1,12 @@ -/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $ - * +/* * copy_page, __copy_user_page, __copy_user implementation of SuperH * * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima * Copyright (C) 2002 Toshinobu Sugioka - * + * Copyright (C) 2006 Paul Mundt */ #include <linux/linkage.h> +#include <asm/page.h> /* * copy_page_slow @@ -18,7 +18,7 @@ /* * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + 4096 + * r8 --- from + PAGE_SIZE * r9 --- not used * r10 --- to * r11 --- from @@ -30,7 +30,7 @@ ENTRY(copy_page_slow) mov r4,r10 mov r5,r11 mov r5,r8 - mov.w .L4096,r0 + mov.l .Lpsz,r0 add r0,r8 ! 1: mov.l @r11+,r0 @@ -80,7 +80,7 @@ ENTRY(copy_page_slow) /* * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + 4096 + * r8 --- from + PAGE_SIZE * r9 --- orig_to * r10 --- to * r11 --- from @@ -94,7 +94,7 @@ ENTRY(__copy_user_page) mov r5,r11 mov r6,r9 mov r5,r8 - mov.w .L4096,r0 + mov.l .Lpsz,r0 add r0,r8 ! 1: ocbi @r9 @@ -129,7 +129,7 @@ ENTRY(__copy_user_page) rts nop #endif -.L4096: .word 4096 +.Lpsz: .long PAGE_SIZE /* * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); * Return the number of bytes NOT copied diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 68663b8f99a..716ebf568af 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -26,13 +26,19 @@ extern void die(const char *,struct pt_regs *,long); * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, - unsigned long address) +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long page; + int si_code; + siginfo_t info; + + trace_hardirqs_on(); + local_irq_enable(); #ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) @@ -41,6 +47,46 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, tsk = current; mm = tsk->mm; + si_code = SEGV_MAPERR; + + if (unlikely(address >= TASK_SIZE)) { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = pgd_index(address); + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd = get_TTB() + offset; + pgd_k = swapper_pg_dir + offset; + + /* This will never happen with the folded page table. */ + if (!pgd_present(*pgd)) { + if (!pgd_present(*pgd_k)) + goto bad_area_nosemaphore; + set_pgd(pgd, *pgd_k); + return; + } + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (pud_present(*pud) || !pud_present(*pud_k)) + goto bad_area_nosemaphore; + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (pmd_present(*pmd) || !pmd_present(*pmd_k)) + goto bad_area_nosemaphore; + set_pmd(pmd, *pmd_k); + + return; + } /* * If we're in an interrupt or have no user @@ -65,6 +111,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, * we can handle it.. */ good_area: + si_code = SEGV_ACCERR; if (writeaccess) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; @@ -104,10 +151,13 @@ survive: bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: if (user_mode(regs)) { - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - force_sig(SIGSEGV, tsk); + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); return; } @@ -127,11 +177,9 @@ no_context: printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at virtual address %08lx\n", address); printk(KERN_ALERT "pc = %08lx\n", regs->pc); - asm volatile("mov.l %1, %0" - : "=r" (page) - : "m" (__m(MMU_TTB))); + page = (unsigned long)get_TTB(); if (page) { - page = ((unsigned long *) page)[address >> 22]; + page = ((unsigned long *) page)[address >> PGDIR_SHIFT]; printk(KERN_ALERT "*pde = %08lx\n", page); if (page & _PAGE_PRESENT) { page &= PAGE_MASK; @@ -166,98 +214,13 @@ do_sigbus: * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - tsk->thread.trap_no = 14; - force_sig(SIGBUS, tsk); + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info(SIGBUS, &info, tsk); /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) goto no_context; } - -#ifdef CONFIG_SH_STORE_QUEUES -/* - * This is a special case for the SH-4 store queues, as pages for this - * space still need to be faulted in before it's possible to flush the - * store queue cache for writeout to the remapped region. - */ -#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000) -#else -#define P3_ADDR_MAX P4SEG -#endif - -/* - * Called with interrupts disabled. - */ -asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, - unsigned long writeaccess, - unsigned long address) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - pte_t entry; - struct mm_struct *mm = current->mm; - spinlock_t *ptl; - int ret = 1; - -#ifdef CONFIG_SH_KGDB - if (kgdb_nofault && kgdb_bus_err_hook) - kgdb_bus_err_hook(); -#endif - - /* - * We don't take page faults for P1, P2, and parts of P4, these - * are always mapped, whether it be due to legacy behaviour in - * 29-bit mode, or due to PMB configuration in 32-bit mode. - */ - if (address >= P3SEG && address < P3_ADDR_MAX) { - pgd = pgd_offset_k(address); - mm = NULL; - } else { - if (unlikely(address >= TASK_SIZE || !mm)) - return 1; - - pgd = pgd_offset(mm, address); - } - - pud = pud_offset(pgd, address); - if (pud_none_or_clear_bad(pud)) - return 1; - pmd = pmd_offset(pud, address); - if (pmd_none_or_clear_bad(pmd)) - return 1; - - if (mm) - pte = pte_offset_map_lock(mm, pmd, address, &ptl); - else - pte = pte_offset_kernel(pmd, address); - - entry = *pte; - if (unlikely(pte_none(entry) || pte_not_present(entry))) - goto unlock; - if (unlikely(writeaccess && !pte_write(entry))) - goto unlock; - - if (writeaccess) - entry = pte_mkdirty(entry); - entry = pte_mkyoung(entry); - -#ifdef CONFIG_CPU_SH4 - /* - * ITLB is not affected by "ldtlb" instruction. - * So, we need to flush the entry by ourselves. - */ - __flush_tlb_page(get_asid(), address & PAGE_MASK); -#endif - - set_pte(pte, entry); - update_mmu_cache(NULL, address, entry); - ret = 0; -unlock: - if (mm) - pte_unmap_unlock(pte, ptl); - return ret; -} diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 7154d1ce978..59f4cc18235 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) pmd_t *pmd; pte_t *pte; - pgd = swapper_pg_dir + pgd_index(addr); + pgd = pgd_offset_k(addr); if (pgd_none(*pgd)) { pgd_ERROR(*pgd); return; } - pud = pud_offset(pgd, addr); - if (pud_none(*pud)) { - pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); - set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); - if (pmd != pmd_offset(pud, 0)) { - pud_ERROR(*pud); - return; - } + pud = pud_alloc(NULL, pgd, addr); + if (unlikely(!pud)) { + pud_ERROR(*pud); + return; } - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) { - pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); - set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); - if (pte != pte_offset_kernel(pmd, 0)) { - pmd_ERROR(*pmd); - return; - } + pmd = pmd_alloc(NULL, pud, addr); + if (unlikely(!pmd)) { + pmd_ERROR(*pmd); + return; } pte = pte_offset_kernel(pmd, addr); @@ -155,9 +147,6 @@ extern char __init_begin, __init_end; /* * paging_init() sets up the page tables - * - * This routines also unmaps the page at virtual kernel address 0, so - * that we can trap those pesky NULL-reference errors in the kernel. */ void __init paging_init(void) { @@ -180,14 +169,11 @@ void __init paging_init(void) */ { unsigned long max_dma, low, start_pfn; - pgd_t *pg_dir; - int i; - - /* We don't need kernel mapping as hardware support that. */ - pg_dir = swapper_pg_dir; - for (i = 0; i < PTRS_PER_PGD; i++) - pgd_val(pg_dir[i]) = 0; + /* We don't need to map the kernel through the TLB, as + * it is permanatly mapped using P1. So clear the + * entire pgd. */ + memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); /* Turn on the MMU */ enable_mmu(); @@ -206,6 +192,10 @@ void __init paging_init(void) } } + /* Set an initial value for the MMU.TTB so we don't have to + * check for a null value. */ + set_TTB(swapper_pg_dir); + #elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) /* * If we don't have CONFIG_MMU set and the processor in question @@ -227,7 +217,6 @@ static struct kcore_list kcore_mem, kcore_vmalloc; void __init mem_init(void) { - extern unsigned long empty_zero_page[1024]; int codesize, reservedpages, datasize, initsize; int tmp; extern unsigned long memory_start; diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index a9fe80cfc23..11d54c14982 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -28,9 +28,7 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address, { unsigned long end; unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags); + pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); address &= ~PMD_MASK; end = address + size; diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c index 1406d2e348c..bb23679369d 100644 --- a/arch/sh/mm/pg-dma.c +++ b/arch/sh/mm/pg-dma.c @@ -39,8 +39,6 @@ static void copy_page_dma(void *to, void *from) static void clear_page_dma(void *to) { - extern unsigned long empty_zero_page[1024]; - /* * We get invoked quite early on, if the DMAC hasn't been initialized * yet, fall back on the slow manual implementation. diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 07371ed7a31..3f98d2a4f93 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -6,22 +6,12 @@ * * Released under the terms of the GNU GPL v2.0. */ -#include <linux/init.h> -#include <linux/mman.h> #include <linux/mm.h> -#include <linux/threads.h> -#include <asm/addrspace.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/cache.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/pgalloc.h> +#include <linux/mutex.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h> -extern struct semaphore p3map_sem[]; +extern struct mutex p3map_mutex[]; #define CACHE_ALIAS (cpu_data->dcache.alias_mask) @@ -37,10 +27,6 @@ void clear_user_page(void *to, unsigned long address, struct page *page) if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) clear_page(to); else { - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | - _PAGE_RW | _PAGE_CACHABLE | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); unsigned long phys_addr = PHYSADDR(to); unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *pgd = pgd_offset_k(p3_addr); @@ -50,8 +36,8 @@ void clear_user_page(void *to, unsigned long address, struct page *page) pte_t entry; unsigned long flags; - entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); - down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); + mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); set_pte(pte, entry); local_irq_save(flags); __flush_tlb_page(get_asid(), p3_addr); @@ -59,7 +45,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page) update_mmu_cache(NULL, p3_addr, entry); __clear_user_page((void *)p3_addr, to); pte_clear(&init_mm, p3_addr, pte); - up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } @@ -77,10 +63,6 @@ void copy_user_page(void *to, void *from, unsigned long address, if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) copy_page(to, from); else { - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | - _PAGE_RW | _PAGE_CACHABLE | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); unsigned long phys_addr = PHYSADDR(to); unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *pgd = pgd_offset_k(p3_addr); @@ -90,8 +72,8 @@ void copy_user_page(void *to, void *from, unsigned long address, pte_t entry; unsigned long flags; - entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); - down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); + mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); set_pte(pte, entry); local_irq_save(flags); __flush_tlb_page(get_asid(), p3_addr); @@ -99,7 +81,7 @@ void copy_user_page(void *to, void *from, unsigned long address, update_mmu_cache(NULL, p3_addr, entry); __copy_user_page((void *)p3_addr, from, to); pte_clear(&init_mm, p3_addr, pte); - up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } @@ -122,4 +104,3 @@ inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t } return pte; } - diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index ac57638977e..0571755e9a8 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -30,3 +30,5 @@ R7780MP SH_R7780MP TITAN SH_TITAN SHMIN SH_SHMIN 7710VOIPGW SH_7710VOIPGW +7206SE SH_7206_SOLUTION_ENGINE +7619SE SH_7619_SOLUTION_ENGINE diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 3576b3cc505..7d4190e5565 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -638,7 +638,7 @@ int chan_out_fd(struct list_head *chans) return -1; } -void chan_interrupt(struct list_head *chans, struct work_struct *task, +void chan_interrupt(struct list_head *chans, struct delayed_work *task, struct tty_struct *tty, int irq) { struct list_head *ele, *next; diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 7b172160fe0..96f0189327a 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -56,7 +56,7 @@ static struct notifier_block reboot_notifier = { static LIST_HEAD(mc_requests); -static void mc_work_proc(void *unused) +static void mc_work_proc(struct work_struct *unused) { struct mconsole_entry *req; unsigned long flags; @@ -72,7 +72,7 @@ static void mc_work_proc(void *unused) } } -static DECLARE_WORK(mconsole_work, mc_work_proc, NULL); +static DECLARE_WORK(mconsole_work, mc_work_proc); static irqreturn_t mconsole_interrupt(int irq, void *dev_id) { diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index ec9eb8bd943..286bc0b3207 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -99,6 +99,7 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) * same device, since it tests for (dev->flags & IFF_UP). So * there's no harm in delaying the device shutdown. */ schedule_work(&close_work); +#error this is not permitted - close_work will go out of scope goto out; } reactivate_fd(lp->fd, UM_ETH_IRQ); diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index ce9f3733f73..6dfe632f1c1 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -132,7 +132,7 @@ static int port_accept(struct port_list *port) DECLARE_MUTEX(ports_sem); struct list_head ports = LIST_HEAD_INIT(ports); -void port_work_proc(void *unused) +void port_work_proc(struct work_struct *unused) { struct port_list *port; struct list_head *ele; @@ -150,7 +150,7 @@ void port_work_proc(void *unused) local_irq_restore(flags); } -DECLARE_WORK(port_work, port_work_proc, NULL); +DECLARE_WORK(port_work, port_work_proc); static irqreturn_t port_interrupt(int irq, void *data) { diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index bbea88801d8..c7587fc3901 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -306,8 +306,8 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status) */ static int check_interval = 5 * 60; /* 5 minutes */ -static void mcheck_timer(void *data); -static DECLARE_WORK(mcheck_work, mcheck_timer, NULL); +static void mcheck_timer(struct work_struct *work); +static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer); static void mcheck_check_cpu(void *info) { @@ -315,7 +315,7 @@ static void mcheck_check_cpu(void *info) do_machine_check(NULL, 0); } -static void mcheck_timer(void *data) +static void mcheck_timer(struct work_struct *work) { on_each_cpu(mcheck_check_cpu, NULL, 1, 1); schedule_delayed_work(&mcheck_work, check_interval * HZ); diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 62c2e747af5..9800147c4c6 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -753,14 +753,16 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta } struct create_idle { + struct work_struct work; struct task_struct *idle; struct completion done; int cpu; }; -void do_fork_idle(void *_c_idle) +void do_fork_idle(struct work_struct *work) { - struct create_idle *c_idle = _c_idle; + struct create_idle *c_idle = + container_of(work, struct create_idle, work); c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); @@ -775,10 +777,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) int timeout; unsigned long start_rip; struct create_idle c_idle = { + .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), }; - DECLARE_WORK(work, do_fork_idle, &c_idle); /* allocate memory for gdts of secondary cpus. Hotplug is considered */ if (!cpu_gdt_descr[cpu].address && @@ -825,9 +827,9 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) * thread. */ if (!keventd_up() || current_is_keventd()) - work.func(work.data); + c_idle.work.func(&c_idle.work); else { - schedule_work(&work); + schedule_work(&c_idle.work); wait_for_completion(&c_idle.done); } diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index e3ef544d2cf..9f05bc9b2da 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -563,7 +563,7 @@ static unsigned int cpufreq_delayed_issched = 0; static unsigned int cpufreq_init = 0; static struct work_struct cpufreq_delayed_get_work; -static void handle_cpufreq_delayed_get(void *v) +static void handle_cpufreq_delayed_get(struct work_struct *v) { unsigned int cpu; for_each_online_cpu(cpu) { @@ -639,7 +639,7 @@ static struct notifier_block time_cpufreq_notifier_block = { static int __init cpufreq_tsc(void) { - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); if (!cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER)) cpufreq_init = 1; diff --git a/block/as-iosched.c b/block/as-iosched.c index 00242111a45..5934c4bfd52 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1274,9 +1274,10 @@ static void as_merged_requests(request_queue_t *q, struct request *req, * * FIXME! dispatch queue is not a queue at all! */ -static void as_work_handler(void *data) +static void as_work_handler(struct work_struct *work) { - struct request_queue *q = data; + struct as_data *ad = container_of(work, struct as_data, antic_work); + struct request_queue *q = ad->q; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -1332,7 +1333,7 @@ static void *as_init_queue(request_queue_t *q) ad->antic_timer.function = as_antic_timeout; ad->antic_timer.data = (unsigned long)q; init_timer(&ad->antic_timer); - INIT_WORK(&ad->antic_work, as_work_handler, q); + INIT_WORK(&ad->antic_work, as_work_handler); INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index e9019ed39b7..84e9be07318 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1840,9 +1840,11 @@ queue_fail: return 1; } -static void cfq_kick_queue(void *data) +static void cfq_kick_queue(struct work_struct *work) { - request_queue_t *q = data; + struct cfq_data *cfqd = + container_of(work, struct cfq_data, unplug_work); + request_queue_t *q = cfqd->queue; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -1986,7 +1988,7 @@ static void *cfq_init_queue(request_queue_t *q) cfqd->idle_class_timer.function = cfq_idle_class_timer; cfqd->idle_class_timer.data = (unsigned long) cfqd; - INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); + INIT_WORK(&cfqd->unplug_work, cfq_kick_queue); cfqd->cfq_quantum = cfq_quantum; cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 0f82e12f7b6..cc6e95f8e5d 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -34,7 +34,7 @@ */ #include <scsi/scsi_cmnd.h> -static void blk_unplug_work(void *data); +static void blk_unplug_work(struct work_struct *work); static void blk_unplug_timeout(unsigned long data); static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); static void init_request_from_bio(struct request *req, struct bio *bio); @@ -227,7 +227,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) if (q->unplug_delay == 0) q->unplug_delay = 1; - INIT_WORK(&q->unplug_work, blk_unplug_work, q); + INIT_WORK(&q->unplug_work, blk_unplug_work); q->unplug_timer.function = blk_unplug_timeout; q->unplug_timer.data = (unsigned long)q; @@ -1631,9 +1631,9 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, } } -static void blk_unplug_work(void *data) +static void blk_unplug_work(struct work_struct *work) { - request_queue_t *q = data; + request_queue_t *q = container_of(work, request_queue_t, unplug_work); blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, q->rq.count[READ] + q->rq.count[WRITE]); diff --git a/crypto/cryptomgr.c b/crypto/cryptomgr.c index 9b5b1560106..2ebffb84f1d 100644 --- a/crypto/cryptomgr.c +++ b/crypto/cryptomgr.c @@ -40,9 +40,10 @@ struct cryptomgr_param { char template[CRYPTO_MAX_ALG_NAME]; }; -static void cryptomgr_probe(void *data) +static void cryptomgr_probe(struct work_struct *work) { - struct cryptomgr_param *param = data; + struct cryptomgr_param *param = + container_of(work, struct cryptomgr_param, work); struct crypto_template *tmpl; struct crypto_instance *inst; int err; @@ -112,7 +113,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) param->larval.type = larval->alg.cra_flags; param->larval.mask = larval->mask; - INIT_WORK(¶m->work, cryptomgr_probe, param); + INIT_WORK(¶m->work, cryptomgr_probe); schedule_work(¶m->work); return NOTIFY_STOP; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 068fe4f100b..02b30ae6a68 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -50,6 +50,7 @@ ACPI_MODULE_NAME("osl") struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; + struct work_struct work; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -564,12 +565,9 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); } -static void acpi_os_execute_deferred(void *context) +static void acpi_os_execute_deferred(struct work_struct *work) { - struct acpi_os_dpc *dpc = NULL; - - - dpc = (struct acpi_os_dpc *)context; + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); if (!dpc) { printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); return; @@ -602,7 +600,6 @@ acpi_status acpi_os_execute(acpi_execute_type type, { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; - struct work_struct *task; ACPI_FUNCTION_TRACE("os_queue_for_execution"); @@ -615,28 +612,22 @@ acpi_status acpi_os_execute(acpi_execute_type type, /* * Allocate/initialize DPC structure. Note that this memory will be - * freed by the callee. The kernel handles the tq_struct list in a + * freed by the callee. The kernel handles the work_struct list in a * way that allows us to also free its memory inside the callee. * Because we may want to schedule several tasks with different * parameters we can't use the approach some kernel code uses of - * having a static tq_struct. - * We can save time and code by allocating the DPC and tq_structs - * from the same memory. + * having a static work_struct. */ - dpc = - kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), - GFP_ATOMIC); + dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); if (!dpc) return_ACPI_STATUS(AE_NO_MEMORY); dpc->function = function; dpc->context = context; - task = (void *)(dpc + 1); - INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - - if (!queue_work(kacpid_wq, task)) { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); kfree(dpc); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f8ec3896b79..8816e30fb7a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1081,7 +1081,7 @@ static unsigned int ata_id_xfermask(const u16 *id) * ata_port_queue_task - Queue port_task * @ap: The ata_port to queue port_task for * @fn: workqueue function to be scheduled - * @data: data value to pass to workqueue function + * @data: data for @fn to use * @delay: delay time for workqueue function * * Schedule @fn(@data) for execution after @delay jiffies using @@ -1096,7 +1096,7 @@ static unsigned int ata_id_xfermask(const u16 *id) * LOCKING: * Inherited from caller. */ -void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, +void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay) { int rc; @@ -1104,12 +1104,10 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK) return; - PREPARE_WORK(&ap->port_task, fn, data); + PREPARE_DELAYED_WORK(&ap->port_task, fn); + ap->port_task_data = data; - if (!delay) - rc = queue_work(ata_wq, &ap->port_task); - else - rc = queue_delayed_work(ata_wq, &ap->port_task, delay); + rc = queue_delayed_work(ata_wq, &ap->port_task, delay); /* rc == 0 means that another user is using port task */ WARN_ON(rc == 0); @@ -4588,10 +4586,11 @@ fsm_start: return poll_next; } -static void ata_pio_task(void *_data) +static void ata_pio_task(struct work_struct *work) { - struct ata_queued_cmd *qc = _data; - struct ata_port *ap = qc->ap; + struct ata_port *ap = + container_of(work, struct ata_port, port_task.work); + struct ata_queued_cmd *qc = ap->port_task_data; u8 status; int poll_next; @@ -5635,9 +5634,9 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host, ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; #endif - INIT_WORK(&ap->port_task, NULL, NULL); - INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); - INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); + INIT_DELAYED_WORK(&ap->port_task, NULL); + INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 76a85dfb730..08ad44b3e48 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -332,7 +332,7 @@ void ata_scsi_error(struct Scsi_Host *host) if (ap->pflags & ATA_PFLAG_LOADING) ap->pflags &= ~ATA_PFLAG_LOADING; else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) - queue_work(ata_aux_wq, &ap->hotplug_task); + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, 0); if (ap->pflags & ATA_PFLAG_RECOVERED) ata_port_printk(ap, KERN_INFO, "EH complete\n"); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8eaace94d96..664e1377b54 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2963,7 +2963,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev) /** * ata_scsi_hotplug - SCSI part of hotplug - * @data: Pointer to ATA port to perform SCSI hotplug on + * @work: Pointer to ATA port to perform SCSI hotplug on * * Perform SCSI part of hotplug. It's executed from a separate * workqueue after EH completes. This is necessary because SCSI @@ -2973,9 +2973,10 @@ static void ata_scsi_remove_dev(struct ata_device *dev) * LOCKING: * Kernel thread context (may sleep). */ -void ata_scsi_hotplug(void *data) +void ata_scsi_hotplug(struct work_struct *work) { - struct ata_port *ap = data; + struct ata_port *ap = + container_of(work, struct ata_port, hotplug_task.work); int i; if (ap->pflags & ATA_PFLAG_UNLOADING) { @@ -3076,7 +3077,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, /** * ata_scsi_dev_rescan - initiate scsi_rescan_device() - * @data: Pointer to ATA port to perform scsi_rescan_device() + * @work: Pointer to ATA port to perform scsi_rescan_device() * * After ATA pass thru (SAT) commands are executed successfully, * libata need to propagate the changes to SCSI layer. This @@ -3086,9 +3087,10 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, * LOCKING: * Kernel thread context (may sleep). */ -void ata_scsi_dev_rescan(void *data) +void ata_scsi_dev_rescan(struct work_struct *work) { - struct ata_port *ap = data; + struct ata_port *ap = + container_of(work, struct ata_port, scsi_rescan_task); unsigned long flags; unsigned int i; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 107b2b56522..81ae41d5f23 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -94,7 +94,7 @@ extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); extern int ata_scsi_offline_dev(struct ata_device *dev); -extern void ata_scsi_hotplug(void *data); +extern void ata_scsi_hotplug(struct work_struct *work); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); @@ -124,7 +124,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); -extern void ata_scsi_dev_rescan(void *data); +extern void ata_scsi_dev_rescan(struct work_struct *work); extern int ata_bus_probe(struct ata_port *ap); /* libata-eh.c */ diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 87b17c33b3f..f4078612194 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -135,7 +135,7 @@ static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags); static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page); -static void idt77252_softint(void *dev_id); +static void idt77252_softint(struct work_struct *work); static struct atmdev_ops idt77252_ops = @@ -2866,9 +2866,10 @@ out: } static void -idt77252_softint(void *dev_id) +idt77252_softint(struct work_struct *work) { - struct idt77252_dev *card = dev_id; + struct idt77252_dev *card = + container_of(work, struct idt77252_dev, tqueue); u32 stat; int done; @@ -3697,7 +3698,7 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) card->pcidev = pcidev; sprintf(card->name, "idt77252-%d", card->index); - INIT_WORK(&card->tqueue, idt77252_softint, (void *)card); + INIT_WORK(&card->tqueue, idt77252_softint); membase = pci_resource_start(pcidev, 1); srambase = pci_resource_start(pcidev, 2); diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 6d111228cfa..2308e83e5f3 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -159,7 +159,7 @@ void aoecmd_work(struct aoedev *d); void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); void aoecmd_ata_rsp(struct sk_buff *); void aoecmd_cfg_rsp(struct sk_buff *); -void aoecmd_sleepwork(void *vp); +void aoecmd_sleepwork(struct work_struct *); struct sk_buff *new_skb(ulong); int aoedev_init(void); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 8a13b1af8ba..97f7f535f41 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -408,9 +408,9 @@ rexmit_timer(ulong vp) /* this function performs work that has been deferred until sleeping is OK */ void -aoecmd_sleepwork(void *vp) +aoecmd_sleepwork(struct work_struct *work) { - struct aoedev *d = (struct aoedev *) vp; + struct aoedev *d = container_of(work, struct aoedev, work); if (d->flags & DEVFL_GDALLOC) aoeblk_gdalloc(d); diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 6125921bbec..05a97197c91 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -88,7 +88,7 @@ aoedev_newdev(ulong nframes) kfree(d); return NULL; } - INIT_WORK(&d->work, aoecmd_sleepwork, d); + INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); init_timer(&d->timer); d->timer.data = (ulong) d; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 9e6d3a87cbe..3f1b38276e9 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -992,11 +992,11 @@ static void empty(void) { } -static DECLARE_WORK(floppy_work, NULL, NULL); +static DECLARE_WORK(floppy_work, NULL); static void schedule_bh(void (*handler) (void)) { - PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)handler); schedule_work(&floppy_work); } @@ -1008,7 +1008,7 @@ static void cancel_activity(void) spin_lock_irqsave(&floppy_lock, flags); do_floppy = NULL; - PREPARE_WORK(&floppy_work, (void *)empty, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)empty); del_timer(&fd_timer); spin_unlock_irqrestore(&floppy_lock, flags); } @@ -1868,7 +1868,7 @@ static void show_floppy(void) printk("fdc_busy=%lu\n", fdc_busy); if (do_floppy) printk("do_floppy=%p\n", do_floppy); - if (floppy_work.pending) + if (work_pending(&floppy_work)) printk("floppy_work.func=%p\n", floppy_work.func); if (timer_pending(&fd_timer)) printk("fd_timer.function=%p\n", fd_timer.function); @@ -4498,7 +4498,7 @@ static void floppy_release_irq_and_dma(void) printk("floppy timer still active:%s\n", timeout_message); if (timer_pending(&fd_timer)) printk("auxiliary floppy timer still active\n"); - if (floppy_work.pending) + if (work_pending(&floppy_work)) printk("work still pending\n"); #endif old_fdc = fdc; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 40a11e56797..9d9bff23f42 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -352,19 +352,19 @@ static enum action (*phase)(void); static void run_fsm(void); -static void ps_tq_int( void *data); +static void ps_tq_int(struct work_struct *work); -static DECLARE_WORK(fsm_tq, ps_tq_int, NULL); +static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int); static void schedule_fsm(void) { if (!nice) - schedule_work(&fsm_tq); + schedule_delayed_work(&fsm_tq, 0); else schedule_delayed_work(&fsm_tq, nice-1); } -static void ps_tq_int(void *data) +static void ps_tq_int(struct work_struct *work) { run_fsm(); } diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h index 932342d7a8e..bc370329414 100644 --- a/drivers/block/paride/pseudo.h +++ b/drivers/block/paride/pseudo.h @@ -35,7 +35,7 @@ #include <linux/sched.h> #include <linux/workqueue.h> -static void ps_tq_int( void *data); +static void ps_tq_int(struct work_struct *work); static void (* ps_continuation)(void); static int (* ps_ready)(void); @@ -45,7 +45,7 @@ static int ps_nice = 0; static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused))); -static DECLARE_WORK(ps_tq, ps_tq_int, NULL); +static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int); static void ps_set_intr(void (*continuation)(void), int (*ready)(void), @@ -63,14 +63,14 @@ static void ps_set_intr(void (*continuation)(void), if (!ps_tq_active) { ps_tq_active = 1; if (!ps_nice) - schedule_work(&ps_tq); + schedule_delayed_work(&ps_tq, 0); else schedule_delayed_work(&ps_tq, ps_nice-1); } spin_unlock_irqrestore(&ps_spinlock,flags); } -static void ps_tq_int(void *data) +static void ps_tq_int(struct work_struct *work) { void (*con)(void); unsigned long flags; @@ -92,7 +92,7 @@ static void ps_tq_int(void *data) } ps_tq_active = 1; if (!ps_nice) - schedule_work(&ps_tq); + schedule_delayed_work(&ps_tq, 0); else schedule_delayed_work(&ps_tq, ps_nice-1); spin_unlock_irqrestore(&ps_spinlock,flags); diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 47d6975268f..54509eb3391 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -1244,9 +1244,10 @@ out: return IRQ_RETVAL(handled); } -static void carm_fsm_task (void *_data) +static void carm_fsm_task (struct work_struct *work) { - struct carm_host *host = _data; + struct carm_host *host = + container_of(work, struct carm_host, fsm_task); unsigned long flags; unsigned int state; int rc, i, next_dev; @@ -1619,7 +1620,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) host->pdev = pdev; host->flags = pci_dac ? FL_DAC : 0; spin_lock_init(&host->lock); - INIT_WORK(&host->fsm_task, carm_fsm_task, host); + INIT_WORK(&host->fsm_task, carm_fsm_task); init_completion(&host->probe_comp); for (i = 0; i < ARRAY_SIZE(host->req); i++) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 0d5c73f0726..2098eff91e1 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -376,7 +376,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int stalled_pipe); static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); static void ub_reset_enter(struct ub_dev *sc, int try); -static void ub_reset_task(void *arg); +static void ub_reset_task(struct work_struct *work); static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret); @@ -1558,9 +1558,9 @@ static void ub_reset_enter(struct ub_dev *sc, int try) schedule_work(&sc->reset_work); } -static void ub_reset_task(void *arg) +static void ub_reset_task(struct work_struct *work) { - struct ub_dev *sc = arg; + struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); unsigned long flags; struct list_head *p; struct ub_lun *lun; @@ -2179,7 +2179,7 @@ static int ub_probe(struct usb_interface *intf, usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); - INIT_WORK(&sc->reset_work, ub_reset_task, sc); + INIT_WORK(&sc->reset_work, ub_reset_task); init_waitqueue_head(&sc->reset_wait); init_timer(&sc->work_timer); diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 516751754aa..9256985cbe3 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -157,9 +157,10 @@ static void bcm203x_complete(struct urb *urb) } } -static void bcm203x_work(void *user_data) +static void bcm203x_work(struct work_struct *work) { - struct bcm203x_data *data = user_data; + struct bcm203x_data *data = + container_of(work, struct bcm203x_data, work); if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); @@ -246,7 +247,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id release_firmware(firmware); - INIT_WORK(&data->work, bcm203x_work, (void *) data); + INIT_WORK(&data->work, bcm203x_work); usb_set_intfdata(intf, data); diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e608dadece2..acb2de5e3a9 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -926,9 +926,10 @@ cy_sched_event(struct cyclades_port *info, int event) * had to poll every port to see if that port needed servicing. */ static void -do_softint(void *private_) +do_softint(struct work_struct *work) { - struct cyclades_port *info = (struct cyclades_port *) private_; + struct cyclades_port *info = + container_of(work, struct cyclades_port, tqueue); struct tty_struct *tty; tty = info->tty; @@ -5328,7 +5329,7 @@ cy_init(void) info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue, do_softint); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->shutdown_wait); @@ -5403,7 +5404,7 @@ cy_init(void) info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue, do_softint); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->shutdown_wait); diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 60c1695db30..806f9ce5f47 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -500,9 +500,9 @@ via_dmablit_timer(unsigned long data) static void -via_dmablit_workqueue(void *data) +via_dmablit_workqueue(struct work_struct *work) { - drm_via_blitq_t *blitq = (drm_via_blitq_t *) data; + drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq); drm_device_t *dev = blitq->dev; unsigned long irqsave; drm_via_sg_info_t *cur_sg; @@ -571,7 +571,7 @@ via_init_dmablit(drm_device_t *dev) DRM_INIT_WAITQUEUE(blitq->blit_queue + j); } DRM_INIT_WAITQUEUE(&blitq->busy_queue); - INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq); + INIT_WORK(&blitq->wq, via_dmablit_workqueue); init_timer(&blitq->poll_timer); blitq->poll_timer.function = &via_dmablit_timer; blitq->poll_timer.data = (unsigned long) blitq; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 706733c0b36..7c71eb77980 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -200,7 +200,7 @@ static int pc_ioctl(struct tty_struct *, struct file *, static int info_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void pc_set_termios(struct tty_struct *, struct termios *); -static void do_softint(void *); +static void do_softint(struct work_struct *work); static void pc_stop(struct tty_struct *); static void pc_start(struct tty_struct *); static void pc_throttle(struct tty_struct * tty); @@ -1505,7 +1505,7 @@ static void post_fep_init(unsigned int crd) ch->brdchan = bc; ch->mailbox = gd; - INIT_WORK(&ch->tqueue, do_softint, ch); + INIT_WORK(&ch->tqueue, do_softint); ch->board = &boards[crd]; spin_lock_irqsave(&epca_lock, flags); @@ -2566,9 +2566,9 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) /* --------------------- Begin do_softint ----------------------- */ -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { /* Begin do_softint */ - struct channel *ch = (struct channel *) private_; + struct channel *ch = container_of(work, struct channel, tqueue); /* Called in response to a modem change event */ if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */ struct tty_struct *tty = ch->tty; diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 15a4ea89632..93b55196251 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -723,9 +723,10 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * ------------------------------------------------------------------- */ -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { - struct esp_struct *info = (struct esp_struct *) private_; + struct esp_struct *info = + container_of(work, struct esp_struct, tqueue); struct tty_struct *tty; tty = info->tty; @@ -746,9 +747,10 @@ static void do_softint(void *private_) * do_serial_hangup() -> tty->hangup() -> esp_hangup() * */ -static void do_serial_hangup(void *private_) +static void do_serial_hangup(struct work_struct *work) { - struct esp_struct *info = (struct esp_struct *) private_; + struct esp_struct *info = + container_of(work, struct esp_struct, tqueue_hangup); struct tty_struct *tty; tty = info->tty; @@ -2501,8 +2503,8 @@ static int __init espserial_init(void) info->magic = ESP_MAGIC; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; - INIT_WORK(&info->tqueue, do_softint, info); - INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + INIT_WORK(&info->tqueue, do_softint); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup); info->config.rx_timeout = rx_timeout; info->config.flow_on = flow_on; info->config.flow_off = flow_off; diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 817dc409ac2..23b25ada65e 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -102,7 +102,7 @@ static void gen_rtc_interrupt(unsigned long arg); * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -static void genrtc_troutine(void *data) +static void genrtc_troutine(struct work_struct *work) { unsigned int tmp = get_rtc_ss(); @@ -255,7 +255,7 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit) irq_active = 1; stop_rtc_timers = 0; lostint = 0; - INIT_WORK(&genrtc_task, genrtc_troutine, NULL); + INIT_WORK(&genrtc_task, genrtc_troutine); oldsecs = get_rtc_ss(); init_timer(&timer_task); diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 2cf63e7305a..82a41d5b4ed 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -69,7 +69,7 @@ #define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) struct hvsi_struct { - struct work_struct writer; + struct delayed_work writer; struct work_struct handshaker; wait_queue_head_t emptyq; /* woken when outbuf is emptied */ wait_queue_head_t stateq; /* woken when HVSI state changes */ @@ -744,9 +744,10 @@ static int hvsi_handshake(struct hvsi_struct *hp) return 0; } -static void hvsi_handshaker(void *arg) +static void hvsi_handshaker(struct work_struct *work) { - struct hvsi_struct *hp = (struct hvsi_struct *)arg; + struct hvsi_struct *hp = + container_of(work, struct hvsi_struct, handshaker); if (hvsi_handshake(hp) >= 0) return; @@ -951,9 +952,10 @@ static void hvsi_push(struct hvsi_struct *hp) } /* hvsi_write_worker will keep rescheduling itself until outbuf is empty */ -static void hvsi_write_worker(void *arg) +static void hvsi_write_worker(struct work_struct *work) { - struct hvsi_struct *hp = (struct hvsi_struct *)arg; + struct hvsi_struct *hp = + container_of(work, struct hvsi_struct, writer.work); unsigned long flags; #ifdef DEBUG static long start_j = 0; @@ -1287,8 +1289,8 @@ static int __init hvsi_console_init(void) } hp = &hvsi_ports[hvsi_count]; - INIT_WORK(&hp->writer, hvsi_write_worker, hp); - INIT_WORK(&hp->handshaker, hvsi_handshaker, hp); + INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker); + INIT_WORK(&hp->handshaker, hvsi_handshaker); init_waitqueue_head(&hp->emptyq); init_waitqueue_head(&hp->stateq); spin_lock_init(&hp->lock); diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 54d93f0345e..c213fdbdb2b 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c @@ -84,8 +84,8 @@ static void iiSendPendingMail(i2eBordStrPtr); static void serviceOutgoingFifo(i2eBordStrPtr); // Functions defined in ip2.c as part of interrupt handling -static void do_input(void *); -static void do_status(void *); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); //*************** //* Debug Data * @@ -331,8 +331,8 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) pCh->ClosingWaitTime = 30*HZ; // Initialize task queue objects - INIT_WORK(&pCh->tqueue_input, do_input, pCh); - INIT_WORK(&pCh->tqueue_status, do_status, pCh); + INIT_WORK(&pCh->tqueue_input, do_input); + INIT_WORK(&pCh->tqueue_status, do_status); #ifdef IP2DEBUG_TRACE pCh->trace = ip2trace; @@ -1573,7 +1573,7 @@ i2StripFifo(i2eBordStrPtr pB) #ifdef USE_IQ schedule_work(&pCh->tqueue_input); #else - do_input(pCh); + do_input(&pCh->tqueue_input); #endif // Note we do not need to maintain any flow-control credits at this @@ -1810,7 +1810,7 @@ i2StripFifo(i2eBordStrPtr pB) #ifdef USE_IQ schedule_work(&pCh->tqueue_status); #else - do_status(pCh); + do_status(&pCh->tqueue_status); #endif } } diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index a3f32d46d2f..cda2459c1d6 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -189,12 +189,12 @@ static int ip2_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void set_irq(int, int); -static void ip2_interrupt_bh(i2eBordStrPtr pB); +static void ip2_interrupt_bh(struct work_struct *work); static irqreturn_t ip2_interrupt(int irq, void *dev_id); static void ip2_poll(unsigned long arg); static inline void service_all_boards(void); -static void do_input(void *p); -static void do_status(void *p); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); static void ip2_wait_until_sent(PTTY,int); @@ -918,7 +918,7 @@ ip2_init_board( int boardnum ) pCh++; } ex_exit: - INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB); + INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); return; err_release_region: @@ -1125,8 +1125,8 @@ service_all_boards(void) /******************************************************************************/ -/* Function: ip2_interrupt_bh(pB) */ -/* Parameters: pB - pointer to the board structure */ +/* Function: ip2_interrupt_bh(work) */ +/* Parameters: work - pointer to the board structure */ /* Returns: Nothing */ /* */ /* Description: */ @@ -1135,8 +1135,9 @@ service_all_boards(void) /* */ /******************************************************************************/ static void -ip2_interrupt_bh(i2eBordStrPtr pB) +ip2_interrupt_bh(struct work_struct *work) { + i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); // pB better well be set or we have a problem! We can only get // here from the IMMEDIATE queue. Here, we process the boards. // Checking pB doesn't cost much and it saves us from the sanity checkers. @@ -1245,9 +1246,9 @@ ip2_poll(unsigned long arg) ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); } -static void do_input(void *p) +static void do_input(struct work_struct *work) { - i2ChanStrPtr pCh = p; + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); unsigned long flags; ip2trace(CHANN, ITRC_INPUT, 21, 0 ); @@ -1279,9 +1280,9 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) } } -static void do_status(void *p) +static void do_status(struct work_struct *work) { - i2ChanStrPtr pCh = p; + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); int status; status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 58c955e390b..1637c1d9a4b 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -530,9 +530,9 @@ sched_again: /* Interrupt handlers */ -static void isicom_bottomhalf(void *data) +static void isicom_bottomhalf(struct work_struct *work) { - struct isi_port *port = (struct isi_port *) data; + struct isi_port *port = container_of(work, struct isi_port, bh_tqueue); struct tty_struct *tty = port->tty; if (!tty) @@ -1474,9 +1474,9 @@ static void isicom_start(struct tty_struct *tty) } /* hangup et all */ -static void do_isicom_hangup(void *data) +static void do_isicom_hangup(struct work_struct *work) { - struct isi_port *port = data; + struct isi_port *port = container_of(work, struct isi_port, hangup_tq); struct tty_struct *tty; tty = port->tty; @@ -1966,8 +1966,8 @@ static int __devinit isicom_setup(void) port->channel = channel; port->close_delay = 50 * HZ/100; port->closing_wait = 3000 * HZ/100; - INIT_WORK(&port->hangup_tq, do_isicom_hangup, port); - INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port); + INIT_WORK(&port->hangup_tq, do_isicom_hangup); + INIT_WORK(&port->bh_tqueue, isicom_bottomhalf); port->status = 0; init_waitqueue_head(&port->open_wait); init_waitqueue_head(&port->close_wait); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index ffdf9df1a67..bd9195e1795 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -663,7 +663,7 @@ static int stli_initopen(stlibrd_t *brdp, stliport_t *portp); static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp); -static void stli_dohangup(void *arg); +static void stli_dohangup(struct work_struct *); static int stli_setport(stliport_t *portp); static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); @@ -1990,9 +1990,9 @@ static void stli_start(struct tty_struct *tty) * aren't that time critical). */ -static void stli_dohangup(void *arg) +static void stli_dohangup(struct work_struct *ugly_api) { - stliport_t *portp = (stliport_t *) arg; + stliport_t *portp = container_of(ugly_api, stliport_t, tqhangup); if (portp->tty != NULL) { tty_hangup(portp->tty); } @@ -2898,7 +2898,7 @@ static int stli_initports(stlibrd_t *brdp) portp->baud_base = STL_BAUDBASE; portp->close_delay = STL_CLOSEDELAY; portp->closing_wait = 30 * HZ; - INIT_WORK(&portp->tqhangup, stli_dohangup, portp); + INIT_WORK(&portp->tqhangup, stli_dohangup); init_waitqueue_head(&portp->open_wait); init_waitqueue_head(&portp->close_wait); init_waitqueue_head(&portp->raw_wait); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 96cb1f07332..2d025a9fd14 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -222,7 +222,7 @@ static struct semaphore moxaBuffSem; /* * static functions: */ -static void do_moxa_softint(void *); +static void do_moxa_softint(struct work_struct *); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); static int moxa_write(struct tty_struct *, const unsigned char *, int); @@ -363,7 +363,7 @@ static int __init moxa_init(void) for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { ch->type = PORT_16550A; ch->port = i; - INIT_WORK(&ch->tqueue, do_moxa_softint, ch); + INIT_WORK(&ch->tqueue, do_moxa_softint); ch->tty = NULL; ch->close_delay = 5 * HZ / 10; ch->closing_wait = 30 * HZ; @@ -509,9 +509,9 @@ static void __exit moxa_exit(void) module_init(moxa_init); module_exit(moxa_exit); -static void do_moxa_softint(void *private_) +static void do_moxa_softint(struct work_struct *work) { - struct moxa_str *ch = (struct moxa_str *) private_; + struct moxa_str *ch = container_of(work, struct moxa_str, tqueue); struct tty_struct *tty; if (ch && (tty = ch->tty)) { diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 048d91142c1..5ed2486b758 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -389,7 +389,7 @@ static int mxser_init(void); /* static void mxser_poll(unsigned long); */ static int mxser_get_ISA_conf(int, struct mxser_hwconf *); static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *); -static void mxser_do_softint(void *); +static void mxser_do_softint(struct work_struct *); static int mxser_open(struct tty_struct *, struct file *); static void mxser_close(struct tty_struct *, struct file *); static int mxser_write(struct tty_struct *, const unsigned char *, int); @@ -590,7 +590,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) info->custom_divisor = hwconf->baud_base[i] * 16; info->close_delay = 5 * HZ / 10; info->closing_wait = 30 * HZ; - INIT_WORK(&info->tqueue, mxser_do_softint, info); + INIT_WORK(&info->tqueue, mxser_do_softint); info->normal_termios = mxvar_sdriver->init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); @@ -917,9 +917,10 @@ static int mxser_init(void) return 0; } -static void mxser_do_softint(void *private_) +static void mxser_do_softint(struct work_struct *work) { - struct mxser_struct *info = private_; + struct mxser_struct *info = + container_of(work, struct mxser_struct, tqueue); struct tty_struct *tty; tty = info->tty; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index f9f72500ea5..1bd12296dca 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -421,7 +421,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id); /* * Bottom half interrupt handlers */ -static void bh_handler(void* Context); +static void bh_handler(struct work_struct *work); static void bh_transmit(MGSLPC_INFO *info); static void bh_status(MGSLPC_INFO *info); @@ -547,7 +547,7 @@ static int mgslpc_probe(struct pcmcia_device *link) memset(info, 0, sizeof(MGSLPC_INFO)); info->magic = MGSLPC_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; @@ -835,9 +835,9 @@ static int bh_action(MGSLPC_INFO *info) return rc; } -static void bh_handler(void* Context) +static void bh_handler(struct work_struct *work) { - MGSLPC_INFO *info = (MGSLPC_INFO*)Context; + MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); int action; if (!info) diff --git a/drivers/char/random.c b/drivers/char/random.c index d40df30c2b1..4c6782a1ecd 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1422,9 +1422,9 @@ static struct keydata { static unsigned int ip_cnt; -static void rekey_seq_generator(void *private_); +static void rekey_seq_generator(struct work_struct *work); -static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL); +static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator); /* * Lock avoidance: @@ -1438,7 +1438,7 @@ static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL); * happen, and even if that happens only a not perfectly compliant * ISN is generated, nothing fatal. */ -static void rekey_seq_generator(void *private_) +static void rekey_seq_generator(struct work_struct *work) { struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 5ab32b38f45..722dd3e7418 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1516,9 +1516,9 @@ static void rc_start(struct tty_struct * tty) * do_rc_hangup() -> tty->hangup() -> rc_hangup() * */ -static void do_rc_hangup(void *private_) +static void do_rc_hangup(struct work_struct *ugly_api) { - struct riscom_port *port = (struct riscom_port *) private_; + struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue_hangup); struct tty_struct *tty; tty = port->tty; @@ -1567,9 +1567,9 @@ static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios } } -static void do_softint(void *private_) +static void do_softint(struct work_struct *ugly_api) { - struct riscom_port *port = (struct riscom_port *) private_; + struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue); struct tty_struct *tty; if(!(tty = port->tty)) @@ -1632,8 +1632,8 @@ static inline int rc_init_drivers(void) memset(rc_port, 0, sizeof(rc_port)); for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { rc_port[i].magic = RISCOM8_MAGIC; - INIT_WORK(&rc_port[i].tqueue, do_softint, &rc_port[i]); - INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup, &rc_port[i]); + INIT_WORK(&rc_port[i].tqueue, do_softint); + INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup); rc_port[i].close_delay = 50 * HZ/100; rc_port[i].closing_wait = 3000 * HZ/100; init_waitqueue_head(&rc_port[i].open_wait); diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 3af7f0958c5..9ba13af234b 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -706,9 +706,9 @@ cd2401_rx_interrupt(int irq, void *dev_id) * had to poll every port to see if that port needed servicing. */ static void -do_softint(void *private_) +do_softint(struct work_struct *ugly_api) { - struct cyclades_port *info = (struct cyclades_port *) private_; + struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue); struct tty_struct *tty; tty = info->tty; @@ -2273,7 +2273,7 @@ scrn[1] = '\0'; info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue, do_softint); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); /* info->session */ diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index c084149153d..fc87070f186 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -765,7 +765,7 @@ static void sonypi_setbluetoothpower(u8 state) sonypi_device.bluetooth_power = state; } -static void input_keyrelease(void *data) +static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; @@ -1412,7 +1412,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) goto err_inpdev_unregister; } - INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); + INIT_WORK(&sonypi_device.input_work, input_keyrelease); } sonypi_enable(0); diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 7e1bd9562c2..99137ab66b6 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -2261,9 +2261,10 @@ static void sx_start(struct tty_struct * tty) * do_sx_hangup() -> tty->hangup() -> sx_hangup() * */ -static void do_sx_hangup(void *private_) +static void do_sx_hangup(struct work_struct *work) { - struct specialix_port *port = (struct specialix_port *) private_; + struct specialix_port *port = + container_of(work, struct specialix_port, tqueue_hangup); struct tty_struct *tty; func_enter(); @@ -2336,9 +2337,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios } -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { - struct specialix_port *port = (struct specialix_port *) private_; + struct specialix_port *port = + container_of(work, struct specialix_port, tqueue); struct tty_struct *tty; func_enter(); @@ -2411,8 +2413,8 @@ static int sx_init_drivers(void) memset(sx_port, 0, sizeof(sx_port)); for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { sx_port[i].magic = SPECIALIX_MAGIC; - INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]); - INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]); + INIT_WORK(&sx_port[i].tqueue, do_softint); + INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup); sx_port[i].close_delay = 50 * HZ/100; sx_port[i].closing_wait = 3000 * HZ/100; init_waitqueue_head(&sx_port[i].open_wait); diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 522e88e395c..5e2de62bce7 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -500,7 +500,7 @@ static int stl_echatintr(stlbrd_t *brdp); static int stl_echmcaintr(stlbrd_t *brdp); static int stl_echpciintr(stlbrd_t *brdp); static int stl_echpci64intr(stlbrd_t *brdp); -static void stl_offintr(void *private); +static void stl_offintr(struct work_struct *); static stlbrd_t *stl_allocbrd(void); static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); @@ -2081,14 +2081,12 @@ static int stl_echpci64intr(stlbrd_t *brdp) /* * Service an off-level request for some channel. */ -static void stl_offintr(void *private) +static void stl_offintr(struct work_struct *work) { - stlport_t *portp; + stlport_t *portp = container_of(work, stlport_t, tqueue); struct tty_struct *tty; unsigned int oldsigs; - portp = private; - #ifdef DEBUG printk("stl_offintr(portp=%x)\n", (int) portp); #endif @@ -2156,7 +2154,7 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) portp->baud_base = STL_BAUDBASE; portp->close_delay = STL_CLOSEDELAY; portp->closing_wait = 30 * HZ; - INIT_WORK(&portp->tqueue, stl_offintr, portp); + INIT_WORK(&portp->tqueue, stl_offintr); init_waitqueue_head(&portp->open_wait); init_waitqueue_head(&portp->close_wait); portp->stats.brd = portp->brdnr; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 06784adcc35..147c30da81e 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -802,7 +802,7 @@ static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, u /* * Bottom half interrupt handlers */ -static void mgsl_bh_handler(void* Context); +static void mgsl_bh_handler(struct work_struct *work); static void mgsl_bh_receive(struct mgsl_struct *info); static void mgsl_bh_transmit(struct mgsl_struct *info); static void mgsl_bh_status(struct mgsl_struct *info); @@ -1071,9 +1071,10 @@ static int mgsl_bh_action(struct mgsl_struct *info) /* * Perform bottom half processing of work items queued by ISR. */ -static void mgsl_bh_handler(void* Context) +static void mgsl_bh_handler(struct work_struct *work) { - struct mgsl_struct *info = (struct mgsl_struct*)Context; + struct mgsl_struct *info = + container_of(work, struct mgsl_struct, task); int action; if (!info) @@ -4337,7 +4338,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) } else { memset(info, 0, sizeof(struct mgsl_struct)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, mgsl_bh_handler, info); + INIT_WORK(&info->task, mgsl_bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index d4334c79f8d..07f34d43dc7 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -485,7 +485,7 @@ static void enable_loopback(struct slgt_info *info); static void set_rate(struct slgt_info *info, u32 data_rate); static int bh_action(struct slgt_info *info); -static void bh_handler(void* context); +static void bh_handler(struct work_struct *work); static void bh_transmit(struct slgt_info *info); static void isr_serial(struct slgt_info *info); static void isr_rdma(struct slgt_info *info); @@ -1878,9 +1878,9 @@ static int bh_action(struct slgt_info *info) /* * perform bottom half processing */ -static void bh_handler(void* context) +static void bh_handler(struct work_struct *work) { - struct slgt_info *info = context; + struct slgt_info *info = container_of(work, struct slgt_info, task); int action; if (!info) @@ -3326,7 +3326,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev } else { memset(info, 0, sizeof(struct slgt_info)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->raw_rx_size = DMABUFSIZE; info->close_delay = 5*HZ/10; @@ -4799,6 +4799,6 @@ static void rx_timeout(unsigned long context) spin_lock_irqsave(&info->lock, flags); info->pending_bh |= BH_RECEIVE; spin_unlock_irqrestore(&info->lock, flags); - bh_handler(info); + bh_handler(&info->task); } diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 3e932b68137..13a57245cf2 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -602,7 +602,7 @@ static void enable_loopback(SLMP_INFO *info, int enable); static void set_rate(SLMP_INFO *info, u32 data_rate); static int bh_action(SLMP_INFO *info); -static void bh_handler(void* Context); +static void bh_handler(struct work_struct *work); static void bh_receive(SLMP_INFO *info); static void bh_transmit(SLMP_INFO *info); static void bh_status(SLMP_INFO *info); @@ -2063,9 +2063,9 @@ int bh_action(SLMP_INFO *info) /* Perform bottom half processing of work items queued by ISR. */ -void bh_handler(void* Context) +void bh_handler(struct work_struct *work) { - SLMP_INFO *info = (SLMP_INFO*)Context; + SLMP_INFO *info = container_of(work, SLMP_INFO, task); int action; if (!info) @@ -3805,7 +3805,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) } else { memset(info, 0, sizeof(SLMP_INFO)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 5f49280779f..c64f5bcff94 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -219,13 +219,13 @@ static struct sysrq_key_op sysrq_term_op = { .enable_mask = SYSRQ_ENABLE_SIGNAL, }; -static void moom_callback(void *ignored) +static void moom_callback(struct work_struct *ignored) { out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); } -static DECLARE_WORK(moom_work, moom_callback, NULL); +static DECLARE_WORK(moom_work, moom_callback); static void sysrq_handle_moom(int key, struct tty_struct *tty) { diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 6e1329d404d..774fa861169 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -325,9 +325,9 @@ static void user_reader_timeout(unsigned long ptr) schedule_work(&chip->work); } -static void timeout_work(void *ptr) +static void timeout_work(struct work_struct *work) { - struct tpm_chip *chip = ptr; + struct tpm_chip *chip = container_of(work, struct tpm_chip, work); down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); @@ -1105,7 +1105,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend init_MUTEX(&chip->tpm_mutex); INIT_LIST_HEAD(&chip->list); - INIT_WORK(&chip->work, timeout_work, chip); + INIT_WORK(&chip->work, timeout_work); init_timer(&chip->user_read_timer); chip->user_read_timer.function = user_reader_timeout; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 50dc49205a2..b3cfc8bc613 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1254,7 +1254,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); /** * do_tty_hangup - actual handler for hangup events - * @data: tty device + * @work: tty device * * This can be called by the "eventd" kernel thread. That is process * synchronous but doesn't hold any locks, so we need to make sure we @@ -1274,9 +1274,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * tasklist_lock to walk task list for hangup event * */ -static void do_tty_hangup(void *data) +static void do_tty_hangup(struct work_struct *work) { - struct tty_struct *tty = (struct tty_struct *) data; + struct tty_struct *tty = + container_of(work, struct tty_struct, hangup_work); struct file * cons_filp = NULL; struct file *filp, *f = NULL; struct task_struct *p; @@ -1433,7 +1434,7 @@ void tty_vhangup(struct tty_struct * tty) printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); #endif - do_tty_hangup((void *) tty); + do_tty_hangup(&tty->hangup_work); } EXPORT_SYMBOL(tty_vhangup); @@ -3304,12 +3305,13 @@ int tty_ioctl(struct inode * inode, struct file * file, * Nasty bug: do_SAK is being called in interrupt context. This can * deadlock. We punt it up to process context. AKPM - 16Mar2001 */ -static void __do_SAK(void *arg) +static void __do_SAK(struct work_struct *work) { + struct tty_struct *tty = + container_of(work, struct tty_struct, SAK_work); #ifdef TTY_SOFT_SAK tty_hangup(tty); #else - struct tty_struct *tty = arg; struct task_struct *g, *p; int session; int i; @@ -3388,7 +3390,7 @@ void do_SAK(struct tty_struct *tty) { if (!tty) return; - PREPARE_WORK(&tty->SAK_work, __do_SAK, tty); + PREPARE_WORK(&tty->SAK_work, __do_SAK); schedule_work(&tty->SAK_work); } @@ -3396,7 +3398,7 @@ EXPORT_SYMBOL(do_SAK); /** * flush_to_ldisc - * @private_: tty structure passed from work queue. + * @work: tty structure passed from work queue. * * This routine is called out of the software interrupt to flush data * from the buffer chain to the line discipline. @@ -3406,9 +3408,10 @@ EXPORT_SYMBOL(do_SAK); * receive_buf method is single threaded for each tty instance. */ -static void flush_to_ldisc(void *private_) +static void flush_to_ldisc(struct work_struct *work) { - struct tty_struct *tty = (struct tty_struct *) private_; + struct tty_struct *tty = + container_of(work, struct tty_struct, buf.work.work); unsigned long flags; struct tty_ldisc *disc; struct tty_buffer *tbuf, *head; @@ -3553,7 +3556,7 @@ void tty_flip_buffer_push(struct tty_struct *tty) spin_unlock_irqrestore(&tty->buf.lock, flags); if (tty->low_latency) - flush_to_ldisc((void *) tty); + flush_to_ldisc(&tty->buf.work.work); else schedule_delayed_work(&tty->buf.work, 1); } @@ -3580,17 +3583,17 @@ static void initialize_tty_struct(struct tty_struct *tty) tty->overrun_time = jiffies; tty->buf.head = tty->buf.tail = NULL; tty_buffer_init(tty); - INIT_WORK(&tty->buf.work, flush_to_ldisc, tty); + INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); init_MUTEX(&tty->buf.pty_sem); mutex_init(&tty->termios_mutex); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); - INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); + INIT_WORK(&tty->hangup_work, do_tty_hangup); mutex_init(&tty->atomic_read_lock); mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->read_lock); INIT_LIST_HEAD(&tty->tty_files); - INIT_WORK(&tty->SAK_work, NULL, NULL); + INIT_WORK(&tty->SAK_work, NULL); } /* diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 87587b4385a..75ff0286e1a 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -155,7 +155,7 @@ static void con_flush_chars(struct tty_struct *tty); static void set_vesa_blanking(char __user *p); static void set_cursor(struct vc_data *vc); static void hide_cursor(struct vc_data *vc); -static void console_callback(void *ignored); +static void console_callback(struct work_struct *ignored); static void blank_screen_t(unsigned long dummy); static void set_palette(struct vc_data *vc); @@ -174,7 +174,7 @@ static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ static int blankinterval = 10*60*HZ; static int vesa_off_interval; -static DECLARE_WORK(console_work, console_callback, NULL); +static DECLARE_WORK(console_work, console_callback); /* * fg_console is the current virtual console, @@ -2154,7 +2154,7 @@ out: * with other console code and prevention of re-entrancy is * ensured with console_sem. */ -static void console_callback(void *ignored) +static void console_callback(struct work_struct *ignored) { acquire_console_sem(); diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 05f8ce2cfb4..b418b16e910 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -31,9 +31,11 @@ #include <linux/connector.h> #include <linux/delay.h> -void cn_queue_wrapper(void *data) +void cn_queue_wrapper(struct work_struct *work) { - struct cn_callback_data *d = data; + struct cn_callback_entry *cbq = + container_of(work, struct cn_callback_entry, work.work); + struct cn_callback_data *d = &cbq->data; d->callback(d->callback_priv); @@ -57,7 +59,7 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc memcpy(&cbq->id.id, id, sizeof(struct cb_id)); cbq->data.callback = callback; - INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data); + INIT_DELAYED_WORK(&cbq->work, &cn_queue_wrapper); return cbq; } diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index b49bacfd8de..5e7cd45d10e 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -135,40 +135,39 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) { - if (likely(!test_bit(0, &__cbq->work.pending) && + if (likely(!test_bit(WORK_STRUCT_PENDING, + &__cbq->work.work.management) && __cbq->data.ddata == NULL)) { __cbq->data.callback_priv = msg; __cbq->data.ddata = data; __cbq->data.destruct_data = destruct_data; - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; } else { - struct work_struct *w; struct cn_callback_data *d; - w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC); - if (w) { - d = (struct cn_callback_data *)(w+1); - + __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); + if (__cbq) { + d = &__cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = w; + d->free = __cbq; - INIT_LIST_HEAD(&w->entry); - w->pending = 0; - w->func = &cn_queue_wrapper; - w->data = d; - init_timer(&w->timer); + INIT_DELAYED_WORK(&__cbq->work, + &cn_queue_wrapper); - if (queue_work(dev->cbdev->cn_queue, w)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; else { - kfree(w); + kfree(__cbq); err = -EINVAL; } } else diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index dd0c2623e27..7a7c6e6dfe4 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); -static void handle_update(void *data); +static void handle_update(struct work_struct *work); /** * Two notifier lists: the "policy" list is involved in the @@ -665,7 +665,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) mutex_init(&policy->lock); mutex_lock(&policy->lock); init_completion(&policy->kobj_unregister); - INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); + INIT_WORK(&policy->update, handle_update); /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU @@ -895,9 +895,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) } -static void handle_update(void *data) +static void handle_update(struct work_struct *work) { - unsigned int cpu = (unsigned int)(long)data; + struct cpufreq_policy *policy = + container_of(work, struct cpufreq_policy, update); + unsigned int cpu = policy->cpu; dprintk("handle_update for cpu %u called\n", cpu); cpufreq_update_policy(cpu); } diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index c4c578defab..5ef5ede5b88 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -59,7 +59,7 @@ static unsigned int def_sampling_rate; #define MAX_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -static void do_dbs_timer(void *data); +static void do_dbs_timer(struct work_struct *work); struct cpu_dbs_info_s { struct cpufreq_policy *cur_policy; @@ -82,7 +82,7 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * is recursive for the same process. -Venki */ static DEFINE_MUTEX (dbs_mutex); -static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); +static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); struct dbs_tuners { unsigned int sampling_rate; @@ -420,7 +420,7 @@ static void dbs_check_cpu(int cpu) } } -static void do_dbs_timer(void *data) +static void do_dbs_timer(struct work_struct *work) { int i; lock_cpu_hotplug(); @@ -435,7 +435,6 @@ static void do_dbs_timer(void *data) static inline void dbs_timer_init(void) { - INIT_WORK(&dbs_work, do_dbs_timer, NULL); schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); return; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bf8aa45d4f0..e1cc5113c2a 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -47,13 +47,17 @@ static unsigned int def_sampling_rate; #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -static void do_dbs_timer(void *data); +static void do_dbs_timer(struct work_struct *work); + +/* Sampling types */ +enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; struct cpu_dbs_info_s { cputime64_t prev_cpu_idle; cputime64_t prev_cpu_wall; struct cpufreq_policy *cur_policy; - struct work_struct work; + struct delayed_work work; + enum dbs_sample sample_type; unsigned int enable; struct cpufreq_frequency_table *freq_table; unsigned int freq_lo; @@ -407,30 +411,31 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) } } -/* Sampling types */ -enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; - -static void do_dbs_timer(void *data) +static void do_dbs_timer(struct work_struct *work) { unsigned int cpu = smp_processor_id(); struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); + enum dbs_sample sample_type = dbs_info->sample_type; /* We want all CPUs to do sampling nearly on same jiffy */ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + /* Permit rescheduling of this work item */ + work_release(work); + delay -= jiffies % delay; if (!dbs_info->enable) return; /* Common NORMAL_SAMPLE setup */ - INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE); + dbs_info->sample_type = DBS_NORMAL_SAMPLE; if (!dbs_tuners_ins.powersave_bias || - (unsigned long) data == DBS_NORMAL_SAMPLE) { + sample_type == DBS_NORMAL_SAMPLE) { lock_cpu_hotplug(); dbs_check_cpu(dbs_info); unlock_cpu_hotplug(); if (dbs_info->freq_lo) { /* Setup timer for SUB_SAMPLE */ - INIT_WORK(&dbs_info->work, do_dbs_timer, - (void *)DBS_SUB_SAMPLE); + dbs_info->sample_type = DBS_SUB_SAMPLE; delay = dbs_info->freq_hi_jiffies; } } else { @@ -449,7 +454,8 @@ static inline void dbs_timer_init(unsigned int cpu) delay -= jiffies % delay; ondemand_powersave_bias_init(); - INIT_WORK(&dbs_info->work, do_dbs_timer, NULL); + INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer); + dbs_info->sample_type = DBS_NORMAL_SAMPLE; queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); } diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c index 4630f1969a0..15edf40828b 100644 --- a/drivers/i2c/chips/ds1374.c +++ b/drivers/i2c/chips/ds1374.c @@ -140,12 +140,14 @@ ulong ds1374_get_rtc_time(void) return t1; } -static void ds1374_set_work(void *arg) +static ulong new_time; + +static void ds1374_set_work(struct work_struct *work) { ulong t1, t2; int limit = 10; /* arbitrary retry limit */ - t1 = *(ulong *) arg; + t1 = new_time; mutex_lock(&ds1374_mutex); @@ -167,11 +169,9 @@ static void ds1374_set_work(void *arg) "can't confirm time set from rtc chip\n"); } -static ulong new_time; - static struct workqueue_struct *ds1374_workqueue; -static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time); +static DECLARE_WORK(ds1374_work, ds1374_set_work); int ds1374_set_rtc_time(ulong nowtime) { @@ -180,7 +180,7 @@ int ds1374_set_rtc_time(ulong nowtime) if (in_interrupt()) queue_work(ds1374_workqueue, &ds1374_work); else - ds1374_set_work(&new_time); + ds1374_set_work(NULL); return 0; } diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index 2dd0a34d947..420377c8642 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -215,8 +215,15 @@ m41t00_set(void *arg) } static ulong new_time; +/* well, isn't this API just _lovely_? */ +static void +m41t00_barf(struct work_struct *unusable) +{ + m41t00_set(&new_time); +} + static struct workqueue_struct *m41t00_wq; -static DECLARE_WORK(m41t00_work, m41t00_set, &new_time); +static DECLARE_WORK(m41t00_work, m41t00_barf); int m41t00_set_rtc_time(ulong nowtime) diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index d90a3a1898c..8f4378a1631 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -31,9 +31,10 @@ #include "config_roms.h" -static void delayed_reset_bus(void * __reset_info) +static void delayed_reset_bus(struct work_struct *work) { - struct hpsb_host *host = (struct hpsb_host*)__reset_info; + struct hpsb_host *host = + container_of(work, struct hpsb_host, delayed_reset.work); int generation = host->csr.generation + 1; /* The generation field rolls over to 2 rather than 0 per IEEE @@ -145,7 +146,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, atomic_set(&h->generation, 0); - INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); + INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus); init_timer(&h->timeout); h->timeout.data = (unsigned long) h; @@ -234,7 +235,7 @@ int hpsb_update_config_rom_image(struct hpsb_host *host) * Config ROM in the near future. */ reset_delay = HZ; - PREPARE_WORK(&host->delayed_reset, delayed_reset_bus, host); + PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus); schedule_delayed_work(&host->delayed_reset, reset_delay); return 0; diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index bc6dbfadb89..d553e38c954 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -62,7 +62,7 @@ struct hpsb_host { struct class_device class_dev; int update_config_rom; - struct work_struct delayed_reset; + struct delayed_work delayed_reset; unsigned int config_roms; struct list_head addr_space; diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 6986ac18828..cd156d4e779 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -493,20 +493,25 @@ static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id, scsi_unblock_requests(scsi_id->scsi_host); } -static void sbp2util_write_orb_pointer(void *p) +static void sbp2util_write_orb_pointer(struct work_struct *work) { + struct scsi_id_instance_data *scsi_id = + container_of(work, struct scsi_id_instance_data, + protocol_work.work); quadlet_t data[2]; - data[0] = ORB_SET_NODE_ID( - ((struct scsi_id_instance_data *)p)->hi->host->node_id); - data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma; + data[0] = ORB_SET_NODE_ID(scsi_id->hi->host->node_id); + data[1] = scsi_id->last_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8); + sbp2util_notify_fetch_agent(scsi_id, SBP2_ORB_POINTER_OFFSET, data, 8); } -static void sbp2util_write_doorbell(void *p) +static void sbp2util_write_doorbell(struct work_struct *work) { - sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4); + struct scsi_id_instance_data *scsi_id = + container_of(work, struct scsi_id_instance_data, + protocol_work.work); + sbp2util_notify_fetch_agent(scsi_id, SBP2_DOORBELL_OFFSET, NULL, 4); } /* @@ -843,7 +848,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud INIT_LIST_HEAD(&scsi_id->scsi_list); spin_lock_init(&scsi_id->sbp2_command_orb_lock); atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING); - INIT_WORK(&scsi_id->protocol_work, NULL, NULL); + INIT_DELAYED_WORK(&scsi_id->protocol_work, NULL); ud->device.driver_data = scsi_id; @@ -2047,11 +2052,10 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, * We do not accept new commands until the job is over. */ scsi_block_requests(scsi_id->scsi_host); - PREPARE_WORK(&scsi_id->protocol_work, + PREPARE_DELAYED_WORK(&scsi_id->protocol_work, last_orb ? sbp2util_write_doorbell: - sbp2util_write_orb_pointer, - scsi_id); - schedule_work(&scsi_id->protocol_work); + sbp2util_write_orb_pointer); + schedule_delayed_work(&scsi_id->protocol_work, 0); } } diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index abbe48e646c..1b16d6b9cf1 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -348,7 +348,7 @@ struct scsi_id_instance_data { unsigned workarounds; atomic_t state; - struct work_struct protocol_work; + struct delayed_work protocol_work; }; /* For use in scsi_id_instance_data.state */ diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 7767a11b689..af939796750 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -55,11 +55,11 @@ struct addr_req { int status; }; -static void process_req(void *data); +static void process_req(struct work_struct *work); static DEFINE_MUTEX(lock); static LIST_HEAD(req_list); -static DECLARE_WORK(work, process_req, NULL); +static DECLARE_DELAYED_WORK(work, process_req); static struct workqueue_struct *addr_wq; void rdma_addr_register_client(struct rdma_addr_client *client) @@ -215,7 +215,7 @@ out: return ret; } -static void process_req(void *data) +static void process_req(struct work_struct *work) { struct addr_req *req, *temp_req; struct sockaddr_in *src_in, *dst_in; diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 20e9f64e67a..98272fbbfb3 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -285,9 +285,10 @@ err: kfree(tprops); } -static void ib_cache_task(void *work_ptr) +static void ib_cache_task(struct work_struct *_work) { - struct ib_update_work *work = work_ptr; + struct ib_update_work *work = + container_of(_work, struct ib_update_work, work); ib_cache_update(work->device, work->port_num); kfree(work); @@ -306,7 +307,7 @@ static void ib_cache_event(struct ib_event_handler *handler, event->event == IB_EVENT_CLIENT_REREGISTER) { work = kmalloc(sizeof *work, GFP_ATOMIC); if (work) { - INIT_WORK(&work->work, ib_cache_task, work); + INIT_WORK(&work->work, ib_cache_task); work->device = event->device; work->port_num = event->element.port_num; schedule_work(&work->work); diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index e5dc4530808..79c937bf696 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -101,7 +101,7 @@ struct cm_av { }; struct cm_work { - struct work_struct work; + struct delayed_work work; struct list_head list; struct cm_port *port; struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */ @@ -161,7 +161,7 @@ struct cm_id_private { atomic_t work_count; }; -static void cm_work_handler(void *data); +static void cm_work_handler(struct work_struct *work); static inline void cm_deref_id(struct cm_id_private *cm_id_priv) { @@ -668,8 +668,7 @@ static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id) return ERR_PTR(-ENOMEM); timewait_info->work.local_id = local_id; - INIT_WORK(&timewait_info->work.work, cm_work_handler, - &timewait_info->work); + INIT_DELAYED_WORK(&timewait_info->work.work, cm_work_handler); timewait_info->work.cm_event.event = IB_CM_TIMEWAIT_EXIT; return timewait_info; } @@ -2995,9 +2994,9 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent, } } -static void cm_work_handler(void *data) +static void cm_work_handler(struct work_struct *_work) { - struct cm_work *work = data; + struct cm_work *work = container_of(_work, struct cm_work, work.work); int ret; switch (work->cm_event.event) { @@ -3087,12 +3086,12 @@ static int cm_establish(struct ib_cm_id *cm_id) * we need to find the cm_id once we're in the context of the * worker thread, rather than holding a reference on it. */ - INIT_WORK(&work->work, cm_work_handler, work); + INIT_DELAYED_WORK(&work->work, cm_work_handler); work->local_id = cm_id->local_id; work->remote_id = cm_id->remote_id; work->mad_recv_wc = NULL; work->cm_event.event = IB_CM_USER_ESTABLISHED; - queue_work(cm.wq, &work->work); + queue_delayed_work(cm.wq, &work->work, 0); out: return ret; } @@ -3191,11 +3190,11 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, return; } - INIT_WORK(&work->work, cm_work_handler, work); + INIT_DELAYED_WORK(&work->work, cm_work_handler); work->cm_event.event = event; work->mad_recv_wc = mad_recv_wc; work->port = (struct cm_port *)mad_agent->context; - queue_work(cm.wq, &work->work); + queue_delayed_work(cm.wq, &work->work, 0); } static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index cf48f269743..985a6b564d8 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1340,9 +1340,9 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, return (id_priv->query_id < 0) ? id_priv->query_id : 0; } -static void cma_work_handler(void *data) +static void cma_work_handler(struct work_struct *_work) { - struct cma_work *work = data; + struct cma_work *work = container_of(_work, struct cma_work, work); struct rdma_id_private *id_priv = work->id; int destroy = 0; @@ -1373,7 +1373,7 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) return -ENOMEM; work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ROUTE_QUERY; work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; @@ -1430,7 +1430,7 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms) return -ENOMEM; work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ROUTE_QUERY; work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; @@ -1583,7 +1583,7 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) } work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ADDR_QUERY; work->new_state = CMA_ADDR_RESOLVED; work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index cf797d7aea0..1039ad57d53 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -828,9 +828,9 @@ static int process_event(struct iwcm_id_private *cm_id_priv, * thread asleep on the destroy_comp list vs. an object destroyed * here synchronously when the last reference is removed. */ -static void cm_work_handler(void *arg) +static void cm_work_handler(struct work_struct *_work) { - struct iwcm_work *work = arg; + struct iwcm_work *work = container_of(_work, struct iwcm_work, work); struct iw_cm_event levent; struct iwcm_id_private *cm_id_priv = work->cm_id; unsigned long flags; @@ -900,7 +900,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id, goto out; } - INIT_WORK(&work->work, cm_work_handler, work); + INIT_WORK(&work->work, cm_work_handler); work->cm_id = cm_id_priv; work->event = *iw_event; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 3f9c16232c4..15f38d94b3a 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -65,8 +65,8 @@ static struct ib_mad_agent_private *find_mad_agent( static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, struct ib_mad_private *mad); static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv); -static void timeout_sends(void *data); -static void local_completions(void *data); +static void timeout_sends(struct work_struct *work); +static void local_completions(struct work_struct *work); static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req, struct ib_mad_agent_private *agent_priv, u8 mgmt_class); @@ -356,10 +356,9 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, INIT_LIST_HEAD(&mad_agent_priv->wait_list); INIT_LIST_HEAD(&mad_agent_priv->done_list); INIT_LIST_HEAD(&mad_agent_priv->rmpp_list); - INIT_WORK(&mad_agent_priv->timed_work, timeout_sends, mad_agent_priv); + INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends); INIT_LIST_HEAD(&mad_agent_priv->local_list); - INIT_WORK(&mad_agent_priv->local_work, local_completions, - mad_agent_priv); + INIT_WORK(&mad_agent_priv->local_work, local_completions); atomic_set(&mad_agent_priv->refcount, 1); init_completion(&mad_agent_priv->comp); @@ -2198,12 +2197,12 @@ static void mad_error_handler(struct ib_mad_port_private *port_priv, /* * IB MAD completion callback */ -static void ib_mad_completion_handler(void *data) +static void ib_mad_completion_handler(struct work_struct *work) { struct ib_mad_port_private *port_priv; struct ib_wc wc; - port_priv = (struct ib_mad_port_private *)data; + port_priv = container_of(work, struct ib_mad_port_private, work); ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP); while (ib_poll_cq(port_priv->cq, 1, &wc) == 1) { @@ -2324,7 +2323,7 @@ void ib_cancel_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_cancel_mad); -static void local_completions(void *data) +static void local_completions(struct work_struct *work) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_local_private *local; @@ -2334,7 +2333,8 @@ static void local_completions(void *data) struct ib_wc wc; struct ib_mad_send_wc mad_send_wc; - mad_agent_priv = (struct ib_mad_agent_private *)data; + mad_agent_priv = + container_of(work, struct ib_mad_agent_private, local_work); spin_lock_irqsave(&mad_agent_priv->lock, flags); while (!list_empty(&mad_agent_priv->local_list)) { @@ -2434,14 +2434,15 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr) return ret; } -static void timeout_sends(void *data) +static void timeout_sends(struct work_struct *work) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; unsigned long flags, delay; - mad_agent_priv = (struct ib_mad_agent_private *)data; + mad_agent_priv = container_of(work, struct ib_mad_agent_private, + timed_work.work); mad_send_wc.vendor_err = 0; spin_lock_irqsave(&mad_agent_priv->lock, flags); @@ -2799,7 +2800,7 @@ static int ib_mad_port_open(struct ib_device *device, ret = -ENOMEM; goto error8; } - INIT_WORK(&port_priv->work, ib_mad_completion_handler, port_priv); + INIT_WORK(&port_priv->work, ib_mad_completion_handler); spin_lock_irqsave(&ib_mad_port_list_lock, flags); list_add_tail(&port_priv->port_list, &ib_mad_port_list); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index d06b59083f6..d5548e73e06 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -102,7 +102,7 @@ struct ib_mad_agent_private { struct list_head send_list; struct list_head wait_list; struct list_head done_list; - struct work_struct timed_work; + struct delayed_work timed_work; unsigned long timeout; struct list_head local_list; struct work_struct local_work; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 1ef79d015a1..3663fd7022b 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -45,8 +45,8 @@ enum rmpp_state { struct mad_rmpp_recv { struct ib_mad_agent_private *agent; struct list_head list; - struct work_struct timeout_work; - struct work_struct cleanup_work; + struct delayed_work timeout_work; + struct delayed_work cleanup_work; struct completion comp; enum rmpp_state state; spinlock_t lock; @@ -233,9 +233,10 @@ static void nack_recv(struct ib_mad_agent_private *agent, } } -static void recv_timeout_handler(void *data) +static void recv_timeout_handler(struct work_struct *work) { - struct mad_rmpp_recv *rmpp_recv = data; + struct mad_rmpp_recv *rmpp_recv = + container_of(work, struct mad_rmpp_recv, timeout_work.work); struct ib_mad_recv_wc *rmpp_wc; unsigned long flags; @@ -254,9 +255,10 @@ static void recv_timeout_handler(void *data) ib_free_recv_mad(rmpp_wc); } -static void recv_cleanup_handler(void *data) +static void recv_cleanup_handler(struct work_struct *work) { - struct mad_rmpp_recv *rmpp_recv = data; + struct mad_rmpp_recv *rmpp_recv = + container_of(work, struct mad_rmpp_recv, cleanup_work.work); unsigned long flags; spin_lock_irqsave(&rmpp_recv->agent->lock, flags); @@ -285,8 +287,8 @@ create_rmpp_recv(struct ib_mad_agent_private *agent, rmpp_recv->agent = agent; init_completion(&rmpp_recv->comp); - INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv); - INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv); + INIT_DELAYED_WORK(&rmpp_recv->timeout_work, recv_timeout_handler); + INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler); spin_lock_init(&rmpp_recv->lock); rmpp_recv->state = RMPP_STATE_ACTIVE; atomic_set(&rmpp_recv->refcount, 1); diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 1706d3c7e95..e45afba7534 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -360,9 +360,10 @@ static void free_sm_ah(struct kref *kref) kfree(sm_ah); } -static void update_sm_ah(void *port_ptr) +static void update_sm_ah(struct work_struct *work) { - struct ib_sa_port *port = port_ptr; + struct ib_sa_port *port = + container_of(work, struct ib_sa_port, update_task); struct ib_sa_sm_ah *new_ah, *old_ah; struct ib_port_attr port_attr; struct ib_ah_attr ah_attr; @@ -992,8 +993,7 @@ static void ib_sa_add_one(struct ib_device *device) if (IS_ERR(sa_dev->port[i].agent)) goto err; - INIT_WORK(&sa_dev->port[i].update_task, - update_sm_ah, &sa_dev->port[i]); + INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); } ib_set_client_data(device, &sa_client, sa_dev); @@ -1010,7 +1010,7 @@ static void ib_sa_add_one(struct ib_device *device) goto err; for (i = 0; i <= e - s; ++i) - update_sm_ah(&sa_dev->port[i]); + update_sm_ah(&sa_dev->port[i].update_task); return; diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c index efe147dbeb4..db12cc0841d 100644 --- a/drivers/infiniband/core/uverbs_mem.c +++ b/drivers/infiniband/core/uverbs_mem.c @@ -179,9 +179,10 @@ void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) up_write(¤t->mm->mmap_sem); } -static void ib_umem_account(void *work_ptr) +static void ib_umem_account(struct work_struct *_work) { - struct ib_umem_account_work *work = work_ptr; + struct ib_umem_account_work *work = + container_of(_work, struct ib_umem_account_work, work); down_write(&work->mm->mmap_sem); work->mm->locked_vm -= work->diff; @@ -216,7 +217,7 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem) return; } - INIT_WORK(&work->work, ib_umem_account, work); + INIT_WORK(&work->work, ib_umem_account); work->mm = mm; work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c index 413754b1d8a..8536aeb96af 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c @@ -214,9 +214,10 @@ struct ipath_user_pages_work { unsigned long num_pages; }; -static void user_pages_account(void *ptr) +static void user_pages_account(struct work_struct *_work) { - struct ipath_user_pages_work *work = ptr; + struct ipath_user_pages_work *work = + container_of(_work, struct ipath_user_pages_work, work); down_write(&work->mm->mmap_sem); work->mm->locked_vm -= work->num_pages; @@ -242,7 +243,7 @@ void ipath_release_user_pages_on_close(struct page **p, size_t num_pages) goto bail; - INIT_WORK(&work->work, user_pages_account, work); + INIT_WORK(&work->work, user_pages_account); work->mm = mm; work->num_pages = num_pages; diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index cd044ea2dfa..e948158a28d 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c @@ -57,7 +57,7 @@ static int catas_reset_disable; module_param_named(catas_reset_disable, catas_reset_disable, int, 0644); MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero"); -static void catas_reset(void *work_ptr) +static void catas_reset(struct work_struct *work) { struct mthca_dev *dev, *tmpdev; LIST_HEAD(tlist); @@ -203,7 +203,7 @@ void mthca_stop_catas_poll(struct mthca_dev *dev) int __init mthca_catas_init(void) { - INIT_WORK(&catas_work, catas_reset, NULL); + INIT_WORK(&catas_work, catas_reset); catas_wq = create_singlethread_workqueue("mthca_catas"); if (!catas_wq) diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index f2b61851a49..99547996aba 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -136,11 +136,11 @@ struct ipoib_dev_priv { struct list_head multicast_list; struct rb_root multicast_tree; - struct work_struct pkey_task; - struct work_struct mcast_task; + struct delayed_work pkey_task; + struct delayed_work mcast_task; struct work_struct flush_task; struct work_struct restart_task; - struct work_struct ah_reap_task; + struct delayed_work ah_reap_task; struct ib_device *ca; u8 port; @@ -254,13 +254,13 @@ int ipoib_add_pkey_attr(struct net_device *dev); void ipoib_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_ah *address, u32 qpn); -void ipoib_reap_ah(void *dev_ptr); +void ipoib_reap_ah(struct work_struct *work); void ipoib_flush_paths(struct net_device *dev); struct ipoib_dev_priv *ipoib_intf_alloc(const char *format); int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port); -void ipoib_ib_dev_flush(void *dev); +void ipoib_ib_dev_flush(struct work_struct *work); void ipoib_ib_dev_cleanup(struct net_device *dev); int ipoib_ib_dev_open(struct net_device *dev); @@ -271,10 +271,10 @@ int ipoib_ib_dev_stop(struct net_device *dev); int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); void ipoib_dev_cleanup(struct net_device *dev); -void ipoib_mcast_join_task(void *dev_ptr); +void ipoib_mcast_join_task(struct work_struct *work); void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); -void ipoib_mcast_restart_task(void *dev_ptr); +void ipoib_mcast_restart_task(struct work_struct *work); int ipoib_mcast_start_thread(struct net_device *dev); int ipoib_mcast_stop_thread(struct net_device *dev, int flush); @@ -312,7 +312,7 @@ void ipoib_event(struct ib_event_handler *handler, int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey); int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey); -void ipoib_pkey_poll(void *dev); +void ipoib_pkey_poll(struct work_struct *work); int ipoib_pkey_dev_delay_open(struct net_device *dev); #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 8bf5e9ec7c9..f10fba5d326 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -400,10 +400,11 @@ static void __ipoib_reap_ah(struct net_device *dev) spin_unlock_irq(&priv->tx_lock); } -void ipoib_reap_ah(void *dev_ptr) +void ipoib_reap_ah(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, ah_reap_task.work); + struct net_device *dev = priv->dev; __ipoib_reap_ah(dev); @@ -613,10 +614,11 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) return 0; } -void ipoib_ib_dev_flush(void *_dev) +void ipoib_ib_dev_flush(struct work_struct *work) { - struct net_device *dev = (struct net_device *)_dev; - struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv; + struct ipoib_dev_priv *cpriv, *priv = + container_of(work, struct ipoib_dev_priv, flush_task); + struct net_device *dev = priv->dev; if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) { ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); @@ -638,14 +640,14 @@ void ipoib_ib_dev_flush(void *_dev) */ if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { ipoib_ib_dev_up(dev); - ipoib_mcast_restart_task(dev); + ipoib_mcast_restart_task(&priv->restart_task); } mutex_lock(&priv->vlan_mutex); /* Flush any child interfaces too */ list_for_each_entry(cpriv, &priv->child_intfs, list) - ipoib_ib_dev_flush(cpriv->dev); + ipoib_ib_dev_flush(&cpriv->flush_task); mutex_unlock(&priv->vlan_mutex); } @@ -672,10 +674,11 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) * change async notification is available. */ -void ipoib_pkey_poll(void *dev_ptr) +void ipoib_pkey_poll(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, pkey_task.work); + struct net_device *dev = priv->dev; ipoib_pkey_dev_check_presence(dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 5ba3154320b..c0928024372 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -940,11 +940,11 @@ static void ipoib_setup(struct net_device *dev) INIT_LIST_HEAD(&priv->dead_ahs); INIT_LIST_HEAD(&priv->multicast_list); - INIT_WORK(&priv->pkey_task, ipoib_pkey_poll, priv->dev); - INIT_WORK(&priv->mcast_task, ipoib_mcast_join_task, priv->dev); - INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush, priv->dev); - INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task, priv->dev); - INIT_WORK(&priv->ah_reap_task, ipoib_reap_ah, priv->dev); + INIT_DELAYED_WORK(&priv->pkey_task, ipoib_pkey_poll); + INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); + INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush); + INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); + INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); } struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index d282d65e3ee..b04b72ca32e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -399,7 +399,8 @@ static void ipoib_mcast_join_complete(int status, mcast->backoff = 1; mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, + &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); complete(&mcast->done); return; @@ -435,7 +436,8 @@ static void ipoib_mcast_join_complete(int status, if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { if (status == -ETIMEDOUT) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, &priv->mcast_task, + 0); else queue_delayed_work(ipoib_workqueue, &priv->mcast_task, mcast->backoff * HZ); @@ -517,10 +519,11 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, mcast->query_id = ret; } -void ipoib_mcast_join_task(void *dev_ptr) +void ipoib_mcast_join_task(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, mcast_task.work); + struct net_device *dev = priv->dev; if (!test_bit(IPOIB_MCAST_RUN, &priv->flags)) return; @@ -610,7 +613,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) mutex_lock(&mcast_mutex); if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); spin_lock_irq(&priv->lock); @@ -818,10 +821,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } } -void ipoib_mcast_restart_task(void *dev_ptr) +void ipoib_mcast_restart_task(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, restart_task); + struct net_device *dev = priv->dev; struct dev_mc_list *mclist; struct ipoib_mcast *mcast, *tmcast; LIST_HEAD(remove_list); diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 18a00003499..693b7700289 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -48,7 +48,7 @@ static void iser_cq_tasklet_fn(unsigned long data); static void iser_cq_callback(struct ib_cq *cq, void *cq_context); -static void iser_comp_error_worker(void *data); +static void iser_comp_error_worker(struct work_struct *work); static void iser_cq_event_callback(struct ib_event *cause, void *context) { @@ -480,8 +480,7 @@ int iser_conn_init(struct iser_conn **ibconn) init_waitqueue_head(&ib_conn->wait); atomic_set(&ib_conn->post_recv_buf_count, 0); atomic_set(&ib_conn->post_send_buf_count, 0); - INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker, - ib_conn); + INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker); INIT_LIST_HEAD(&ib_conn->conn_list); spin_lock_init(&ib_conn->lock); @@ -754,9 +753,10 @@ int iser_post_send(struct iser_desc *tx_desc) return ret_val; } -static void iser_comp_error_worker(void *data) +static void iser_comp_error_worker(struct work_struct *work) { - struct iser_conn *ib_conn = data; + struct iser_conn *ib_conn = + container_of(work, struct iser_conn, comperror_work); /* getting here when the state is UP means that the conn is being * * terminated asynchronously from the iSCSI layer's perspective. */ diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 64ab5fc7cca..a6289595557 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -390,9 +390,10 @@ static void srp_disconnect_target(struct srp_target_port *target) wait_for_completion(&target->done); } -static void srp_remove_work(void *target_ptr) +static void srp_remove_work(struct work_struct *work) { - struct srp_target_port *target = target_ptr; + struct srp_target_port *target = + container_of(work, struct srp_target_port, work); spin_lock_irq(target->scsi_host->host_lock); if (target->state != SRP_TARGET_DEAD) { @@ -575,7 +576,7 @@ err: spin_lock_irq(target->scsi_host->host_lock); if (target->state == SRP_TARGET_CONNECTING) { target->state = SRP_TARGET_DEAD; - INIT_WORK(&target->work, srp_remove_work, target); + INIT_WORK(&target->work, srp_remove_work); schedule_work(&target->work); } spin_unlock_irq(target->scsi_host->host_lock); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index cbb93669d1c..8451b29a3db 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -567,9 +567,9 @@ static int atkbd_set_leds(struct atkbd *atkbd) * interrupt context. */ -static void atkbd_event_work(void *data) +static void atkbd_event_work(struct work_struct *work) { - struct atkbd *atkbd = data; + struct atkbd *atkbd = container_of(work, struct atkbd, event_work); mutex_lock(&atkbd->event_mutex); @@ -943,7 +943,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); - INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd); + INIT_WORK(&atkbd->event_work, atkbd_event_work); mutex_init(&atkbd->event_mutex); switch (serio->id.type) { diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 979b93e33da..b7f049b45b6 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -572,9 +572,9 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, * were in. */ static void -lkkbd_reinit (void *data) +lkkbd_reinit (struct work_struct *work) { - struct lkkbd *lk = data; + struct lkkbd *lk = container_of(work, struct lkkbd, tq); int division; unsigned char leds_on = 0; unsigned char leds_off = 0; @@ -651,7 +651,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) lk->serio = serio; lk->dev = input_dev; - INIT_WORK (&lk->tq, lkkbd_reinit, lk); + INIT_WORK (&lk->tq, lkkbd_reinit); lk->bell_volume = bell_volume; lk->keyclick_volume = keyclick_volume; lk->ctrlclick_volume = ctrlclick_volume; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index cac4781103c..6cd887c5eb0 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -208,9 +208,9 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) * were in. */ -static void sunkbd_reinit(void *data) +static void sunkbd_reinit(struct work_struct *work) { - struct sunkbd *sunkbd = data; + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); @@ -248,7 +248,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) sunkbd->serio = serio; sunkbd->dev = input_dev; init_waitqueue_head(&sunkbd->wait); - INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd); + INIT_WORK(&sunkbd->tq, sunkbd_reinit); snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys); serio_set_drvdata(serio, sunkbd); diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 6f9b2c7cc9c..52bb2226ce2 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -888,9 +888,10 @@ static int psmouse_poll(struct psmouse *psmouse) * psmouse_resync() attempts to re-validate current protocol. */ -static void psmouse_resync(void *p) +static void psmouse_resync(struct work_struct *work) { - struct psmouse *psmouse = p, *parent = NULL; + struct psmouse *parent = NULL, *psmouse = + container_of(work, struct psmouse, resync_work); struct serio *serio = psmouse->ps2dev.serio; psmouse_ret_t rc = PSMOUSE_GOOD_DATA; int failed = 0, enabled = 0; @@ -1121,7 +1122,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) goto out; ps2_init(&psmouse->ps2dev, serio); - INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); + INIT_WORK(&psmouse->resync_work, psmouse_resync); psmouse->dev = input_dev; snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index e5b1b60757b..b3e84d3bb7f 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -251,9 +251,9 @@ EXPORT_SYMBOL(ps2_command); * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.) */ -static void ps2_execute_scheduled_command(void *data) +static void ps2_execute_scheduled_command(struct work_struct *work) { - struct ps2work *ps2work = data; + struct ps2work *ps2work = container_of(work, struct ps2work, work); ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command); kfree(ps2work); @@ -278,7 +278,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman ps2work->ps2dev = ps2dev; ps2work->command = command; memcpy(ps2work->param, param, send); - INIT_WORK(&ps2work->work, ps2_execute_scheduled_command, ps2work); + INIT_WORK(&ps2work->work, ps2_execute_scheduled_command); if (!schedule_work(&ps2work->work)) { kfree(ps2work); diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c index 6ae6eb32211..946c38cf6f8 100644 --- a/drivers/isdn/act2000/capi.c +++ b/drivers/isdn/act2000/capi.c @@ -627,8 +627,10 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { } void -actcapi_dispatch(act2000_card *card) +actcapi_dispatch(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, rcv_tq); struct sk_buff *skb; actcapi_msg *msg; __u16 ccmd; diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h index 49f453c53c6..e55f6a931f6 100644 --- a/drivers/isdn/act2000/capi.h +++ b/drivers/isdn/act2000/capi.h @@ -356,7 +356,7 @@ extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int extern void actcapi_select_b2_protocol_req(act2000_card *, act2000_chan *); extern void actcapi_disconnect_b3_req(act2000_card *, act2000_chan *); extern void actcapi_connect_resp(act2000_card *, act2000_chan *, __u8); -extern void actcapi_dispatch(act2000_card *); +extern void actcapi_dispatch(struct work_struct *); #ifdef DEBUG_MSG extern void actcapi_debug_msg(struct sk_buff *skb, int); #else diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index d89dcde4ead..90593e2ef87 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -192,8 +192,11 @@ act2000_set_msn(act2000_card *card, char *eazmsn) } static void -act2000_transmit(struct act2000_card *card) +act2000_transmit(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, snd_tq); + switch (card->bus) { case ACT2000_BUS_ISA: act2000_isa_send(card); @@ -207,8 +210,11 @@ act2000_transmit(struct act2000_card *card) } static void -act2000_receive(struct act2000_card *card) +act2000_receive(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, poll_tq); + switch (card->bus) { case ACT2000_BUS_ISA: act2000_isa_receive(card); @@ -227,7 +233,7 @@ act2000_poll(unsigned long data) act2000_card * card = (act2000_card *)data; unsigned long flags; - act2000_receive(card); + act2000_receive(&card->poll_tq); spin_lock_irqsave(&card->lock, flags); mod_timer(&card->ptimer, jiffies+3); spin_unlock_irqrestore(&card->lock, flags); @@ -578,9 +584,9 @@ act2000_alloccard(int bus, int port, int irq, char *id) skb_queue_head_init(&card->sndq); skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->ackq); - INIT_WORK(&card->snd_tq, (void *) (void *) act2000_transmit, card); - INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card); - INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card); + INIT_WORK(&card->snd_tq, act2000_transmit); + INIT_WORK(&card->rcv_tq, actcapi_dispatch); + INIT_WORK(&card->poll_tq, act2000_receive); init_timer(&card->ptimer); card->interface.owner = THIS_MODULE; card->interface.channels = ACT2000_BCH; diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 8c4fcb9027b..783a2552631 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -208,9 +208,10 @@ static void notify_down(u32 contr) } } -static void notify_handler(void *data) +static void notify_handler(struct work_struct *work) { - struct capi_notifier *np = data; + struct capi_notifier *np = + container_of(work, struct capi_notifier, work); switch (np->cmd) { case KCI_CONTRUP: @@ -235,7 +236,7 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) if (!np) return -ENOMEM; - INIT_WORK(&np->work, notify_handler, np); + INIT_WORK(&np->work, notify_handler); np->cmd = cmd; np->controller = controller; np->applid = applid; @@ -248,10 +249,11 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) /* -------- Receiver ------------------------------------------ */ -static void recv_handler(void *_ap) +static void recv_handler(struct work_struct *work) { struct sk_buff *skb; - struct capi20_appl *ap = (struct capi20_appl *) _ap; + struct capi20_appl *ap = + container_of(work, struct capi20_appl, recv_work); if ((!ap) || (ap->release_in_progress)) return; @@ -527,7 +529,7 @@ u16 capi20_register(struct capi20_appl *ap) ap->callback = NULL; init_MUTEX(&ap->recv_sem); skb_queue_head_init(&ap->recv_queue); - INIT_WORK(&ap->recv_work, recv_handler, (void *)ap); + INIT_WORK(&ap->recv_work, recv_handler); ap->release_in_progress = 0; write_unlock_irqrestore(&application_lock, flags); diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index bec59010bc6..3b19caeba25 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c @@ -232,9 +232,10 @@ Amd7930_new_ph(struct IsdnCardState *cs) static void -Amd7930_bh(struct IsdnCardState *cs) +Amd7930_bh(struct work_struct *work) { - + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -789,7 +790,7 @@ Amd7930_init(struct IsdnCardState *cs) void __devinit setup_Amd7930(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs); + INIT_WORK(&cs->tqueue, Amd7930_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 785b08554fc..cede72cdbb3 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1137,7 +1137,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow cs->tx_skb = NULL; cs->tx_cnt = 0; cs->event = 0; - cs->tqueue.data = cs; skb_queue_head_init(&cs->rq); skb_queue_head_init(&cs->sq); @@ -1554,7 +1553,7 @@ static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); static void hisax_bc_close(struct BCState *bcs); -static void hisax_bh(struct IsdnCardState *cs); +static void hisax_bh(struct work_struct *work); static void EChannel_proc_rcv(struct hisax_d_if *d_if); int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], @@ -1586,7 +1585,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; cs->cardmsg = hisax_cardmsg; - INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs); + INIT_WORK(&cs->tqueue, hisax_bh); cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1; for (i = 0; i < 2; i++) { cs->bcs[i].BC_SetStack = hisax_bc_setstack; @@ -1618,8 +1617,10 @@ static void hisax_sched_event(struct IsdnCardState *cs, int event) schedule_work(&cs->tqueue); } -static void hisax_bh(struct IsdnCardState *cs) +static void hisax_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *st; int pr; diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c index d852c9d998b..de9b1a4d6ba 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/drivers/isdn/hisax/hfc4s8s_l1.c @@ -1083,8 +1083,9 @@ tx_b_frame(struct hfc4s8s_btype *bch) /* bottom half handler for interrupt */ /*************************************/ static void -hfc4s8s_bh(hfc4s8s_hw * hw) +hfc4s8s_bh(struct work_struct *work) { + hfc4s8s_hw *hw = container_of(work, hfc4s8s_hw, tqueue); u_char b; struct hfc4s8s_l1 *l1p; volatile u_char *fifo_stat; @@ -1550,7 +1551,7 @@ setup_instance(hfc4s8s_hw * hw) goto out; } - INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw); + INIT_WORK(&hw->tqueue, hfc4s8s_bh); if (request_irq (hw->irq, hfc4s8s_interrupt, IRQF_SHARED, hw->card_name, hw)) { diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 6360e821472..8d9864453a2 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -549,10 +549,11 @@ setstack_2b(struct PStack *st, struct BCState *bcs) } static void -hfcd_bh(struct IsdnCardState *cs) +hfcd_bh(struct work_struct *work) { - if (!cs) - return; + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { switch (cs->dc.hfcd.ph_state) { case (0): @@ -1072,5 +1073,5 @@ set_cs_func(struct IsdnCardState *cs) cs->dbusytimer.function = (void *) hfc_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs); + INIT_WORK(&cs->tqueue, hfcd_bh); } diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 93f60b56351..5db0a85b827 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -1506,8 +1506,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs) /* handle L1 state changes */ /***************************/ static void -hfcpci_bh(struct IsdnCardState *cs) +hfcpci_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); u_long flags; // struct PStack *stptr; @@ -1722,7 +1724,7 @@ setup_hfcpci(struct IsdnCard *card) Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); /* At this point the needed PCI config is done */ /* fifos are still not enabled */ - INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs); + INIT_WORK(&cs->tqueue, hfcpci_bh); cs->setstack_d = setstack_hfcpci; cs->BC_Send_Data = &hfcpci_send_data; cs->readisac = NULL; diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 954d1536db1..4fd09d21a27 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -1251,8 +1251,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs) /* handle L1 state changes */ /***************************/ static void -hfcsx_bh(struct IsdnCardState *cs) +hfcsx_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); u_long flags; if (!cs) @@ -1499,7 +1501,7 @@ setup_hfcsx(struct IsdnCard *card) cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs); + INIT_WORK(&cs->tqueue, hfcsx_bh); cs->readisac = NULL; cs->writeisac = NULL; cs->readisacfifo = NULL; diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index da706925d54..682cac32f25 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -77,8 +77,10 @@ icc_new_ph(struct IsdnCardState *cs) } static void -icc_bh(struct IsdnCardState *cs) +icc_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -674,7 +676,7 @@ clear_pending_icc_ints(struct IsdnCardState *cs) void __devinit setup_icc(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs); + INIT_WORK(&cs->tqueue, icc_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 282f349408b..4e9f23803da 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -81,8 +81,10 @@ isac_new_ph(struct IsdnCardState *cs) } static void -isac_bh(struct IsdnCardState *cs) +isac_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -674,7 +676,7 @@ clear_pending_isac_ints(struct IsdnCardState *cs) void __devinit setup_isac(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs); + INIT_WORK(&cs->tqueue, isac_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 674af673ff9..6f1a6583b17 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -437,8 +437,10 @@ extern void BChannel_bh(struct BCState *); #define B_LL_OK 10 static void -isar_bh(struct BCState *bcs) +isar_bh(struct work_struct *work) { + struct BCState *bcs = container_of(work, struct BCState, tqueue); + BChannel_bh(bcs); if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); @@ -1580,7 +1582,7 @@ isar_setup(struct IsdnCardState *cs) cs->bcs[i].mode = 0; cs->bcs[i].hw.isar.dpath = i + 1; modeisar(&cs->bcs[i], 0, 0); - INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]); + INIT_WORK(&cs->bcs[i].tqueue, isar_bh); } } diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index bab35688648..a14204ec88e 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -315,8 +315,10 @@ BChannel_proc_ack(struct BCState *bcs) } void -BChannel_bh(struct BCState *bcs) +BChannel_bh(struct work_struct *work) { + struct BCState *bcs = container_of(work, struct BCState, tqueue); + if (!bcs) return; if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event)) @@ -362,7 +364,7 @@ init_bcstate(struct IsdnCardState *cs, int bc) bcs->cs = cs; bcs->channel = bc; - INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs); + INIT_WORK(&bcs->tqueue, BChannel_bh); spin_lock_init(&bcs->aclock); bcs->BC_SetStack = NULL; bcs->BC_Close = NULL; diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index 1655341797a..3aeceaf9769 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -101,8 +101,10 @@ W6692_new_ph(struct IsdnCardState *cs) } static void -W6692_bh(struct IsdnCardState *cs) +W6692_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -1070,7 +1072,7 @@ setup_w6692(struct IsdnCard *card) id_list[cs->subtyp].card_name, cs->irq, cs->hw.w6692.iobase); - INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs); + INIT_WORK(&cs->tqueue, W6692_bh); cs->readW6692 = &ReadW6692; cs->writeW6692 = &WriteW6692; cs->readisacfifo = &ReadISACfifo; diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c index 82e42a80dc4..a1206498a1c 100644 --- a/drivers/isdn/hysdn/boardergo.c +++ b/drivers/isdn/hysdn/boardergo.c @@ -71,8 +71,9 @@ ergo_interrupt(int intno, void *dev_id) /* may be queued from everywhere (interrupts included). */ /******************************************************************************/ static void -ergo_irq_bh(hysdn_card * card) +ergo_irq_bh(struct work_struct *ugli_api) { + hysdn_card * card = container_of(ugli_api, hysdn_card, irq_queue); tErgDpram *dpr; int again; unsigned long flags; @@ -442,7 +443,7 @@ ergo_inithardware(hysdn_card * card) card->writebootseq = ergo_writebootseq; card->waitpofready = ergo_waitpofready; card->set_errlog_state = ergo_set_errlog_state; - INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card); + INIT_WORK(&card->irq_queue, ergo_irq_bh); card->hysdn_lock = SPIN_LOCK_UNLOCKED; return (0); diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 1f8d6ae66b4..2e4daebfb7e 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -984,9 +984,9 @@ void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb) /* * called from tq_immediate */ -static void isdn_net_softint(void *private) +static void isdn_net_softint(struct work_struct *work) { - isdn_net_local *lp = private; + isdn_net_local *lp = container_of(work, isdn_net_local, tqueue); struct sk_buff *skb; spin_lock_bh(&lp->xmit_lock); @@ -2596,7 +2596,7 @@ isdn_net_new(char *name, struct net_device *master) netdev->local->netdev = netdev; netdev->local->next = netdev->local; - INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local); + INIT_WORK(&netdev->local->tqueue, isdn_net_softint); spin_lock_init(&netdev->local->xmit_lock); netdev->local->isdn_device = -1; diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 6ead5e1508b..1966f3410a1 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -68,8 +68,6 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list); static int pcbit_check_msn(struct pcbit_dev *dev, char *msn); -extern void pcbit_deliver(void * data); - int pcbit_init_dev(int board, int mem_base, int irq) { struct pcbit_dev *dev; @@ -129,7 +127,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) memset(dev->b2, 0, sizeof(struct pcbit_chan)); dev->b2->id = 1; - INIT_WORK(&dev->qdelivery, pcbit_deliver, dev); + INIT_WORK(&dev->qdelivery, pcbit_deliver); /* * interrupts diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c index 937fd212038..0c9f6df873f 100644 --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -67,7 +67,6 @@ extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, * Prototypes */ -void pcbit_deliver(void *data); static void pcbit_transmit(struct pcbit_dev *dev); static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); @@ -299,11 +298,12 @@ pcbit_transmit(struct pcbit_dev *dev) */ void -pcbit_deliver(void *data) +pcbit_deliver(struct work_struct *work) { struct frame_buf *frame; unsigned long flags, msg; - struct pcbit_dev *dev = (struct pcbit_dev *) data; + struct pcbit_dev *dev = + container_of(work, struct pcbit_dev, qdelivery); spin_lock_irqsave(&dev->lock, flags); diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h index 388bacefd23..19c18e88ff1 100644 --- a/drivers/isdn/pcbit/pcbit.h +++ b/drivers/isdn/pcbit/pcbit.h @@ -166,4 +166,6 @@ struct pcbit_ioctl { #define L2_RUNNING 5 #define L2_ERROR 6 +extern void pcbit_deliver(struct work_struct *work); + #endif diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index be0bd34ff6f..d43ea81d6df 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -267,12 +267,12 @@ adb_probe_task(void *x) } static void -__adb_probe_task(void *data) +__adb_probe_task(struct work_struct *bullshit) { adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL); } -static DECLARE_WORK(adb_reset_work, __adb_probe_task, NULL); +static DECLARE_WORK(adb_reset_work, __adb_probe_task); int adb_reset_bus(void) diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index f1b6f563673..5ed41fe84e5 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -48,7 +48,8 @@ struct rackmeter_dma { } ____cacheline_aligned; struct rackmeter_cpu { - struct work_struct sniffer; + struct delayed_work sniffer; + struct rackmeter *rm; cputime64_t prev_wall; cputime64_t prev_idle; int zero; @@ -208,11 +209,12 @@ static void rackmeter_setup_dbdma(struct rackmeter *rm) rackmeter_do_pause(rm, 0); } -static void rackmeter_do_timer(void *data) +static void rackmeter_do_timer(struct work_struct *work) { - struct rackmeter *rm = data; + struct rackmeter_cpu *rcpu = + container_of(work, struct rackmeter_cpu, sniffer.work); + struct rackmeter *rm = rcpu->rm; unsigned int cpu = smp_processor_id(); - struct rackmeter_cpu *rcpu = &rm->cpu[cpu]; cputime64_t cur_jiffies, total_idle_ticks; unsigned int total_ticks, idle_ticks; int i, offset, load, cumm, pause; @@ -263,8 +265,10 @@ static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm) * on those machines yet */ - INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm); - INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm); + rm->cpu[0].rm = rm; + INIT_DELAYED_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer); + rm->cpu[1].rm = rm; + INIT_DELAYED_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer); for_each_online_cpu(cpu) { struct rackmeter_cpu *rcpu; diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 4f724cdd2ef..6dde27ab79a 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -601,7 +601,7 @@ core_initcall(smu_late_init); * sysfs visibility */ -static void smu_expose_childs(void *unused) +static void smu_expose_childs(struct work_struct *unused) { struct device_node *np; @@ -611,7 +611,7 @@ static void smu_expose_childs(void *unused) &smu->of_dev->dev); } -static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); +static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); static int smu_platform_probe(struct of_device* dev, const struct of_device_id *match) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 08a40f4e4f6..ed2d4ef27fd 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -458,11 +458,11 @@ static void dec_pending(struct crypt_io *io, int error) * interrupt context. */ static struct workqueue_struct *_kcryptd_workqueue; -static void kcryptd_do_work(void *data); +static void kcryptd_do_work(struct work_struct *work); static void kcryptd_queue_io(struct crypt_io *io) { - INIT_WORK(&io->work, kcryptd_do_work, io); + INIT_WORK(&io->work, kcryptd_do_work); queue_work(_kcryptd_workqueue, &io->work); } @@ -618,9 +618,9 @@ static void process_read_endio(struct crypt_io *io) dec_pending(io, crypt_convert(cc, &ctx)); } -static void kcryptd_do_work(void *data) +static void kcryptd_do_work(struct work_struct *work) { - struct crypt_io *io = data; + struct crypt_io *io = container_of(work, struct crypt_io, work); if (io->post_process) process_read_endio(io); diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index d754e0bc6e9..e77ee6fd104 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -104,8 +104,8 @@ typedef int (*action_fn) (struct pgpath *pgpath); static kmem_cache_t *_mpio_cache; struct workqueue_struct *kmultipathd; -static void process_queued_ios(void *data); -static void trigger_event(void *data); +static void process_queued_ios(struct work_struct *work); +static void trigger_event(struct work_struct *work); /*----------------------------------------------- @@ -173,8 +173,8 @@ static struct multipath *alloc_multipath(struct dm_target *ti) INIT_LIST_HEAD(&m->priority_groups); spin_lock_init(&m->lock); m->queue_io = 1; - INIT_WORK(&m->process_queued_ios, process_queued_ios, m); - INIT_WORK(&m->trigger_event, trigger_event, m); + INIT_WORK(&m->process_queued_ios, process_queued_ios); + INIT_WORK(&m->trigger_event, trigger_event); m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); if (!m->mpio_pool) { kfree(m); @@ -379,9 +379,10 @@ static void dispatch_queued_ios(struct multipath *m) } } -static void process_queued_ios(void *data) +static void process_queued_ios(struct work_struct *work) { - struct multipath *m = (struct multipath *) data; + struct multipath *m = + container_of(work, struct multipath, process_queued_ios); struct hw_handler *hwh = &m->hw_handler; struct pgpath *pgpath = NULL; unsigned init_required = 0, must_queue = 1; @@ -421,9 +422,10 @@ out: * An event is triggered whenever a path is taken out of use. * Includes path failure and PG bypass. */ -static void trigger_event(void *data) +static void trigger_event(struct work_struct *work) { - struct multipath *m = (struct multipath *) data; + struct multipath *m = + container_of(work, struct multipath, trigger_event); dm_table_event(m->ti->table); } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 48a653b3f51..fc8cbb168e3 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -883,7 +883,7 @@ static void do_mirror(struct mirror_set *ms) do_writes(ms, &writes); } -static void do_work(void *ignored) +static void do_work(struct work_struct *ignored) { struct mirror_set *ms; @@ -1269,7 +1269,7 @@ static int __init dm_mirror_init(void) dm_dirty_log_exit(); return r; } - INIT_WORK(&_kmirrord_work, do_work, NULL); + INIT_WORK(&_kmirrord_work, do_work); r = dm_register_target(&mirror_target); if (r < 0) { diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 5281e009407..91c7aa1fed0 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -40,7 +40,7 @@ #define SNAPSHOT_PAGES 256 struct workqueue_struct *ksnapd; -static void flush_queued_bios(void *data); +static void flush_queued_bios(struct work_struct *work); struct pending_exception { struct exception e; @@ -528,7 +528,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) } bio_list_init(&s->queued_bios); - INIT_WORK(&s->queued_bios_work, flush_queued_bios, s); + INIT_WORK(&s->queued_bios_work, flush_queued_bios); /* Add snapshot to the list of snapshots for this origin */ /* Exceptions aren't triggered till snapshot_resume() is called */ @@ -603,9 +603,10 @@ static void flush_bios(struct bio *bio) } } -static void flush_queued_bios(void *data) +static void flush_queued_bios(struct work_struct *work) { - struct dm_snapshot *s = (struct dm_snapshot *) data; + struct dm_snapshot *s = + container_of(work, struct dm_snapshot, queued_bios_work); struct bio *queued_bios; unsigned long flags; diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index f1db6eff485..b3c01496c73 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -417,7 +417,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *)) /* * kcopyd does this every time it's woken up. */ -static void do_work(void *ignored) +static void do_work(struct work_struct *ignored) { /* * The order that these are called is *very* important. @@ -628,7 +628,7 @@ static int kcopyd_init(void) } kcopyd_clients++; - INIT_WORK(&_kcopyd_work, do_work, NULL); + INIT_WORK(&_kcopyd_work, do_work); mutex_unlock(&kcopyd_init_lock); return 0; } diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 06893243f3d..6e166801505 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -63,7 +63,7 @@ struct flexcop_pci { unsigned long last_irq; - struct work_struct irq_check_work; + struct delayed_work irq_check_work; struct flexcop_device *fc_dev; }; @@ -97,9 +97,10 @@ static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi return 0; } -static void flexcop_pci_irq_check_work(void *data) +static void flexcop_pci_irq_check_work(struct work_struct *work) { - struct flexcop_pci *fc_pci = data; + struct flexcop_pci *fc_pci = + container_of(work, struct flexcop_pci, irq_check_work.work); struct flexcop_device *fc = fc_pci->fc_dev; flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); @@ -371,7 +372,7 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) goto err_fc_exit; - INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci); + INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); return ret; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 8a7dd507cf6..206c13e47a0 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -128,7 +128,7 @@ struct cinergyt2 { struct dvbt_set_parameters_msg param; struct dvbt_get_status_msg status; - struct work_struct query_work; + struct delayed_work query_work; wait_queue_head_t poll_wq; int pending_fe_events; @@ -142,7 +142,7 @@ struct cinergyt2 { #ifdef ENABLE_RC struct input_dev *rc_input_dev; char phys[64]; - struct work_struct rc_query_work; + struct delayed_work rc_query_work; int rc_input_event; u32 rc_last_code; unsigned long last_event_jiffies; @@ -723,9 +723,10 @@ static struct dvb_device cinergyt2_fe_template = { #ifdef ENABLE_RC -static void cinergyt2_query_rc (void *data) +static void cinergyt2_query_rc (struct work_struct *work) { - struct cinergyt2 *cinergyt2 = data; + struct cinergyt2 *cinergyt2 = + container_of(work, struct cinergyt2, rc_query_work.work); char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; struct cinergyt2_rc_event rc_events[12]; int n, len, i; @@ -806,7 +807,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); cinergyt2->rc_input_event = KEY_MAX; cinergyt2->rc_last_code = ~0; - INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); + INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); input_dev->name = DRIVER_NAME " remote control"; input_dev->phys = cinergyt2->phys; @@ -847,9 +848,10 @@ static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } #endif /* ENABLE_RC */ -static void cinergyt2_query (void *data) +static void cinergyt2_query (struct work_struct *work) { - struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; + struct cinergyt2 *cinergyt2 = + container_of(work, struct cinergyt2, query_work.work); char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; struct dvbt_get_status_msg *s = &cinergyt2->status; uint8_t lock_bits; @@ -893,7 +895,7 @@ static int cinergyt2_probe (struct usb_interface *intf, mutex_init(&cinergyt2->sem); init_waitqueue_head (&cinergyt2->poll_wq); - INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); + INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); cinergyt2->udev = interface_to_usbdev(intf); cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 8859ab74f0f..ebf4dc5190f 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -127,6 +127,7 @@ struct dvb_net_priv { int in_use; struct net_device_stats stats; u16 pid; + struct net_device *net; struct dvb_net *host; struct dmx_demux *demux; struct dmx_section_feed *secfeed; @@ -1123,10 +1124,11 @@ static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) } -static void wq_set_multicast_list (void *data) +static void wq_set_multicast_list (struct work_struct *work) { - struct net_device *dev = data; - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = + container_of(work, struct dvb_net_priv, set_multicast_list_wq); + struct net_device *dev = priv->net; dvb_net_feed_stop(dev); priv->rx_mode = RX_MODE_UNI; @@ -1167,9 +1169,11 @@ static void dvb_net_set_multicast_list (struct net_device *dev) } -static void wq_restart_net_feed (void *data) +static void wq_restart_net_feed (struct work_struct *work) { - struct net_device *dev = data; + struct dvb_net_priv *priv = + container_of(work, struct dvb_net_priv, restart_net_feed_wq); + struct net_device *dev = priv->net; if (netif_running(dev)) { dvb_net_feed_stop(dev); @@ -1276,6 +1280,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) dvbnet->device[if_num] = net; priv = net->priv; + priv->net = net; priv->demux = dvbnet->demux; priv->pid = pid; priv->rx_mode = RX_MODE_UNI; @@ -1284,8 +1289,8 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) priv->feedtype = feedtype; reset_ule(priv); - INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); - INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); + INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list); + INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed); mutex_init(&priv->mutex); net->base_addr = pid; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 0a3a0b6c235..794e4471561 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -13,9 +13,10 @@ * * TODO: Fix the repeat rate of the input device. */ -static void dvb_usb_read_remote_control(void *data) +static void dvb_usb_read_remote_control(struct work_struct *work) { - struct dvb_usb_device *d = data; + struct dvb_usb_device *d = + container_of(work, struct dvb_usb_device, rc_query_work.work); u32 event; int state; @@ -128,7 +129,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_register_device(d->rc_input_dev); - INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d); + INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); info("schedule remote query interval to %d msecs.", d->props.rc_interval); schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 376c45a8e77..0d721731a52 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -369,7 +369,7 @@ struct dvb_usb_device { /* remote control */ struct input_dev *rc_input_dev; char rc_phys[64]; - struct work_struct rc_query_work; + struct delayed_work rc_query_work; u32 last_event; int last_state; diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c index 41f4b8d1755..b12cec94f4c 100644 --- a/drivers/media/video/cpia_pp.c +++ b/drivers/media/video/cpia_pp.c @@ -82,6 +82,8 @@ struct pp_cam_entry { struct pardevice *pdev; struct parport *port; struct work_struct cb_task; + void (*cb_func)(void *cbdata); + void *cb_data; int open_count; wait_queue_head_t wq_stream; /* image state flags */ @@ -130,6 +132,20 @@ static void cpia_parport_disable_irq( struct parport *port ) { #define PARPORT_CHUNK_SIZE PAGE_SIZE +static void cpia_pp_run_callback(struct work_struct *work) +{ + void (*cb_func)(void *cbdata); + void *cb_data; + struct pp_cam_entry *cam; + + cam = container_of(work, struct pp_cam_entry, cb_task); + cb_func = cam->cb_func; + cb_data = cam->cb_data; + work_release(work); + + cb_func(cb_data); +} + /**************************************************************************** * * CPiA-specific low-level parport functions for nibble uploads @@ -664,7 +680,9 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo int retval = 0; if(cam->port->irq != PARPORT_IRQ_NONE) { - INIT_WORK(&cam->cb_task, cb, cbdata); + cam->cb_func = cb; + cam->cb_data = cbdata; + INIT_WORK_NAR(&cam->cb_task, cpia_pp_run_callback); } else { retval = -1; } diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 57e1c024a54..e60a0a52e4b 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -145,9 +145,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void cx88_ir_work(void *data) +static void cx88_ir_work(struct work_struct *work) { - struct cx88_IR *ir = data; + struct cx88_IR *ir = container_of(work, struct cx88_IR, work); unsigned long timeout; cx88_ir_handle_key(ir); @@ -308,7 +308,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) core->ir = ir; if (ir->polling) { - INIT_WORK(&ir->work, cx88_ir_work, ir); + INIT_WORK(&ir->work, cx88_ir_work); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 1457b160222..ab87e7bfe84 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -268,9 +268,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void ir_work(void *data) +static void ir_work(struct work_struct *work) { - struct IR_i2c *ir = data; + struct IR_i2c *ir = container_of(work, struct IR_i2c, work); ir_key_poll(ir); mod_timer(&ir->timer, jiffies+HZ/10); } @@ -400,7 +400,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->input->name,ir->input->phys,adap->name); /* start polling via eventd */ - INIT_WORK(&ir->work, ir_work, ir); + INIT_WORK(&ir->work, ir_work); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index f129f316d20..cf129746205 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -45,16 +45,21 @@ static void pvr2_context_trigger_poll(struct pvr2_context *mp) } -static void pvr2_context_poll(struct pvr2_context *mp) +static void pvr2_context_poll(struct work_struct *work) { + struct pvr2_context *mp = + container_of(work, struct pvr2_context, workpoll); pvr2_context_enter(mp); do { pvr2_hdw_poll(mp->hdw); } while (0); pvr2_context_exit(mp); } -static void pvr2_context_setup(struct pvr2_context *mp) +static void pvr2_context_setup(struct work_struct *work) { + struct pvr2_context *mp = + container_of(work, struct pvr2_context, workinit); + pvr2_context_enter(mp); do { if (!pvr2_hdw_dev_ok(mp->hdw)) break; pvr2_hdw_setup(mp->hdw); @@ -92,8 +97,8 @@ struct pvr2_context *pvr2_context_create( } mp->workqueue = create_singlethread_workqueue("pvrusb2"); - INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp); - INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp); + INIT_WORK(&mp->workinit, pvr2_context_setup); + INIT_WORK(&mp->workpoll, pvr2_context_poll); queue_work(mp->workqueue,&mp->workinit); done: return mp; diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 7b9859c3301..92eabf88a09 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -324,9 +324,9 @@ static void saa6588_timer(unsigned long data) schedule_work(&s->work); } -static void saa6588_work(void *data) +static void saa6588_work(struct work_struct *work) { - struct saa6588 *s = (struct saa6588 *)data; + struct saa6588 *s = container_of(work, struct saa6588, work); saa6588_i2c_poll(s); mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); @@ -419,7 +419,7 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) saa6588_configure(s); /* start polling via eventd */ - INIT_WORK(&s->work, saa6588_work, s); + INIT_WORK(&s->work, saa6588_work); init_timer(&s->timer); s->timer.function = saa6588_timer; s->timer.data = (unsigned long)s; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 65d044086ce..daaae870a2c 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -343,9 +343,10 @@ static struct video_device saa7134_empress_template = .minor = -1, }; -static void empress_signal_update(void* data) +static void empress_signal_update(struct work_struct *work) { - struct saa7134_dev* dev = (struct saa7134_dev*) data; + struct saa7134_dev* dev = + container_of(work, struct saa7134_dev, empress_workqueue); if (dev->nosignal) { dprintk("no video signal\n"); @@ -378,7 +379,7 @@ static int empress_init(struct saa7134_dev *dev) "%s empress (%s)", dev->name, saa7134_boards[dev->board].name); - INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev); + INIT_WORK(&dev->empress_workqueue, empress_signal_update); err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, empress_nr[dev->nr]); @@ -399,7 +400,7 @@ static int empress_init(struct saa7134_dev *dev) sizeof(struct saa7134_buf), dev); - empress_signal_update(dev); + empress_signal_update(&dev->empress_workqueue); return 0; } diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 1dd49177315..ef2b55e1991 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1018,9 +1018,10 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) } static void -mptfc_setup_reset(void *arg) +mptfc_setup_reset(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_setup_reset_work); u64 pn; struct mptfc_rport_info *ri; @@ -1043,9 +1044,10 @@ mptfc_setup_reset(void *arg) } static void -mptfc_rescan_devices(void *arg) +mptfc_rescan_devices(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_rescan_work); int ii; u64 pn; struct mptfc_rport_info *ri; @@ -1154,8 +1156,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) } spin_lock_init(&ioc->fc_rescan_work_lock); - INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); - INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); + INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices); + INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset); spin_lock_irqsave(&ioc->FreeQlock, flags); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 314c3a27585..b7c4407c5e3 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -111,7 +111,8 @@ struct mpt_lan_priv { u32 total_received; struct net_device_stats stats; /* Per device statistics */ - struct work_struct post_buckets_task; + struct delayed_work post_buckets_task; + struct net_device *dev; unsigned long post_buckets_active; }; @@ -132,7 +133,7 @@ static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, static int mpt_lan_open(struct net_device *dev); static int mpt_lan_reset(struct net_device *dev); static int mpt_lan_close(struct net_device *dev); -static void mpt_lan_post_receive_buckets(void *dev_id); +static void mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv); static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority); static int mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg); @@ -345,7 +346,7 @@ mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; spin_unlock_irqrestore(&priv->rxfidx_lock, flags); } else { - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); netif_wake_queue(dev); } @@ -441,7 +442,7 @@ mpt_lan_open(struct net_device *dev) dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n")); - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n", IOC_AND_NETDEV_NAMES_s_s(dev)); @@ -854,7 +855,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) if (test_and_set_bit(0, &priv->post_buckets_active) == 0) { if (priority) { - schedule_work(&priv->post_buckets_task); + schedule_delayed_work(&priv->post_buckets_task, 0); } else { schedule_delayed_work(&priv->post_buckets_task, 1); dioprintk((KERN_INFO MYNAM ": post_buckets queued on " @@ -1188,10 +1189,9 @@ mpt_lan_receive_post_reply(struct net_device *dev, /* Simple SGE's only at the moment */ static void -mpt_lan_post_receive_buckets(void *dev_id) +mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv) { - struct net_device *dev = dev_id; - struct mpt_lan_priv *priv = dev->priv; + struct net_device *dev = priv->dev; MPT_ADAPTER *mpt_dev = priv->mpt_dev; MPT_FRAME_HDR *mf; LANReceivePostRequest_t *pRecvReq; @@ -1335,6 +1335,13 @@ out: clear_bit(0, &priv->post_buckets_active); } +static void +mpt_lan_post_receive_buckets_work(struct work_struct *work) +{ + mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv, + post_buckets_task.work)); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static struct net_device * mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) @@ -1350,11 +1357,13 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) priv = netdev_priv(dev); + priv->dev = dev; priv->mpt_dev = mpt_dev; priv->pnum = pnum; - memset(&priv->post_buckets_task, 0, sizeof(struct work_struct)); - INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev); + memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task)); + INIT_DELAYED_WORK(&priv->post_buckets_task, + mpt_lan_post_receive_buckets_work); priv->post_buckets_active = 0; dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n", diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b752a479f6d..4f0c530e47b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -2006,9 +2006,10 @@ __mptsas_discovery_work(MPT_ADAPTER *ioc) *(Mutex LOCKED) */ static void -mptsas_discovery_work(void * arg) +mptsas_discovery_work(struct work_struct *work) { - struct mptsas_discovery_event *ev = arg; + struct mptsas_discovery_event *ev = + container_of(work, struct mptsas_discovery_event, work); MPT_ADAPTER *ioc = ev->ioc; mutex_lock(&ioc->sas_discovery_mutex); @@ -2068,9 +2069,9 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) * Work queue thread to clear the persitency table */ static void -mptsas_persist_clear_table(void * arg) +mptsas_persist_clear_table(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task); mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); } @@ -2093,9 +2094,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) * Work queue thread to handle SAS hotplug events */ static void -mptsas_hotplug_work(void *arg) +mptsas_hotplug_work(struct work_struct *work) { - struct mptsas_hotplug_event *ev = arg; + struct mptsas_hotplug_event *ev = + container_of(work, struct mptsas_hotplug_event, work); MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; @@ -2341,7 +2343,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, break; } - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->handle = le16_to_cpu(sas_event_data->DevHandle); ev->parent_handle = @@ -2366,7 +2368,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, * Persistent table is full. */ INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, (void *)ioc); + mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: @@ -2395,7 +2397,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, return; } - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->id = raid_event_data->VolumeID; ev->event_type = MPTSAS_IGNORE_EVENT; @@ -2474,7 +2476,7 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) return; - INIT_WORK(&ev->work, mptsas_discovery_work, ev); + INIT_WORK(&ev->work, mptsas_discovery_work); ev->ioc = ioc; schedule_work(&ev->work); }; @@ -2511,8 +2513,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) break; case MPI_EVENT_PERSISTENT_TABLE_FULL: INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, - (void *)ioc); + mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; case MPI_EVENT_SAS_DISCOVERY: diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index e4cc3dd5fc9..f422c0d0621 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -646,9 +646,10 @@ struct work_queue_wrapper { int disk; }; -static void mpt_work_wrapper(void *data) +static void mpt_work_wrapper(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct Scsi_Host *shost = hd->ioc->sh; struct scsi_device *sdev; @@ -695,7 +696,7 @@ static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) disk); return; } - INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); + INIT_WORK(&wqw->work, mpt_work_wrapper); wqw->hd = hd; wqw->disk = disk; @@ -784,9 +785,10 @@ MODULE_DEVICE_TABLE(pci, mptspi_pci_table); * renegotiate for a given target */ static void -mptspi_dv_renegotiate_work(void *data) +mptspi_dv_renegotiate_work(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct scsi_device *sdev; @@ -804,7 +806,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd) if (!wqw) return; - INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw); + INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work); wqw->hd = hd; schedule_work(&wqw->work); diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 64130227574..7fc7399bd2e 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -232,7 +232,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) break; } - INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); + INIT_WORK(&evt->work, drv->event); queue_work(drv->event_queue, &evt->work); return 1; } diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index a2350640384..9e529d8dd5c 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -371,8 +371,10 @@ static int i2o_exec_remove(struct device *dev) * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY * again, otherwise send LCT NOTIFY to get informed on next LCT change. */ -static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work) +static void i2o_exec_lct_modified(struct work_struct *_work) { + struct i2o_exec_lct_notify_work *work = + container_of(_work, struct i2o_exec_lct_notify_work, work); u32 change_ind = 0; struct i2o_controller *c = work->c; @@ -439,8 +441,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, work->c = c; - INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified, - work); + INIT_WORK(&work->work, i2o_exec_lct_modified); queue_work(i2o_exec_driver.event_queue, &work->work); return 1; } @@ -460,13 +461,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, /** * i2o_exec_event - Event handling function - * @evt: Event which occurs + * @work: Work item in occurring event * * Handles events send by the Executive device. At the moment does not do * anything useful. */ -static void i2o_exec_event(struct i2o_event *evt) +static void i2o_exec_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); + if (likely(evt->i2o_dev)) osm_debug("Event received from device: %d\n", evt->i2o_dev->lct_data.tid); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index eaba81bf2ec..70ae0025332 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -419,16 +419,18 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) /** * i2o_block_delayed_request_fn - delayed request queue function - * delayed_request: the delayed request with the queue to start + * @work: the delayed request with the queue to start * * If the request queue is stopped for a disk, and there is no open * request, a new event is created, which calls this function to start * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never * be started again. */ -static void i2o_block_delayed_request_fn(void *delayed_request) +static void i2o_block_delayed_request_fn(struct work_struct *work) { - struct i2o_block_delayed_request *dreq = delayed_request; + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); struct request_queue *q = dreq->queue; unsigned long flags; @@ -538,8 +540,9 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, return 1; }; -static void i2o_block_event(struct i2o_event *evt) +static void i2o_block_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); osm_debug("event received\n"); kfree(evt); }; @@ -938,8 +941,8 @@ static void i2o_block_request_fn(struct request_queue *q) continue; dreq->queue = q; - INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, - dreq); + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); if (!queue_delayed_work(i2o_block_driver.event_queue, &dreq->work, diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index 4fdaa5bda41..d9fdc95b440 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -96,7 +96,7 @@ struct i2o_block_request { /* I2O Block device delayed request */ struct i2o_block_delayed_request { - struct work_struct work; + struct delayed_work work; struct request_queue *queue; }; diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 1ba8754e938..2ab7add78f9 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -33,9 +33,10 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) spin_unlock_irqrestore(&fm->lock, flags); } -static void tifm_7xx1_remove_media(void *adapter) +static void tifm_7xx1_remove_media(struct work_struct *work) { - struct tifm_adapter *fm = adapter; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_remover); unsigned long flags; int cnt; struct tifm_dev *sock; @@ -169,9 +170,10 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) return base_addr + ((sock_num + 1) << 10); } -static void tifm_7xx1_insert_media(void *adapter) +static void tifm_7xx1_insert_media(struct work_struct *work) { - struct tifm_adapter *fm = adapter; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_inserter); unsigned long flags; tifm_media_id media_id; char *card_name = "xx"; @@ -261,7 +263,7 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) spin_unlock_irqrestore(&fm->lock, flags); flush_workqueue(fm->wq); - tifm_7xx1_remove_media(fm); + tifm_7xx1_remove_media(&fm->media_remover); pci_set_power_state(dev, PCI_D3hot); pci_disable_device(dev); @@ -328,8 +330,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (!fm->sockets) goto err_out_free; - INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media, fm); - INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media, fm); + INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media); + INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media); fm->eject = tifm_7xx1_eject; pci_set_drvdata(dev, fm); @@ -384,7 +386,7 @@ static void tifm_7xx1_remove(struct pci_dev *dev) flush_workqueue(fm->wq); - tifm_7xx1_remove_media(fm); + tifm_7xx1_remove_media(&fm->media_remover); writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); free_irq(dev->irq, fm); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 9d190022a49..6f2a282e2b9 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1419,18 +1419,16 @@ static void mmc_setup(struct mmc_host *host) */ void mmc_detect_change(struct mmc_host *host, unsigned long delay) { - if (delay) - mmc_schedule_delayed_work(&host->detect, delay); - else - mmc_schedule_work(&host->detect); + mmc_schedule_delayed_work(&host->detect, delay); } EXPORT_SYMBOL(mmc_detect_change); -static void mmc_rescan(void *data) +static void mmc_rescan(struct work_struct *work) { - struct mmc_host *host = data; + struct mmc_host *host = + container_of(work, struct mmc_host, detect.work); struct list_head *l, *n; unsigned char power_mode; @@ -1513,7 +1511,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_LIST_HEAD(&host->cards); - INIT_WORK(&host->detect, mmc_rescan, host); + INIT_DELAYED_WORK(&host->detect, mmc_rescan); /* * By default, hosts do not support SGIO or large requests. @@ -1611,7 +1609,7 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - mmc_rescan(host); + mmc_rescan(&host->detect.work); return 0; } diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h index cd5e0ab3d84..149affe0b68 100644 --- a/drivers/mmc/mmc.h +++ b/drivers/mmc/mmc.h @@ -20,6 +20,6 @@ void mmc_remove_host_sysfs(struct mmc_host *host); void mmc_free_host_sysfs(struct mmc_host *host); int mmc_schedule_work(struct work_struct *work); -int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay); +int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); void mmc_flush_scheduled_work(void); #endif diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index ac532963604..e334acd045b 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -321,17 +321,9 @@ void mmc_free_host_sysfs(struct mmc_host *host) static struct workqueue_struct *workqueue; /* - * Internal function. Schedule work in the MMC work queue. - */ -int mmc_schedule_work(struct work_struct *work) -{ - return queue_work(workqueue, work); -} - -/* * Internal function. Schedule delayed work in the MMC work queue. */ -int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay) +int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) { return queue_delayed_work(workqueue, work, delay); } diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index 0fdc55b08a6..e846499a004 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c @@ -99,7 +99,7 @@ struct tifm_sd { struct mmc_request *req; struct work_struct cmd_handler; - struct work_struct abort_handler; + struct delayed_work abort_handler; wait_queue_head_t can_eject; size_t written_blocks; @@ -496,9 +496,9 @@ err_out: mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd(void *data) +static void tifm_sd_end_cmd(struct work_struct *work) { - struct tifm_sd *host = data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -608,9 +608,9 @@ err_out: mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd_nodma(void *data) +static void tifm_sd_end_cmd_nodma(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -661,11 +661,14 @@ static void tifm_sd_end_cmd_nodma(void *data) mmc_request_done(mmc, mrq); } -static void tifm_sd_abort(void *data) +static void tifm_sd_abort(struct work_struct *work) { + struct tifm_sd *host = + container_of(work, struct tifm_sd, abort_handler.work); + printk(KERN_ERR DRIVER_NAME ": card failed to respond for a long period of time"); - tifm_eject(((struct tifm_sd*)data)->dev); + tifm_eject(host->dev); } static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) @@ -762,9 +765,9 @@ static struct mmc_host_ops tifm_sd_ops = { .get_ro = tifm_sd_ro }; -static void tifm_sd_register_host(void *data) +static void tifm_sd_register_host(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); unsigned long flags; @@ -772,8 +775,7 @@ static void tifm_sd_register_host(void *data) spin_lock_irqsave(&sock->lock, flags); host->flags |= HOST_REG; PREPARE_WORK(&host->cmd_handler, - no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, - data); + no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); spin_unlock_irqrestore(&sock->lock, flags); dev_dbg(&sock->dev, "adding host\n"); mmc_add_host(mmc); @@ -799,8 +801,8 @@ static int tifm_sd_probe(struct tifm_dev *sock) host->dev = sock; host->clk_div = 61; init_waitqueue_head(&host->can_eject); - INIT_WORK(&host->cmd_handler, tifm_sd_register_host, host); - INIT_WORK(&host->abort_handler, tifm_sd_abort, host); + INIT_WORK(&host->cmd_handler, tifm_sd_register_host); + INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort); tifm_set_drvdata(sock, mmc); sock->signal_irq = tifm_sd_signal_irq; diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index d02ed51abfc..931028f672d 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -594,7 +594,7 @@ struct rtl8139_private { u32 rx_config; struct rtl_extra_stats xstats; - struct work_struct thread; + struct delayed_work thread; struct mii_if_info mii; unsigned int regs_len; @@ -636,8 +636,8 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); -static void rtl8139_thread (void *_data); -static void rtl8139_tx_timeout_task(void *_data); +static void rtl8139_thread (struct work_struct *work); +static void rtl8139_tx_timeout_task(struct work_struct *work); static const struct ethtool_ops rtl8139_ethtool_ops; /* write MMIO register, with flush */ @@ -1010,7 +1010,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); spin_lock_init (&tp->lock); spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); + INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); tp->mii.dev = dev; tp->mii.mdio_read = mdio_read; tp->mii.mdio_write = mdio_write; @@ -1596,15 +1596,16 @@ static inline void rtl8139_thread_iter (struct net_device *dev, RTL_R8 (Config1)); } -static void rtl8139_thread (void *_data) +static void rtl8139_thread (struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); + struct rtl8139_private *tp = + container_of(work, struct rtl8139_private, thread.work); + struct net_device *dev = tp->mii.dev; unsigned long thr_delay = next_tick; if (tp->watchdog_fired) { tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); + rtl8139_tx_timeout_task(work); } else if (rtnl_trylock()) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); @@ -1646,10 +1647,11 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp) /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ } -static void rtl8139_tx_timeout_task (void *_data) +static void rtl8139_tx_timeout_task (struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); + struct rtl8139_private *tp = + container_of(work, struct rtl8139_private, thread.work); + struct net_device *dev = tp->mii.dev; void __iomem *ioaddr = tp->mmio_addr; int i; u8 tmp8; @@ -1695,7 +1697,7 @@ static void rtl8139_tx_timeout (struct net_device *dev) struct rtl8139_private *tp = netdev_priv(dev); if (!tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); + INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task); schedule_delayed_work(&tp->thread, next_tick); } else tp->watchdog_fired = 1; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index fc2f1d1c7ea..5bacb7587df 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -4411,9 +4411,9 @@ bnx2_open(struct net_device *dev) } static void -bnx2_reset_task(void *data) +bnx2_reset_task(struct work_struct *work) { - struct bnx2 *bp = data; + struct bnx2 *bp = container_of(work, struct bnx2, reset_task); if (!netif_running(bp->dev)) return; @@ -5702,7 +5702,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->pdev = pdev; spin_lock_init(&bp->phy_lock); - INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); + INIT_WORK(&bp->reset_task, bnx2_reset_task); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index fd2cc13f7d9..c8126484c2b 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -4066,9 +4066,9 @@ static int cas_alloc_rxds(struct cas *cp) return 0; } -static void cas_reset_task(void *data) +static void cas_reset_task(struct work_struct *work) { - struct cas *cp = (struct cas *) data; + struct cas *cp = container_of(work, struct cas, reset_task); #if 0 int pending = atomic_read(&cp->reset_task_pending); #else @@ -5006,7 +5006,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, atomic_set(&cp->reset_task_pending_spare, 0); atomic_set(&cp->reset_task_pending_mtu, 0); #endif - INIT_WORK(&cp->reset_task, cas_reset_task, cp); + INIT_WORK(&cp->reset_task, cas_reset_task); /* Default link parameters */ if (link_mode >= 0 && link_mode <= 6) diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index b265941e137..74758d2c7af 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -279,7 +279,7 @@ struct adapter { struct petp *tp; struct port_info port[MAX_NPORTS]; - struct work_struct stats_update_task; + struct delayed_work stats_update_task; struct timer_list stats_update_timer; spinlock_t tpi_lock; diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h index 60901f25014..cf914349988 100644 --- a/drivers/net/chelsio/cphy.h +++ b/drivers/net/chelsio/cphy.h @@ -91,7 +91,7 @@ struct cphy { int state; /* Link status state machine */ adapter_t *adapter; /* associated adapter */ - struct work_struct phy_update; + struct delayed_work phy_update; u16 bmsr; int count; diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 53bec673981..de48eadddbc 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -953,10 +953,11 @@ static void t1_netpoll(struct net_device *dev) * Periodic accumulation of MAC statistics. This is used only if the MAC * does not have any other way to prevent stats counter overflow. */ -static void mac_stats_task(void *data) +static void mac_stats_task(struct work_struct *work) { int i; - struct adapter *adapter = data; + struct adapter *adapter = + container_of(work, struct adapter, stats_update_task.work); for_each_port(adapter, i) { struct port_info *p = &adapter->port[i]; @@ -977,9 +978,10 @@ static void mac_stats_task(void *data) /* * Processes elmer0 external interrupts in process context. */ -static void ext_intr_task(void *data) +static void ext_intr_task(struct work_struct *work) { - struct adapter *adapter = data; + struct adapter *adapter = + container_of(work, struct adapter, ext_intr_handler_task); t1_elmer0_ext_intr_handler(adapter); @@ -1113,9 +1115,9 @@ static int __devinit init_one(struct pci_dev *pdev, spin_lock_init(&adapter->mac_lock); INIT_WORK(&adapter->ext_intr_handler_task, - ext_intr_task, adapter); - INIT_WORK(&adapter->stats_update_task, mac_stats_task, - adapter); + ext_intr_task); + INIT_DELAYED_WORK(&adapter->stats_update_task, + mac_stats_task); pci_set_drvdata(pdev, netdev); } diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c index 0b90014d5b3..c7731b6f9de 100644 --- a/drivers/net/chelsio/my3126.c +++ b/drivers/net/chelsio/my3126.c @@ -93,9 +93,11 @@ static int my3126_interrupt_handler(struct cphy *cphy) return cphy_cause_link_change; } -static void my3216_poll(void *arg) +static void my3216_poll(struct work_struct *work) { - my3126_interrupt_handler(arg); + struct cphy *cphy = container_of(work, struct cphy, phy_update.work); + + my3126_interrupt_handler(cphy); } static int my3126_set_loopback(struct cphy *cphy, int on) @@ -171,7 +173,7 @@ static struct cphy *my3126_phy_create(adapter_t *adapter, if (cphy) cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops); - INIT_WORK(&cphy->phy_update, my3216_poll, cphy); + INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll); cphy->bmsr = 0; return (cphy); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 3a8df479cbd..03bf164f9e8 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2102,9 +2102,10 @@ static void e100_tx_timeout(struct net_device *netdev) schedule_work(&nic->tx_timeout_task); } -static void e100_tx_timeout_task(struct net_device *netdev) +static void e100_tx_timeout_task(struct work_struct *work) { - struct nic *nic = netdev_priv(netdev); + struct nic *nic = container_of(work, struct nic, tx_timeout_task); + struct net_device *netdev = nic->netdev; DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", readb(&nic->csr->scb.status)); @@ -2637,8 +2638,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->blink_timer.function = e100_blink_led; nic->blink_timer.data = (unsigned long)nic; - INIT_WORK(&nic->tx_timeout_task, - (void (*)(void *))e100_tx_timeout_task, netdev); + INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); if((err = e100_alloc(nic))) { DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 32dde0adb68..73f3a85fd23 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -190,7 +190,7 @@ void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); -static void e1000_reset_task(struct net_device *dev); +static void e1000_reset_task(struct work_struct *work); static void e1000_smartspeed(struct e1000_adapter *adapter); static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb); @@ -914,8 +914,7 @@ e1000_probe(struct pci_dev *pdev, adapter->phy_info_timer.function = &e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; - INIT_WORK(&adapter->reset_task, - (void (*)(void *))e1000_reset_task, netdev); + INIT_WORK(&adapter->reset_task, e1000_reset_task); e1000_check_options(adapter); @@ -3306,9 +3305,10 @@ e1000_tx_timeout(struct net_device *netdev) } static void -e1000_reset_task(struct net_device *netdev) +e1000_reset_task(struct work_struct *work) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, reset_task); e1000_reinit_locked(adapter); } diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 6ad69610141..83fa32f7239 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2224,11 +2224,12 @@ static int ehea_stop(struct net_device *dev) return ret; } -static void ehea_reset_port(void *data) +static void ehea_reset_port(struct work_struct *work) { int ret; - struct net_device *dev = data; - struct ehea_port *port = netdev_priv(dev); + struct ehea_port *port = + container_of(work, struct ehea_port, reset_task); + struct net_device *dev = port->netdev; port->resets++; down(&port->port_lock); @@ -2379,7 +2380,7 @@ static int ehea_setup_single_port(struct ehea_port *port, dev->tx_timeout = &ehea_tx_watchdog; dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; - INIT_WORK(&port->reset_task, ehea_reset_port, dev); + INIT_WORK(&port->reset_task, ehea_reset_port); ehea_set_ethtool_ops(dev); diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 1ed9cccd3c1..3c33d6f6a6a 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -168,8 +168,9 @@ struct baycom_state { int magic; struct pardevice *pdev; + struct net_device *dev; unsigned int work_running; - struct work_struct run_work; + struct delayed_work run_work; unsigned int modem; unsigned int bitrate; unsigned char stat; @@ -659,16 +660,18 @@ static int receive(struct net_device *dev, int cnt) #define GETTICK(x) #endif /* __i386__ */ -static void epp_bh(struct net_device *dev) +static void epp_bh(struct work_struct *work) { + struct net_device *dev; struct baycom_state *bc; struct parport *pp; unsigned char stat; unsigned char tmp[2]; unsigned int time1 = 0, time2 = 0, time3 = 0; int cnt, cnt2; - - bc = netdev_priv(dev); + + bc = container_of(work, struct baycom_state, run_work.work); + dev = bc->dev; if (!bc->work_running) return; baycom_int_freq(bc); @@ -889,7 +892,7 @@ static int epp_open(struct net_device *dev) return -EBUSY; } dev->irq = /*pp->irq*/ 0; - INIT_WORK(&bc->run_work, (void *)(void *)epp_bh, dev); + INIT_DELAYED_WORK(&bc->run_work, epp_bh); bc->work_running = 1; bc->modem = EPP_CONVENTIONAL; if (eppconfig(bc)) @@ -1213,6 +1216,7 @@ static void __init baycom_epp_dev_setup(struct net_device *dev) /* * initialize part of the baycom_state struct */ + bc->dev = dev; bc->magic = BAYCOM_MAGIC; bc->cfg.fclk = 19666600; bc->cfg.bps = 9600; diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 0f8b9afd55b..e6e721aff6f 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -252,7 +252,7 @@ static inline void z8530_isr(struct scc_info *info); static irqreturn_t scc_isr(int irq, void *dev_id); static void rx_isr(struct scc_priv *priv); static void special_condition(struct scc_priv *priv, int rc); -static void rx_bh(void *arg); +static void rx_bh(struct work_struct *); static void tx_isr(struct scc_priv *priv); static void es_isr(struct scc_priv *priv); static void tm_isr(struct scc_priv *priv); @@ -579,7 +579,7 @@ static int __init setup_adapter(int card_base, int type, int n) priv->param.clocks = TCTRxCP | RCRTxCP; priv->param.persist = 256; priv->param.dma = -1; - INIT_WORK(&priv->rx_work, rx_bh, priv); + INIT_WORK(&priv->rx_work, rx_bh); dev->priv = priv; sprintf(dev->name, "dmascc%i", 2 * n + i); dev->base_addr = card_base; @@ -1272,9 +1272,9 @@ static void special_condition(struct scc_priv *priv, int rc) } -static void rx_bh(void *arg) +static void rx_bh(struct work_struct *ugli_api) { - struct scc_priv *priv = arg; + struct scc_priv *priv = container_of(ugli_api, struct scc_priv, rx_work); int i = priv->rx_tail; int cb; unsigned long flags; diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index b32c52ed19d..f0c61f3b2a8 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -560,9 +560,9 @@ static inline int mcs_find_endpoints(struct mcs_cb *mcs, return ret; } -static void mcs_speed_work(void *arg) +static void mcs_speed_work(struct work_struct *work) { - struct mcs_cb *mcs = arg; + struct mcs_cb *mcs = container_of(work, struct mcs_cb, work); struct net_device *netdev = mcs->netdev; mcs_speed_change(mcs); @@ -927,7 +927,7 @@ static int mcs_probe(struct usb_interface *intf, irda_qos_bits_to_value(&mcs->qos); /* Speed change work initialisation*/ - INIT_WORK(&mcs->work, mcs_speed_work, mcs); + INIT_WORK(&mcs->work, mcs_speed_work); /* Override the network functions we need to use */ ndev->hard_start_xmit = mcs_hard_xmit; diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h index 9fa294a546d..2a57bc67ce3 100644 --- a/drivers/net/irda/sir-dev.h +++ b/drivers/net/irda/sir-dev.h @@ -22,7 +22,7 @@ struct sir_fsm { struct semaphore sem; - struct work_struct work; + struct delayed_work work; unsigned state, substate; int param; int result; diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 3b5854d10c1..17b0c3ab620 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -100,9 +100,9 @@ static int sirdev_tx_complete_fsm(struct sir_dev *dev) * Both must be unlocked/restarted on completion - but only on final exit. */ -static void sirdev_config_fsm(void *data) +static void sirdev_config_fsm(struct work_struct *work) { - struct sir_dev *dev = data; + struct sir_dev *dev = container_of(work, struct sir_dev, fsm.work.work); struct sir_fsm *fsm = &dev->fsm; int next_state; int ret = -1; @@ -309,8 +309,8 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par fsm->param = param; fsm->result = 0; - INIT_WORK(&fsm->work, sirdev_config_fsm, dev); - queue_work(irda_sir_wq, &fsm->work); + INIT_DELAYED_WORK(&fsm->work, sirdev_config_fsm); + queue_delayed_work(irda_sir_wq, &fsm->work, 0); return 0; } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 2284e2ce169..d6f4f185bf3 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -166,7 +166,7 @@ struct veth_msg { struct veth_lpar_connection { HvLpIndex remote_lp; - struct work_struct statemachine_wq; + struct delayed_work statemachine_wq; struct veth_msg *msgs; int num_events; struct veth_cap_data local_caps; @@ -456,7 +456,7 @@ static struct kobj_type veth_port_ktype = { static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx) { - schedule_work(&cnx->statemachine_wq); + schedule_delayed_work(&cnx->statemachine_wq, 0); } static void veth_take_cap(struct veth_lpar_connection *cnx, @@ -638,9 +638,11 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) } /* FIXME: The gotos here are a bit dubious */ -static void veth_statemachine(void *p) +static void veth_statemachine(struct work_struct *work) { - struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)p; + struct veth_lpar_connection *cnx = + container_of(work, struct veth_lpar_connection, + statemachine_wq.work); int rlp = cnx->remote_lp; int rc; @@ -827,7 +829,7 @@ static int veth_init_connection(u8 rlp) cnx->remote_lp = rlp; spin_lock_init(&cnx->lock); - INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); + INIT_DELAYED_WORK(&cnx->statemachine_wq, veth_statemachine); init_timer(&cnx->ack_timer); cnx->ack_timer.function = veth_timed_ack; diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 7b127212e62..e628126c9c4 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -106,7 +106,7 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); void ixgb_set_ethtool_ops(struct net_device *netdev); static void ixgb_tx_timeout(struct net_device *dev); -static void ixgb_tx_timeout_task(struct net_device *dev); +static void ixgb_tx_timeout_task(struct work_struct *work); static void ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); @@ -489,8 +489,7 @@ ixgb_probe(struct pci_dev *pdev, adapter->watchdog_timer.function = &ixgb_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))ixgb_tx_timeout_task, netdev); + INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task); strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) @@ -1493,9 +1492,10 @@ ixgb_tx_timeout(struct net_device *netdev) } static void -ixgb_tx_timeout_task(struct net_device *netdev) +ixgb_tx_timeout_task(struct work_struct *work) { - struct ixgb_adapter *adapter = netdev_priv(netdev); + struct ixgb_adapter *adapter = + container_of(work, struct ixgb_adapter, tx_timeout_task); adapter->tx_timeout_count++; ixgb_down(adapter, TRUE); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9997081c6da..d9f48bb04b0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -277,9 +277,11 @@ static void mv643xx_eth_tx_timeout(struct net_device *dev) * * Actual routine to reset the adapter when a timeout on Tx has occurred */ -static void mv643xx_eth_tx_timeout_task(struct net_device *dev) +static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly) { - struct mv643xx_private *mp = netdev_priv(dev); + struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private, + tx_timeout_task); + struct net_device *dev = mp->mii.dev; /* yuck */ if (!netif_running(dev)) return; @@ -1360,8 +1362,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) #endif /* Configure the timeout task */ - INIT_WORK(&mp->tx_timeout_task, - (void (*)(void *))mv643xx_eth_tx_timeout_task, dev); + INIT_WORK(&mp->tx_timeout_task, mv643xx_eth_tx_timeout_task); spin_lock_init(&mp->lock); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 36350e6db1c..38df4280238 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2615,9 +2615,10 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) * This watchdog is used to check whether the board has suffered * from a parity error and needs to be recovered. */ -static void myri10ge_watchdog(void *arg) +static void myri10ge_watchdog(struct work_struct *work) { - struct myri10ge_priv *mgp = arg; + struct myri10ge_priv *mgp = + container_of(work, struct myri10ge_priv, watchdog_work); u32 reboot; int status; u16 cmd, vendor; @@ -2887,7 +2888,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (unsigned long)mgp); SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); - INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp); + INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); status = register_netdev(netdev); if (status != 0) { dev_err(&pdev->dev, "register_netdev failed: %d\n", status); diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index d925053fe59..9c588af8ab7 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -714,6 +714,7 @@ struct netxen_adapter { spinlock_t lock; struct work_struct watchdog_task; struct work_struct tx_timeout_task; + struct net_device *netdev; struct timer_list watchdog_timer; u32 curr_window; @@ -921,7 +922,7 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, struct netxen_port *port); int netxen_nic_rx_has_work(struct netxen_adapter *adapter); int netxen_nic_tx_has_work(struct netxen_adapter *adapter); -void netxen_watchdog_task(unsigned long v); +void netxen_watchdog_task(struct work_struct *work); void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid); void netxen_process_cmd_ring(unsigned long data); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 0dca029bc3e..eae18236aef 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -710,12 +710,13 @@ static inline int netxen_nic_check_temp(struct netxen_adapter *adapter) return rv; } -void netxen_watchdog_task(unsigned long v) +void netxen_watchdog_task(struct work_struct *work) { int port_num; struct netxen_port *port; struct net_device *netdev; - struct netxen_adapter *adapter = (struct netxen_adapter *)v; + struct netxen_adapter *adapter = + container_of(work, struct netxen_adapter, watchdog_task); if (netxen_nic_check_temp(adapter)) return; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 1cb662d5bd7..df0bb36a1cf 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -64,7 +64,7 @@ static int netxen_nic_open(struct net_device *netdev); static int netxen_nic_close(struct net_device *netdev); static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); static void netxen_tx_timeout(struct net_device *netdev); -static void netxen_tx_timeout_task(struct net_device *netdev); +static void netxen_tx_timeout_task(struct work_struct *work); static void netxen_watchdog(unsigned long); static int netxen_handle_int(struct netxen_adapter *, struct net_device *); static int netxen_nic_ioctl(struct net_device *netdev, @@ -274,8 +274,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ahw.xg_linkup = 0; adapter->watchdog_timer.function = &netxen_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->watchdog_task, - (void (*)(void *))netxen_watchdog_task, adapter); + INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); adapter->ahw.pdev = pdev; adapter->proc_cmd_buf_counter = 0; pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id); @@ -379,8 +378,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_addr); } } - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))netxen_tx_timeout_task, netdev); + adapter->netdev = netdev; + INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -938,18 +937,20 @@ static void netxen_tx_timeout(struct net_device *netdev) schedule_work(&adapter->tx_timeout_task); } -static void netxen_tx_timeout_task(struct net_device *netdev) +static void netxen_tx_timeout_task(struct work_struct *work) { - struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); + struct netxen_adapter *adapter = + container_of(work, struct netxen_adapter, tx_timeout_task); + struct net_device *netdev = adapter->netdev; unsigned long flags; printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, netdev->name); - spin_lock_irqsave(&port->adapter->lock, flags); + spin_lock_irqsave(&adapter->lock, flags); netxen_nic_close(netdev); netxen_nic_open(netdev); - spin_unlock_irqrestore(&port->adapter->lock, flags); + spin_unlock_irqrestore(&adapter->lock, flags); netdev->trans_start = jiffies; netif_wake_queue(netdev); } diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index b0127c71a5b..312e0e33171 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -427,6 +427,7 @@ struct ns83820 { u8 __iomem *base; struct pci_dev *pci_dev; + struct net_device *ndev; #ifdef NS83820_VLAN_ACCEL_SUPPORT struct vlan_group *vlgrp; @@ -631,10 +632,10 @@ static void fastcall rx_refill_atomic(struct net_device *ndev) } /* REFILL */ -static inline void queue_refill(void *_dev) +static inline void queue_refill(struct work_struct *work) { - struct net_device *ndev = _dev; - struct ns83820 *dev = PRIV(ndev); + struct ns83820 *dev = container_of(work, struct ns83820, tq_refill); + struct net_device *ndev = dev->ndev; rx_refill(ndev, GFP_KERNEL); if (dev->rx_info.up) @@ -1841,6 +1842,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev = alloc_etherdev(sizeof(struct ns83820)); dev = PRIV(ndev); + dev->ndev = ndev; err = -ENOMEM; if (!dev) goto out; @@ -1853,7 +1855,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); - INIT_WORK(&dev->tq_refill, queue_refill, ndev); + INIT_WORK(&dev->tq_refill, queue_refill); tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)ndev); err = pci_enable_device(pci_dev); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 69813406782..8478dca3d8d 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -332,6 +332,7 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); */ typedef struct local_info_t { + struct net_device *dev; struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; @@ -353,7 +354,7 @@ typedef struct local_info_t { */ static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void do_tx_timeout(struct net_device *dev); -static void xirc2ps_tx_timeout_task(void *data); +static void xirc2ps_tx_timeout_task(struct work_struct *work); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -567,6 +568,7 @@ xirc2ps_probe(struct pcmcia_device *link) if (!dev) return -ENOMEM; local = netdev_priv(dev); + local->dev = dev; local->p_dev = link; link->priv = dev; @@ -591,7 +593,7 @@ xirc2ps_probe(struct pcmcia_device *link) #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev); + INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task); #endif return xirc2ps_config(link); @@ -1324,9 +1326,11 @@ xirc2ps_interrupt(int irq, void *dev_id) /*====================================================================*/ static void -xirc2ps_tx_timeout_task(void *data) +xirc2ps_tx_timeout_task(struct work_struct *work) { - struct net_device *dev = data; + local_info_t *local = + container_of(work, local_info_t, tx_timeout_task); + struct net_device *dev = local->dev; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 88237bdb525..4044bb1ada8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -397,7 +397,7 @@ out_unlock: EXPORT_SYMBOL(phy_start_aneg); -static void phy_change(void *data); +static void phy_change(struct work_struct *work); static void phy_timer(unsigned long data); /* phy_start_machine: @@ -555,7 +555,7 @@ int phy_start_interrupts(struct phy_device *phydev) { int err = 0; - INIT_WORK(&phydev->phy_queue, phy_change, phydev); + INIT_WORK(&phydev->phy_queue, phy_change); if (request_irq(phydev->irq, phy_interrupt, IRQF_SHARED, @@ -598,10 +598,11 @@ EXPORT_SYMBOL(phy_stop_interrupts); /* Scheduled by the phy_interrupt/timer to handle PHY changes */ -static void phy_change(void *data) +static void phy_change(struct work_struct *work) { int err; - struct phy_device *phydev = data; + struct phy_device *phydev = + container_of(work, struct phy_device, phy_queue); err = phy_disable_interrupts(phydev); diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 71afb274498..6bb085f5443 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -138,9 +138,9 @@ static const unsigned int net_debug = NET_DEBUG; #define PLIP_NIBBLE_WAIT 3000 /* Bottom halves */ -static void plip_kick_bh(struct net_device *dev); -static void plip_bh(struct net_device *dev); -static void plip_timer_bh(struct net_device *dev); +static void plip_kick_bh(struct work_struct *work); +static void plip_bh(struct work_struct *work); +static void plip_timer_bh(struct work_struct *work); /* Interrupt handler */ static void plip_interrupt(int irq, void *dev_id); @@ -207,9 +207,10 @@ struct plip_local { struct net_local { struct net_device_stats enet_stats; + struct net_device *dev; struct work_struct immediate; - struct work_struct deferred; - struct work_struct timer; + struct delayed_work deferred; + struct delayed_work timer; struct plip_local snd_data; struct plip_local rcv_data; struct pardevice *pardev; @@ -306,11 +307,11 @@ plip_init_netdev(struct net_device *dev) nl->nibble = PLIP_NIBBLE_WAIT; /* Initialize task queue structures */ - INIT_WORK(&nl->immediate, (void (*)(void *))plip_bh, dev); - INIT_WORK(&nl->deferred, (void (*)(void *))plip_kick_bh, dev); + INIT_WORK(&nl->immediate, plip_bh); + INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh); if (dev->irq == -1) - INIT_WORK(&nl->timer, (void (*)(void *))plip_timer_bh, dev); + INIT_DELAYED_WORK(&nl->timer, plip_timer_bh); spin_lock_init(&nl->lock); } @@ -319,9 +320,10 @@ plip_init_netdev(struct net_device *dev) This routine is kicked by do_timer(). Request `plip_bh' to be invoked. */ static void -plip_kick_bh(struct net_device *dev) +plip_kick_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = + container_of(work, struct net_local, deferred.work); if (nl->is_deferred) schedule_work(&nl->immediate); @@ -362,9 +364,9 @@ static const plip_func connection_state_table[] = /* Bottom half handler of PLIP. */ static void -plip_bh(struct net_device *dev) +plip_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = container_of(work, struct net_local, immediate); struct plip_local *snd = &nl->snd_data; struct plip_local *rcv = &nl->rcv_data; plip_func f; @@ -372,20 +374,21 @@ plip_bh(struct net_device *dev) nl->is_deferred = 0; f = connection_state_table[nl->connection]; - if ((r = (*f)(dev, nl, snd, rcv)) != OK - && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) { + if ((r = (*f)(nl->dev, nl, snd, rcv)) != OK + && (r = plip_bh_timeout_error(nl->dev, nl, snd, rcv, r)) != OK) { nl->is_deferred = 1; schedule_delayed_work(&nl->deferred, 1); } } static void -plip_timer_bh(struct net_device *dev) +plip_timer_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = + container_of(work, struct net_local, timer.work); if (!(atomic_read (&nl->kill_timer))) { - plip_interrupt (-1, dev); + plip_interrupt (-1, nl->dev); schedule_delayed_work(&nl->timer, 1); } @@ -1284,6 +1287,7 @@ static void plip_attach (struct parport *port) } nl = netdev_priv(dev); + nl->dev = dev; nl->pardev = parport_register_device(port, name, plip_preempt, plip_wakeup, plip_interrupt, 0, dev); diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index ec640f6229a..d79d141a601 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2008,7 +2008,7 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) "%s: Another function issued a reset to the " "chip. ISR value = %x.\n", ndev->name, value); } - queue_work(qdev->workqueue, &qdev->reset_work); + queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0); spin_unlock(&qdev->adapter_lock); } else if (value & ISP_IMR_DISABLE_CMPL_INT) { ql_disable_interrupts(qdev); @@ -3182,11 +3182,13 @@ static void ql3xxx_tx_timeout(struct net_device *ndev) /* * Wake up the worker to process this event. */ - queue_work(qdev->workqueue, &qdev->tx_timeout_work); + queue_delayed_work(qdev->workqueue, &qdev->tx_timeout_work, 0); } -static void ql_reset_work(struct ql3_adapter *qdev) +static void ql_reset_work(struct work_struct *work) { + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, reset_work.work); struct net_device *ndev = qdev->ndev; u32 value; struct ql_tx_buf_cb *tx_cb; @@ -3278,9 +3280,12 @@ static void ql_reset_work(struct ql3_adapter *qdev) } } -static void ql_tx_timeout_work(struct ql3_adapter *qdev) +static void ql_tx_timeout_work(struct work_struct *work) { - ql_cycle_adapter(qdev,QL_DO_RESET); + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, tx_timeout_work.work); + + ql_cycle_adapter(qdev, QL_DO_RESET); } static void ql_get_board_info(struct ql3_adapter *qdev) @@ -3459,9 +3464,8 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, netif_stop_queue(ndev); qdev->workqueue = create_singlethread_workqueue(ndev->name); - INIT_WORK(&qdev->reset_work, (void (*)(void *))ql_reset_work, qdev); - INIT_WORK(&qdev->tx_timeout_work, - (void (*)(void *))ql_tx_timeout_work, qdev); + INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work); + INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work); init_timer(&qdev->adapter_timer); qdev->adapter_timer.function = ql3xxx_timer; diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index 65da2c0bfda..ea94de7fd07 100644 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -1186,8 +1186,8 @@ struct ql3_adapter { u32 numPorts; struct net_device_stats stats; struct workqueue_struct *workqueue; - struct work_struct reset_work; - struct work_struct tx_timeout_work; + struct delayed_work reset_work; + struct delayed_work tx_timeout_work; u32 max_frame_size; }; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 45d3ca43195..85a392fab5c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -424,6 +424,7 @@ struct ring_info { struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ + struct net_device *dev; struct net_device_stats stats; /* statistics of net device */ spinlock_t lock; /* spin lock flag */ u32 msg_enable; @@ -455,7 +456,7 @@ struct rtl8169_private { void (*phy_reset_enable)(void __iomem *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); - struct work_struct task; + struct delayed_work task; unsigned wol_enabled : 1; }; @@ -1510,6 +1511,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->dev = dev; tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); /* enable device (incl. PCI PM wakeup and hotplug setup) */ @@ -1782,7 +1784,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_free_rx; - INIT_WORK(&tp->task, NULL, dev); + INIT_DELAYED_WORK(&tp->task, NULL); rtl8169_hw_start(dev); @@ -2105,11 +2107,11 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) tp->cur_tx = tp->dirty_tx = 0; } -static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *)) +static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) { struct rtl8169_private *tp = netdev_priv(dev); - PREPARE_WORK(&tp->task, task, dev); + PREPARE_DELAYED_WORK(&tp->task, task); schedule_delayed_work(&tp->task, 4); } @@ -2128,9 +2130,11 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) netif_poll_enable(dev); } -static void rtl8169_reinit_task(void *_data) +static void rtl8169_reinit_task(struct work_struct *work) { - struct net_device *dev = _data; + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, task.work); + struct net_device *dev = tp->dev; int ret; if (netif_running(dev)) { @@ -2153,10 +2157,11 @@ static void rtl8169_reinit_task(void *_data) } } -static void rtl8169_reset_task(void *_data) +static void rtl8169_reset_task(struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8169_private *tp = netdev_priv(dev); + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, task.work); + struct net_device *dev = tp->dev; if (!netif_running(dev)) return; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 33569ec9dbf..250cdbeefdf 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5872,9 +5872,9 @@ static void s2io_tasklet(unsigned long dev_addr) * Description: Sets the link status for the adapter */ -static void s2io_set_link(unsigned long data) +static void s2io_set_link(struct work_struct *work) { - nic_t *nic = (nic_t *) data; + nic_t *nic = container_of(work, nic_t, set_link_task); struct net_device *dev = nic->dev; XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64; @@ -6379,10 +6379,10 @@ static int s2io_card_up(nic_t * sp) * spin lock. */ -static void s2io_restart_nic(unsigned long data) +static void s2io_restart_nic(struct work_struct *work) { - struct net_device *dev = (struct net_device *) data; - nic_t *sp = dev->priv; + nic_t *sp = container_of(work, nic_t, rst_timer_task); + struct net_device *dev = sp->dev; s2io_card_down(sp); if (s2io_card_up(sp)) { @@ -6992,10 +6992,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->tx_timeout = &s2io_tx_watchdog; dev->watchdog_timeo = WATCH_DOG_TIMEOUT; - INIT_WORK(&sp->rst_timer_task, - (void (*)(void *)) s2io_restart_nic, dev); - INIT_WORK(&sp->set_link_task, - (void (*)(void *)) s2io_set_link, sp); + INIT_WORK(&sp->rst_timer_task, s2io_restart_nic); + INIT_WORK(&sp->set_link_task, s2io_set_link); pci_save_state(sp->pdev); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 12b719f4d00..3b0bafd273c 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -1000,7 +1000,7 @@ s2io_msix_fifo_handle(int irq, void *dev_id); static irqreturn_t s2io_isr(int irq, void *dev_id); static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag); static const struct ethtool_ops netdev_ethtool_ops; -static void s2io_set_link(unsigned long data); +static void s2io_set_link(struct work_struct *work); static int s2io_set_swapper(nic_t * sp); static void s2io_card_down(nic_t *nic); static int s2io_card_up(nic_t *nic); diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index aaba458584f..b70ed79d412 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -280,6 +280,7 @@ enum sis190_feature { struct sis190_private { void __iomem *mmio_addr; struct pci_dev *pci_dev; + struct net_device *dev; struct net_device_stats stats; spinlock_t lock; u32 rx_buf_sz; @@ -897,10 +898,11 @@ static void sis190_hw_start(struct net_device *dev) netif_start_queue(dev); } -static void sis190_phy_task(void * data) +static void sis190_phy_task(struct work_struct *work) { - struct net_device *dev = data; - struct sis190_private *tp = netdev_priv(dev); + struct sis190_private *tp = + container_of(work, struct sis190_private, phy_task); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->mmio_addr; int phy_id = tp->mii_if.phy_id; u16 val; @@ -1047,7 +1049,7 @@ static int sis190_open(struct net_device *dev) if (rc < 0) goto err_free_rx_1; - INIT_WORK(&tp->phy_task, sis190_phy_task, dev); + INIT_WORK(&tp->phy_task, sis190_phy_task); sis190_request_timer(dev); @@ -1436,6 +1438,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->dev = dev; tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT); rc = pci_enable_device(pdev); @@ -1798,7 +1801,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, sis190_init_rxfilter(dev); - INIT_WORK(&tp->phy_task, sis190_phy_task, dev); + INIT_WORK(&tp->phy_task, sis190_phy_task); dev->open = sis190_open; dev->stop = sis190_close; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5513907e839..b60f0451f6c 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1327,10 +1327,11 @@ static void xm_check_link(struct net_device *dev) * Since internal PHY is wired to a level triggered pin, can't * get an interrupt when carrier is detected. */ -static void xm_link_timer(void *arg) +static void xm_link_timer(struct work_struct *work) { - struct net_device *dev = arg; - struct skge_port *skge = netdev_priv(arg); + struct skge_port *skge = + container_of(work, struct skge_port, link_thread.work); + struct net_device *dev = skge->netdev; struct skge_hw *hw = skge->hw; int port = skge->port; @@ -3072,9 +3073,9 @@ static void skge_error_irq(struct skge_hw *hw) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(void *arg) +static void skge_extirq(struct work_struct *work) { - struct skge_hw *hw = arg; + struct skge_hw *hw = container_of(work, struct skge_hw, phy_work); int port; mutex_lock(&hw->phy_mutex); @@ -3456,7 +3457,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->port = port; /* Only used for Genesis XMAC */ - INIT_WORK(&skge->link_thread, xm_link_timer, dev); + INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer); if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; @@ -3543,7 +3544,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, hw->pdev = pdev; mutex_init(&hw->phy_mutex); - INIT_WORK(&hw->phy_work, skge_extirq, hw); + INIT_WORK(&hw->phy_work, skge_extirq); spin_lock_init(&hw->hw_lock); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 537c0aaa1db..23e5275d920 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2456,7 +2456,7 @@ struct skge_port { struct net_device_stats net_stats; - struct work_struct link_thread; + struct delayed_work link_thread; enum pause_control flow_control; enum pause_status flow_status; u8 rx_csum; diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 95b6478f55c..e62a9586fb9 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -210,6 +210,7 @@ struct smc_local { /* work queue */ struct work_struct phy_configure; + struct net_device *dev; int work_pending; spinlock_t lock; @@ -1114,10 +1115,11 @@ static void smc_phy_check_media(struct net_device *dev, int init) * of autonegotiation.) If the RPC ANEG bit is cleared, the selection * is controlled by the RPC SPEED and RPC DPLX bits. */ -static void smc_phy_configure(void *data) +static void smc_phy_configure(struct work_struct *work) { - struct net_device *dev = data; - struct smc_local *lp = netdev_priv(dev); + struct smc_local *lp = + container_of(work, struct smc_local, phy_configure); + struct net_device *dev = lp->dev; void __iomem *ioaddr = lp->base; int phyaddr = lp->mii.phy_id; int my_phy_caps; /* My PHY capabilities */ @@ -1592,7 +1594,7 @@ smc_open(struct net_device *dev) /* Configure the PHY, initialize the link state */ if (lp->phy_type != 0) - smc_phy_configure(dev); + smc_phy_configure(&lp->phy_configure); else { spin_lock_irq(&lp->lock); smc_10bt_check_media(dev, 1); @@ -1972,7 +1974,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) #endif tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev); - INIT_WORK(&lp->phy_configure, smc_phy_configure, dev); + INIT_WORK(&lp->phy_configure, smc_phy_configure); + lp->dev = dev; lp->mii.phy_id_mask = 0x1f; lp->mii.reg_num_mask = 0x1f; lp->mii.force_media = 0; @@ -2322,7 +2325,7 @@ static int smc_drv_resume(struct platform_device *dev) smc_reset(ndev); smc_enable(ndev); if (lp->phy_type != 0) - smc_phy_configure(ndev); + smc_phy_configure(&lp->phy_configure); netif_device_attach(ndev); } } diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 13e0a43e423..ebb6aa39f9c 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1939,10 +1939,11 @@ spider_net_stop(struct net_device *netdev) * called as task when tx hangs, resets interface (if interface is up) */ static void -spider_net_tx_timeout_task(void *data) +spider_net_tx_timeout_task(struct work_struct *work) { - struct net_device *netdev = data; - struct spider_net_card *card = netdev_priv(netdev); + struct spider_net_card *card = + container_of(work, struct spider_net_card, tx_timeout_task); + struct net_device *netdev = card->netdev; if (!(netdev->flags & IFF_UP)) goto out; @@ -2116,7 +2117,7 @@ spider_net_alloc_card(void) card = netdev_priv(netdev); card->netdev = netdev; card->msg_enable = SPIDER_NET_DEFAULT_MSG; - INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev); + INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task); init_waitqueue_head(&card->waitq); atomic_set(&card->tx_timeout_task_counter, 0); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index cf44e72399b..785e4a535f9 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2282,9 +2282,9 @@ static void gem_do_stop(struct net_device *dev, int wol) } } -static void gem_reset_task(void *data) +static void gem_reset_task(struct work_struct *work) { - struct gem *gp = (struct gem *) data; + struct gem *gp = container_of(work, struct gem, reset_task); mutex_lock(&gp->pm_mutex); @@ -3044,7 +3044,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->link_timer.function = gem_link_timer; gp->link_timer.data = (unsigned long) gp; - INIT_WORK(&gp->reset_task, gem_reset_task, gp); + INIT_WORK(&gp->reset_task, gem_reset_task); gp->lstate = link_down; gp->timer_ticks = 0; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c20bb998e0e..d9123c9adc1 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3654,9 +3654,9 @@ static void tg3_poll_controller(struct net_device *dev) } #endif -static void tg3_reset_task(void *_data) +static void tg3_reset_task(struct work_struct *work) { - struct tg3 *tp = _data; + struct tg3 *tp = container_of(work, struct tg3, reset_task); unsigned int restart_timer; tg3_full_lock(tp, 0); @@ -11734,7 +11734,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, #endif spin_lock_init(&tp->lock); spin_lock_init(&tp->indirect_lock); - INIT_WORK(&tp->reset_task, tg3_reset_task, tp); + INIT_WORK(&tp->reset_task, tg3_reset_task); tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index e14f5a00f65..f85f0025112 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -296,6 +296,7 @@ static void TLan_SetMulticastList( struct net_device *); static int TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd); static int TLan_probe1( struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent); static void TLan_tx_timeout( struct net_device *dev); +static void TLan_tx_timeout_work(struct work_struct *work); static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent); static u32 TLan_HandleInvalid( struct net_device *, u16 ); @@ -562,6 +563,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, priv = netdev_priv(dev); priv->pciDev = pdev; + priv->dev = dev; /* Is this a PCI device? */ if (pdev) { @@ -634,7 +636,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, /* This will be used when we get an adapter error from * within our irq handler */ - INIT_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev); + INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work); spin_lock_init(&priv->lock); @@ -1040,6 +1042,25 @@ static void TLan_tx_timeout(struct net_device *dev) } + /*************************************************************** + * TLan_tx_timeout_work + * + * Returns: nothing + * + * Params: + * work work item of device which timed out + * + **************************************************************/ + +static void TLan_tx_timeout_work(struct work_struct *work) +{ + TLanPrivateInfo *priv = + container_of(work, TLanPrivateInfo, tlan_tqueue); + + TLan_tx_timeout(priv->dev); +} + + /*************************************************************** * TLan_StartTx diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h index a44e2f2ef62..41ce0b66593 100644 --- a/drivers/net/tlan.h +++ b/drivers/net/tlan.h @@ -170,6 +170,7 @@ typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE]; typedef struct tlan_private_tag { struct net_device *nextDevice; struct pci_dev *pciDev; + struct net_device *dev; void *dmaStorage; dma_addr_t dmaStorageDMA; unsigned int dmaSize; diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index fa3a2bb105a..942b839ccc5 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -26,10 +26,11 @@ static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list of available transceivers. */ -void t21142_media_task(void *data) +void t21142_media_task(struct work_struct *work) { - struct net_device *dev = data; - struct tulip_private *tp = netdev_priv(dev); + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->base_addr; int csr12 = ioread32(ioaddr + CSR12); int next_tick = 60*HZ; diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index 066e5d6bcbd..df326fe1cc8 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -18,10 +18,11 @@ #include "tulip.h" -void tulip_media_task(void *data) +void tulip_media_task(struct work_struct *work) { - struct net_device *dev = data; - struct tulip_private *tp = netdev_priv(dev); + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->base_addr; u32 csr12 = ioread32(ioaddr + CSR12); int next_tick = 2*HZ; diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index ad107f45c7b..25f25da7691 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -44,7 +44,7 @@ struct tulip_chip_table { int valid_intrs; /* CSR7 interrupt enable settings */ int flags; void (*media_timer) (unsigned long); - void (*media_task) (void *); + work_func_t media_task; }; @@ -392,6 +392,7 @@ struct tulip_private { int csr12_shadow; int pad0; /* Used for 8-byte alignment */ struct work_struct media_work; + struct net_device *dev; }; @@ -406,7 +407,7 @@ struct eeprom_fixup { /* 21142.c */ extern u16 t21142_csr14[]; -void t21142_media_task(void *data); +void t21142_media_task(struct work_struct *work); void t21142_start_nway(struct net_device *dev); void t21142_lnk_change(struct net_device *dev, int csr5); @@ -444,7 +445,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5); void pnic_timer(unsigned long data); /* timer.c */ -void tulip_media_task(void *data); +void tulip_media_task(struct work_struct *work); void mxic_timer(unsigned long data); void comet_timer(unsigned long data); diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 0aee618f883..5a35354aa52 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1367,6 +1367,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, * it is zeroed and aligned in alloc_etherdev */ tp = netdev_priv(dev); + tp->dev = dev; tp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct tulip_rx_desc) * RX_RING_SIZE + @@ -1389,7 +1390,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->timer.data = (unsigned long)dev; tp->timer.function = tulip_tbl[tp->chip_id].media_timer; - INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task, dev); + INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); dev->base_addr = (unsigned long)ioaddr; diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 931cbdf6d79..b2a23aed442 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -125,8 +125,8 @@ static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty); static void cpc_tty_hangup(struct tty_struct *tty); -static void cpc_tty_rx_work(void *data); -static void cpc_tty_tx_work(void *data); +static void cpc_tty_rx_work(struct work_struct *work); +static void cpc_tty_tx_work(struct work_struct *work); static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len); static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx); static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char); @@ -261,8 +261,8 @@ void cpc_tty_init(pc300dev_t *pc300dev) cpc_tty->tty_minor = port + CPC_TTY_MINOR_START; cpc_tty->pc300dev = pc300dev; - INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work, (void *)cpc_tty); - INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work, (void *)port); + INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work); + INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work); cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL; @@ -659,21 +659,23 @@ static void cpc_tty_hangup(struct tty_struct *tty) * o call the line disc. read * o free memory */ -static void cpc_tty_rx_work(void * data) +static void cpc_tty_rx_work(struct work_struct *work) { + st_cpc_tty_area *cpc_tty; unsigned long port; int i, j; - st_cpc_tty_area *cpc_tty; volatile st_cpc_rx_buf *buf; char flags=0,flg_rx=1; struct tty_ldisc *ld; if (cpc_tty_cnt == 0) return; - for (i=0; (i < 4) && flg_rx ; i++) { flg_rx = 0; - port = (unsigned long)data; + + cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work); + port = cpc_tty - cpc_tty_area; + for (j=0; j < CPC_TTY_NPORTS; j++) { cpc_tty = &cpc_tty_area[port]; @@ -882,9 +884,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev) * o if need call line discipline wakeup * o call wake_up_interruptible */ -static void cpc_tty_tx_work(void *data) +static void cpc_tty_tx_work(struct work_struct *work) { - st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) data; + st_cpc_tty_area *cpc_tty = + container_of(work, st_cpc_tty_area, tty_tx_work); struct tty_struct *tty; CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 94dfb92fab5..8286678513b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -819,7 +819,7 @@ struct bcm43xx_private { struct tasklet_struct isr_tasklet; /* Periodic tasks */ - struct work_struct periodic_work; + struct delayed_work periodic_work; unsigned int periodic_state; struct work_struct restart_work; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 5b3c27359a1..2ec2e5afce6 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3215,9 +3215,10 @@ static void do_periodic_work(struct bcm43xx_private *bcm) schedule_delayed_work(&bcm->periodic_work, HZ * 15); } -static void bcm43xx_periodic_work_handler(void *d) +static void bcm43xx_periodic_work_handler(struct work_struct *work) { - struct bcm43xx_private *bcm = d; + struct bcm43xx_private *bcm = + container_of(work, struct bcm43xx_private, periodic_work.work); struct net_device *net_dev = bcm->net_dev; unsigned long flags; u32 savedirqs = 0; @@ -3279,11 +3280,11 @@ void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - struct work_struct *work = &(bcm->periodic_work); + struct delayed_work *work = &bcm->periodic_work; assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - INIT_WORK(work, bcm43xx_periodic_work_handler, bcm); - schedule_work(work); + INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler); + schedule_delayed_work(work, 0); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3635,7 +3636,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_periodic_tasks_setup(bcm); /*FIXME: This should be handled by softmac instead. */ - schedule_work(&bcm->softmac->associnfo.work); + schedule_delayed_work(&bcm->softmac->associnfo.work, 0); out: mutex_unlock(&(bcm)->mutex); @@ -4182,9 +4183,10 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) /* Hard-reset the chip. Do not call this directly. * Use bcm43xx_controller_restart() */ -static void bcm43xx_chip_reset(void *_bcm) +static void bcm43xx_chip_reset(struct work_struct *work) { - struct bcm43xx_private *bcm = _bcm; + struct bcm43xx_private *bcm = + container_of(work, struct bcm43xx_private, restart_work); struct bcm43xx_phyinfo *phy; int err = -ENODEV; @@ -4211,7 +4213,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) return; printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); - INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); + INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset); schedule_work(&bcm->restart_work); } diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h index e663518bd57..e89c890d16f 100644 --- a/drivers/net/wireless/hostap/hostap.h +++ b/drivers/net/wireless/hostap/hostap.h @@ -35,7 +35,7 @@ int hostap_80211_get_hdrlen(u16 fc); struct net_device_stats *hostap_get_stats(struct net_device *dev); void hostap_setup_dev(struct net_device *dev, local_info_t *local, int main_dev); -void hostap_set_multicast_list_queue(void *data); +void hostap_set_multicast_list_queue(struct work_struct *work); int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked); int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked); void hostap_cleanup(local_info_t *local); diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index ba13125024c..08bc57a4b89 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -49,10 +49,10 @@ MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs " static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta); static void hostap_event_expired_sta(struct net_device *dev, struct sta_info *sta); -static void handle_add_proc_queue(void *data); +static void handle_add_proc_queue(struct work_struct *work); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(void *data); +static void handle_wds_oper_queue(struct work_struct *work); static void prism2_send_mgmt(struct net_device *dev, u16 type_subtype, char *body, int body_len, u8 *addr, u16 tx_cb_idx); @@ -807,7 +807,7 @@ void hostap_init_data(local_info_t *local) INIT_LIST_HEAD(&ap->sta_list); /* Initialize task queue structure for AP management */ - INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap); + INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue); ap->tx_callback_idx = hostap_tx_callback_register(local, hostap_ap_tx_cb, ap); @@ -815,7 +815,7 @@ void hostap_init_data(local_info_t *local) printk(KERN_WARNING "%s: failed to register TX callback for " "AP\n", local->dev->name); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local); + INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue); ap->tx_callback_auth = hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap); @@ -1062,9 +1062,10 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off, } -static void handle_add_proc_queue(void *data) +static void handle_add_proc_queue(struct work_struct *work) { - struct ap_data *ap = (struct ap_data *) data; + struct ap_data *ap = container_of(work, struct ap_data, + add_sta_proc_queue); struct sta_info *sta; char name[20]; struct add_sta_proc_data *entry, *prev; @@ -1952,9 +1953,11 @@ static void handle_pspoll(local_info_t *local, #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(void *data) +static void handle_wds_oper_queue(struct work_struct *work) { - local_info_t *local = data; + struct ap_data *ap = container_of(work, struct ap_data, + wds_oper_queue); + local_info_t *local = ap->local; struct wds_oper_data *entry, *prev; spin_lock_bh(&local->lock); diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index ed00ebb6e7f..c19e68636a1 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -1645,9 +1645,9 @@ static void prism2_schedule_reset(local_info_t *local) /* Called only as scheduled task after noticing card timeout in interrupt * context */ -static void handle_reset_queue(void *data) +static void handle_reset_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, reset_queue); printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name); prism2_hw_reset(local->dev); @@ -2896,9 +2896,10 @@ static void hostap_passive_scan(unsigned long data) /* Called only as a scheduled task when communications quality values should * be updated. */ -static void handle_comms_qual_update(void *data) +static void handle_comms_qual_update(struct work_struct *work) { - local_info_t *local = data; + local_info_t *local = + container_of(work, local_info_t, comms_qual_update); prism2_update_comms_qual(local->dev); } @@ -3050,9 +3051,9 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set) } -static void handle_set_tim_queue(void *data) +static void handle_set_tim_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, set_tim_queue); struct set_tim_data *entry; u16 val; @@ -3209,15 +3210,15 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, local->scan_channel_mask = 0xffff; /* Initialize task queue structures */ - INIT_WORK(&local->reset_queue, handle_reset_queue, local); + INIT_WORK(&local->reset_queue, handle_reset_queue); INIT_WORK(&local->set_multicast_list_queue, - hostap_set_multicast_list_queue, local->dev); + hostap_set_multicast_list_queue); - INIT_WORK(&local->set_tim_queue, handle_set_tim_queue, local); + INIT_WORK(&local->set_tim_queue, handle_set_tim_queue); INIT_LIST_HEAD(&local->set_tim_list); spin_lock_init(&local->set_tim_lock); - INIT_WORK(&local->comms_qual_update, handle_comms_qual_update, local); + INIT_WORK(&local->comms_qual_update, handle_comms_qual_update); /* Initialize tasklets for handling hardware IRQ related operations * outside hw IRQ handler */ diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c index 50f72d831cf..5fd2b1ad7f5 100644 --- a/drivers/net/wireless/hostap/hostap_info.c +++ b/drivers/net/wireless/hostap/hostap_info.c @@ -474,9 +474,9 @@ static void handle_info_queue_scanresults(local_info_t *local) /* Called only as scheduled task after receiving info frames (used to avoid * pending too much time in HW IRQ handler). */ -static void handle_info_queue(void *data) +static void handle_info_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, info_queue); if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info)) @@ -493,7 +493,7 @@ void hostap_info_init(local_info_t *local) { skb_queue_head_init(&local->info_list); #ifndef PRISM2_NO_STATION_MODES - INIT_WORK(&local->info_queue, handle_info_queue, local); + INIT_WORK(&local->info_queue, handle_info_queue); #endif /* PRISM2_NO_STATION_MODES */ } diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 53374fcba77..0796be9d9e7 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -767,14 +767,14 @@ static int prism2_set_mac_address(struct net_device *dev, void *p) /* TODO: to be further implemented as soon as Prism2 fully supports * GroupAddresses and correct documentation is available */ -void hostap_set_multicast_list_queue(void *data) +void hostap_set_multicast_list_queue(struct work_struct *work) { - struct net_device *dev = (struct net_device *) data; + local_info_t *local = + container_of(work, local_info_t, set_multicast_list_queue); + struct net_device *dev = local->dev; struct hostap_interface *iface; - local_info_t *local; iface = netdev_priv(dev); - local = iface->local; if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, local->is_promisc)) { printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 79607b8b877..1bcd352a813 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -316,7 +316,7 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw); static int ipw2100_ucode_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw); -static void ipw2100_wx_event_work(struct ipw2100_priv *priv); +static void ipw2100_wx_event_work(struct work_struct *work); static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev); static struct iw_handler_def ipw2100_wx_handler_def; @@ -679,7 +679,8 @@ static void schedule_reset(struct ipw2100_priv *priv) queue_delayed_work(priv->workqueue, &priv->reset_work, priv->reset_backoff * HZ); else - queue_work(priv->workqueue, &priv->reset_work); + queue_delayed_work(priv->workqueue, &priv->reset_work, + 0); if (priv->reset_backoff < MAX_RESET_BACKOFF) priv->reset_backoff++; @@ -1873,8 +1874,10 @@ static void ipw2100_down(struct ipw2100_priv *priv) netif_stop_queue(priv->net_dev); } -static void ipw2100_reset_adapter(struct ipw2100_priv *priv) +static void ipw2100_reset_adapter(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, reset_work.work); unsigned long flags; union iwreq_data wrqu = { .ap_addr = { @@ -2071,9 +2074,9 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) return; if (priv->status & STATUS_SECURITY_UPDATED) - queue_work(priv->workqueue, &priv->security_work); + queue_delayed_work(priv->workqueue, &priv->security_work, 0); - queue_work(priv->workqueue, &priv->wx_event_work); + queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0); } static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) @@ -5524,8 +5527,11 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) return err; } -static void ipw2100_security_work(struct ipw2100_priv *priv) +static void ipw2100_security_work(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, security_work.work); + /* If we happen to have reconnected before we get a chance to * process this, then update the security settings--which causes * a disassociation to occur */ @@ -5748,7 +5754,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p) priv->reset_backoff = 0; mutex_unlock(&priv->action_mutex); - ipw2100_reset_adapter(priv); + ipw2100_reset_adapter(&priv->reset_work.work); return 0; done: @@ -5910,9 +5916,10 @@ static const struct ethtool_ops ipw2100_ethtool_ops = { .get_drvinfo = ipw_ethtool_get_drvinfo, }; -static void ipw2100_hang_check(void *adapter) +static void ipw2100_hang_check(struct work_struct *work) { - struct ipw2100_priv *priv = adapter; + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, hang_check.work); unsigned long flags; u32 rtc = 0xa5a5a5a5; u32 len = sizeof(rtc); @@ -5952,9 +5959,10 @@ static void ipw2100_hang_check(void *adapter) spin_unlock_irqrestore(&priv->low_lock, flags); } -static void ipw2100_rf_kill(void *adapter) +static void ipw2100_rf_kill(struct work_struct *work) { - struct ipw2100_priv *priv = adapter; + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, rf_kill.work); unsigned long flags; spin_lock_irqsave(&priv->low_lock, flags); @@ -6103,14 +6111,11 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->workqueue = create_workqueue(DRV_NAME); - INIT_WORK(&priv->reset_work, - (void (*)(void *))ipw2100_reset_adapter, priv); - INIT_WORK(&priv->security_work, - (void (*)(void *))ipw2100_security_work, priv); - INIT_WORK(&priv->wx_event_work, - (void (*)(void *))ipw2100_wx_event_work, priv); - INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv); - INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv); + INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter); + INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work); + INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); + INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); + INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); @@ -8281,8 +8286,10 @@ static struct iw_handler_def ipw2100_wx_handler_def = { .get_wireless_stats = ipw2100_wx_wireless_stats, }; -static void ipw2100_wx_event_work(struct ipw2100_priv *priv) +static void ipw2100_wx_event_work(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, wx_event_work.work); union iwreq_data wrqu; int len = ETH_ALEN; diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 55b7227198d..de7d384d38a 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -583,11 +583,11 @@ struct ipw2100_priv { struct tasklet_struct irq_tasklet; struct workqueue_struct *workqueue; - struct work_struct reset_work; - struct work_struct security_work; - struct work_struct wx_event_work; - struct work_struct hang_check; - struct work_struct rf_kill; + struct delayed_work reset_work; + struct delayed_work security_work; + struct delayed_work wx_event_work; + struct delayed_work hang_check; + struct delayed_work rf_kill; u32 interrupts; int tx_interrupts; diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index c692d01a76c..e82e56bb85e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -187,9 +187,9 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *); static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *); static void ipw_rx_queue_replenish(void *); static int ipw_up(struct ipw_priv *); -static void ipw_bg_up(void *); +static void ipw_bg_up(struct work_struct *work); static void ipw_down(struct ipw_priv *); -static void ipw_bg_down(void *); +static void ipw_bg_down(struct work_struct *work); static int ipw_config(struct ipw_priv *); static int init_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates *prates); @@ -862,11 +862,12 @@ static void ipw_led_link_on(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_link_on(void *data) +static void ipw_bg_led_link_on(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_link_on.work); mutex_lock(&priv->mutex); - ipw_led_link_on(data); + ipw_led_link_on(priv); mutex_unlock(&priv->mutex); } @@ -906,11 +907,12 @@ static void ipw_led_link_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_link_off(void *data) +static void ipw_bg_led_link_off(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_link_off.work); mutex_lock(&priv->mutex); - ipw_led_link_off(data); + ipw_led_link_off(priv); mutex_unlock(&priv->mutex); } @@ -985,11 +987,12 @@ static void ipw_led_activity_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_activity_off(void *data) +static void ipw_bg_led_activity_off(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_act_off.work); mutex_lock(&priv->mutex); - ipw_led_activity_off(data); + ipw_led_activity_off(priv); mutex_unlock(&priv->mutex); } @@ -2228,11 +2231,12 @@ static void ipw_adapter_restart(void *adapter) } } -static void ipw_bg_adapter_restart(void *data) +static void ipw_bg_adapter_restart(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, adapter_restart); mutex_lock(&priv->mutex); - ipw_adapter_restart(data); + ipw_adapter_restart(priv); mutex_unlock(&priv->mutex); } @@ -2249,11 +2253,12 @@ static void ipw_scan_check(void *data) } } -static void ipw_bg_scan_check(void *data) +static void ipw_bg_scan_check(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, scan_check.work); mutex_lock(&priv->mutex); - ipw_scan_check(data); + ipw_scan_check(priv); mutex_unlock(&priv->mutex); } @@ -3831,17 +3836,19 @@ static int ipw_disassociate(void *data) return 1; } -static void ipw_bg_disassociate(void *data) +static void ipw_bg_disassociate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, disassociate); mutex_lock(&priv->mutex); - ipw_disassociate(data); + ipw_disassociate(priv); mutex_unlock(&priv->mutex); } -static void ipw_system_config(void *data) +static void ipw_system_config(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, system_config); #ifdef CONFIG_IPW2200_PROMISCUOUS if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { @@ -4208,11 +4215,12 @@ static void ipw_gather_stats(struct ipw_priv *priv) IPW_STATS_INTERVAL); } -static void ipw_bg_gather_stats(void *data) +static void ipw_bg_gather_stats(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, gather_stats.work); mutex_lock(&priv->mutex); - ipw_gather_stats(data); + ipw_gather_stats(priv); mutex_unlock(&priv->mutex); } @@ -4268,8 +4276,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, if (!(priv->status & STATUS_ROAMING)) { priv->status |= STATUS_ROAMING; if (!(priv->status & STATUS_SCANNING)) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return; } @@ -4607,8 +4615,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { priv->status |= STATUS_SCAN_FORCED; - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); break; } priv->status &= ~STATUS_SCAN_FORCED; @@ -4631,8 +4639,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, /* Don't schedule if we aborted the scan */ priv->status &= ~STATUS_ROAMING; } else if (priv->status & STATUS_SCAN_PENDING) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); else if (priv->config & CFG_BACKGROUND_SCAN && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, @@ -5055,11 +5063,12 @@ static void ipw_rx_queue_replenish(void *data) ipw_rx_queue_restock(priv); } -static void ipw_bg_rx_queue_replenish(void *data) +static void ipw_bg_rx_queue_replenish(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, rx_replenish); mutex_lock(&priv->mutex); - ipw_rx_queue_replenish(data); + ipw_rx_queue_replenish(priv); mutex_unlock(&priv->mutex); } @@ -5489,9 +5498,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, return 1; } -static void ipw_merge_adhoc_network(void *data) +static void ipw_merge_adhoc_network(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, merge_networks); struct ieee80211_network *network = NULL; struct ipw_network_match match = { .network = priv->assoc_network @@ -5948,11 +5958,12 @@ static void ipw_adhoc_check(void *data) priv->assoc_request.beacon_interval); } -static void ipw_bg_adhoc_check(void *data) +static void ipw_bg_adhoc_check(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, adhoc_check.work); mutex_lock(&priv->mutex); - ipw_adhoc_check(data); + ipw_adhoc_check(priv); mutex_unlock(&priv->mutex); } @@ -6299,19 +6310,26 @@ done: return err; } -static int ipw_request_passive_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); +static void ipw_request_passive_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_passive_scan); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); } -static int ipw_request_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); +static void ipw_request_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); } -static void ipw_bg_abort_scan(void *data) +static void ipw_bg_abort_scan(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, abort_scan); mutex_lock(&priv->mutex); - ipw_abort_scan(data); + ipw_abort_scan(priv); mutex_unlock(&priv->mutex); } @@ -7084,9 +7102,10 @@ static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, /* * background support to run QoS activate functionality */ -static void ipw_bg_qos_activate(void *data) +static void ipw_bg_qos_activate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, qos_activate); if (priv == NULL) return; @@ -7394,11 +7413,12 @@ static void ipw_roam(void *data) priv->status &= ~STATUS_ROAMING; } -static void ipw_bg_roam(void *data) +static void ipw_bg_roam(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, roam); mutex_lock(&priv->mutex); - ipw_roam(data); + ipw_roam(priv); mutex_unlock(&priv->mutex); } @@ -7479,8 +7499,8 @@ static int ipw_associate(void *data) &priv->request_scan, SCAN_INTERVAL); else - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return 0; @@ -7491,11 +7511,12 @@ static int ipw_associate(void *data) return 1; } -static void ipw_bg_associate(void *data) +static void ipw_bg_associate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, associate); mutex_lock(&priv->mutex); - ipw_associate(data); + ipw_associate(priv); mutex_unlock(&priv->mutex); } @@ -9410,7 +9431,7 @@ static int ipw_wx_set_scan(struct net_device *dev, IPW_DEBUG_WX("Start scan\n"); - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); return 0; } @@ -10547,11 +10568,12 @@ static void ipw_rf_kill(void *adapter) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_rf_kill(void *data) +static void ipw_bg_rf_kill(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, rf_kill.work); mutex_lock(&priv->mutex); - ipw_rf_kill(data); + ipw_rf_kill(priv); mutex_unlock(&priv->mutex); } @@ -10582,11 +10604,12 @@ static void ipw_link_up(struct ipw_priv *priv) queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); } -static void ipw_bg_link_up(void *data) +static void ipw_bg_link_up(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, link_up); mutex_lock(&priv->mutex); - ipw_link_up(data); + ipw_link_up(priv); mutex_unlock(&priv->mutex); } @@ -10606,15 +10629,16 @@ static void ipw_link_down(struct ipw_priv *priv) if (!(priv->status & STATUS_EXIT_PENDING)) { /* Queue up another scan... */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); } } -static void ipw_bg_link_down(void *data) +static void ipw_bg_link_down(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, link_down); mutex_lock(&priv->mutex); - ipw_link_down(data); + ipw_link_down(priv); mutex_unlock(&priv->mutex); } @@ -10626,38 +10650,30 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) init_waitqueue_head(&priv->wait_command_queue); init_waitqueue_head(&priv->wait_state); - INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv); - INIT_WORK(&priv->associate, ipw_bg_associate, priv); - INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv); - INIT_WORK(&priv->system_config, ipw_system_config, priv); - INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv); - INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv); - INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv); - INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); - INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); - INIT_WORK(&priv->request_scan, - (void (*)(void *))ipw_request_scan, priv); - INIT_WORK(&priv->request_passive_scan, - (void (*)(void *))ipw_request_passive_scan, priv); - INIT_WORK(&priv->gather_stats, - (void (*)(void *))ipw_bg_gather_stats, priv); - INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); - INIT_WORK(&priv->roam, ipw_bg_roam, priv); - INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv); - INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv); - INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv); - INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on, - priv); - INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off, - priv); - INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off, - priv); - INIT_WORK(&priv->merge_networks, - (void (*)(void *))ipw_merge_adhoc_network, priv); + INIT_DELAYED_WORK(&priv->adhoc_check, ipw_bg_adhoc_check); + INIT_WORK(&priv->associate, ipw_bg_associate); + INIT_WORK(&priv->disassociate, ipw_bg_disassociate); + INIT_WORK(&priv->system_config, ipw_system_config); + INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish); + INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart); + INIT_DELAYED_WORK(&priv->rf_kill, ipw_bg_rf_kill); + INIT_WORK(&priv->up, ipw_bg_up); + INIT_WORK(&priv->down, ipw_bg_down); + INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); + INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); + INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); + INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); + INIT_WORK(&priv->roam, ipw_bg_roam); + INIT_DELAYED_WORK(&priv->scan_check, ipw_bg_scan_check); + INIT_WORK(&priv->link_up, ipw_bg_link_up); + INIT_WORK(&priv->link_down, ipw_bg_link_down); + INIT_DELAYED_WORK(&priv->led_link_on, ipw_bg_led_link_on); + INIT_DELAYED_WORK(&priv->led_link_off, ipw_bg_led_link_off); + INIT_DELAYED_WORK(&priv->led_act_off, ipw_bg_led_activity_off); + INIT_WORK(&priv->merge_networks, ipw_merge_adhoc_network); #ifdef CONFIG_IPW2200_QOS - INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, - priv); + INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate); #endif /* CONFIG_IPW2200_QOS */ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) @@ -11190,7 +11206,8 @@ static int ipw_up(struct ipw_priv *priv) /* If configure to try and auto-associate, kick * off a scan. */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); return 0; } @@ -11211,11 +11228,12 @@ static int ipw_up(struct ipw_priv *priv) return -EIO; } -static void ipw_bg_up(void *data) +static void ipw_bg_up(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, up); mutex_lock(&priv->mutex); - ipw_up(data); + ipw_up(priv); mutex_unlock(&priv->mutex); } @@ -11282,11 +11300,12 @@ static void ipw_down(struct ipw_priv *priv) ipw_led_radio_off(priv); } -static void ipw_bg_down(void *data) +static void ipw_bg_down(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, down); mutex_lock(&priv->mutex); - ipw_down(data); + ipw_down(priv); mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index dad5eedefbf..626a240a87d 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1290,21 +1290,21 @@ struct ipw_priv { struct workqueue_struct *workqueue; - struct work_struct adhoc_check; + struct delayed_work adhoc_check; struct work_struct associate; struct work_struct disassociate; struct work_struct system_config; struct work_struct rx_replenish; - struct work_struct request_scan; + struct delayed_work request_scan; struct work_struct request_passive_scan; struct work_struct adapter_restart; - struct work_struct rf_kill; + struct delayed_work rf_kill; struct work_struct up; struct work_struct down; - struct work_struct gather_stats; + struct delayed_work gather_stats; struct work_struct abort_scan; struct work_struct roam; - struct work_struct scan_check; + struct delayed_work scan_check; struct work_struct link_up; struct work_struct link_down; @@ -1319,9 +1319,9 @@ struct ipw_priv { u32 led_ofdm_on; u32 led_ofdm_off; - struct work_struct led_link_on; - struct work_struct led_link_off; - struct work_struct led_act_off; + struct delayed_work led_link_on; + struct delayed_work led_link_off; + struct delayed_work led_act_off; struct work_struct merge_networks; struct ipw_cmd_log *cmdlog; diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 336cabac13b..936c888e03e 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -980,9 +980,11 @@ static void print_linkstatus(struct net_device *dev, u16 status) } /* Search scan results for requested BSSID, join it if found */ -static void orinoco_join_ap(struct net_device *dev) +static void orinoco_join_ap(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, join_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; int err; unsigned long flags; @@ -1055,9 +1057,11 @@ static void orinoco_join_ap(struct net_device *dev) } /* Send new BSSID to userspace */ -static void orinoco_send_wevents(struct net_device *dev) +static void orinoco_send_wevents(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, wevent_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; union iwreq_data wrqu; int err; @@ -1864,9 +1868,11 @@ __orinoco_set_multicast_list(struct net_device *dev) /* This must be called from user context, without locks held - use * schedule_work() */ -static void orinoco_reset(struct net_device *dev) +static void orinoco_reset(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, reset_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; int err; unsigned long flags; @@ -2434,9 +2440,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, priv->hw_unavailable = 1; /* orinoco_init() must clear this * before anything else touches the * hardware */ - INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); - INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); - INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); + INIT_WORK(&priv->reset_work, orinoco_reset); + INIT_WORK(&priv->join_work, orinoco_join_ap); + INIT_WORK(&priv->wevent_work, orinoco_send_wevents); netif_carrier_off(dev); priv->last_linkstatus = 0xffff; @@ -3608,7 +3614,7 @@ static int orinoco_ioctl_reset(struct net_device *dev, printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); /* Firmware reset */ - orinoco_reset(dev); + orinoco_reset(&priv->reset_work); } else { printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); @@ -4154,7 +4160,7 @@ static int orinoco_ioctl_commit(struct net_device *dev, return 0; if (priv->broken_disableport) { - orinoco_reset(dev); + orinoco_reset(&priv->reset_work); return 0; } diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 4a20e45de3c..a87eb51886c 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -157,8 +157,9 @@ prism54_mib_init(islpci_private *priv) * schedule_work(), thus we can as well use sleeping semaphore * locking */ void -prism54_update_stats(islpci_private *priv) +prism54_update_stats(struct work_struct *work) { + islpci_private *priv = container_of(work, islpci_private, stats_work); char *data; int j; struct obj_bss bss, *bss2; @@ -2493,9 +2494,10 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, * interrupt context, no locks held. */ void -prism54_process_trap(void *data) +prism54_process_trap(struct work_struct *work) { - struct islpci_mgmtframe *frame = data; + struct islpci_mgmtframe *frame = + container_of(work, struct islpci_mgmtframe, ws); struct net_device *ndev = frame->ndev; enum oid_num_t n = mgt_oidtonum(frame->header->oid); diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index e8183d30c52..bcfbfb9281d 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h @@ -31,12 +31,12 @@ void prism54_mib_init(islpci_private *); struct iw_statistics *prism54_get_wireless_stats(struct net_device *); -void prism54_update_stats(islpci_private *); +void prism54_update_stats(struct work_struct *); void prism54_acl_init(struct islpci_acl *); void prism54_acl_clean(struct islpci_acl *); -void prism54_process_trap(void *); +void prism54_process_trap(struct work_struct *); void prism54_wpa_bss_ie_init(islpci_private *priv); void prism54_wpa_bss_ie_clean(islpci_private *priv); diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 1e0603ca436..f057fd9fcd7 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -860,11 +860,10 @@ islpci_setup(struct pci_dev *pdev) priv->state_off = 1; /* initialize workqueue's */ - INIT_WORK(&priv->stats_work, - (void (*)(void *)) prism54_update_stats, priv); + INIT_WORK(&priv->stats_work, prism54_update_stats); priv->stats_timestamp = 0; - INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv); + INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake); priv->reset_task_pending = 0; /* allocate various memory areas */ diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 676d83813dc..b1122912ee2 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -480,9 +480,9 @@ islpci_eth_receive(islpci_private *priv) } void -islpci_do_reset_and_wake(void *data) +islpci_do_reset_and_wake(struct work_struct *work) { - islpci_private *priv = data; + islpci_private *priv = container_of(work, islpci_private, reset_task); islpci_reset(priv, 1); priv->reset_task_pending = 0; diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h index 26789454067..5bf820defbd 100644 --- a/drivers/net/wireless/prism54/islpci_eth.h +++ b/drivers/net/wireless/prism54/islpci_eth.h @@ -67,6 +67,6 @@ void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *); int islpci_eth_transmit(struct sk_buff *, struct net_device *); int islpci_eth_receive(islpci_private *); void islpci_eth_tx_timeout(struct net_device *); -void islpci_do_reset_and_wake(void *data); +void islpci_do_reset_and_wake(struct work_struct *); #endif /* _ISL_GEN_H */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 036a875054c..2246f7930b4 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -386,7 +386,7 @@ islpci_mgt_receive(struct net_device *ndev) /* Create work to handle trap out of interrupt * context. */ - INIT_WORK(&frame->ws, prism54_process_trap, frame); + INIT_WORK(&frame->ws, prism54_process_trap); schedule_work(&frame->ws); } else { diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 2696f95b927..f1573a9c233 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -32,8 +32,8 @@ static void ieee_init(struct ieee80211_device *ieee); static void softmac_init(struct ieee80211softmac_device *sm); -static void set_rts_cts_work(void *d); -static void set_basic_rates_work(void *d); +static void set_rts_cts_work(struct work_struct *work); +static void set_basic_rates_work(struct work_struct *work); static void housekeeping_init(struct zd_mac *mac); static void housekeeping_enable(struct zd_mac *mac); @@ -48,8 +48,8 @@ int zd_mac_init(struct zd_mac *mac, memset(mac, 0, sizeof(*mac)); spin_lock_init(&mac->lock); mac->netdev = netdev; - INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac); - INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac); + INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work); + INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work); ieee_init(ieee); softmac_init(ieee80211_priv(netdev)); @@ -366,9 +366,10 @@ static void try_enable_tx(struct zd_mac *mac) spin_unlock_irqrestore(&mac->lock, flags); } -static void set_rts_cts_work(void *d) +static void set_rts_cts_work(struct work_struct *work) { - struct zd_mac *mac = d; + struct zd_mac *mac = + container_of(work, struct zd_mac, set_rts_cts_work.work); unsigned long flags; u8 rts_rate; unsigned int short_preamble; @@ -387,9 +388,10 @@ static void set_rts_cts_work(void *d) try_enable_tx(mac); } -static void set_basic_rates_work(void *d) +static void set_basic_rates_work(struct work_struct *work) { - struct zd_mac *mac = d; + struct zd_mac *mac = + container_of(work, struct zd_mac, set_basic_rates_work.work); unsigned long flags; u16 basic_rates; @@ -467,12 +469,13 @@ static void bssinfo_change(struct net_device *netdev, u32 changes) if (need_set_rts_cts && !mac->updating_rts_rate) { mac->updating_rts_rate = 1; netif_stop_queue(mac->netdev); - queue_work(zd_workqueue, &mac->set_rts_cts_work); + queue_delayed_work(zd_workqueue, &mac->set_rts_cts_work, 0); } if (need_set_rates && !mac->updating_basic_rates) { mac->updating_basic_rates = 1; netif_stop_queue(mac->netdev); - queue_work(zd_workqueue, &mac->set_basic_rates_work); + queue_delayed_work(zd_workqueue, &mac->set_basic_rates_work, + 0); } spin_unlock_irqrestore(&mac->lock, flags); } @@ -1182,9 +1185,10 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) #define LINK_LED_WORK_DELAY HZ -static void link_led_handler(void *p) +static void link_led_handler(struct work_struct *work) { - struct zd_mac *mac = p; + struct zd_mac *mac = + container_of(work, struct zd_mac, housekeeping.link_led_work.work); struct zd_chip *chip = &mac->chip; struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev); int is_associated; @@ -1205,7 +1209,7 @@ static void link_led_handler(void *p) static void housekeeping_init(struct zd_mac *mac) { - INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac); + INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler); } static void housekeeping_enable(struct zd_mac *mac) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 5dcfb251f02..d4e8b870409 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -119,7 +119,7 @@ struct rx_status { #define ZD_RX_ERROR 0x80 struct housekeeping { - struct work_struct link_led_work; + struct delayed_work link_led_work; }; #define ZD_MAC_STATS_BUFFER_SIZE 16 @@ -133,8 +133,8 @@ struct zd_mac { struct iw_statistics iw_stats; struct housekeeping housekeeping; - struct work_struct set_rts_cts_work; - struct work_struct set_basic_rates_work; + struct delayed_work set_rts_cts_work; + struct delayed_work set_basic_rates_work; unsigned int stats_count; u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index fc4bc9b94c7..a83c3db7d18 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -29,7 +29,7 @@ struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned; -static void wq_sync_buffer(void *); +static void wq_sync_buffer(struct work_struct *work); #define DEFAULT_TIMER_EXPIRE (HZ / 10) static int work_enabled; @@ -65,7 +65,7 @@ int alloc_cpu_buffers(void) b->sample_received = 0; b->sample_lost_overflow = 0; b->cpu = i; - INIT_WORK(&b->work, wq_sync_buffer, b); + INIT_DELAYED_WORK(&b->work, wq_sync_buffer); } return 0; @@ -282,9 +282,10 @@ void oprofile_add_trace(unsigned long pc) * By using schedule_delayed_work_on and then schedule_delayed_work * we guarantee this will stay on the correct cpu */ -static void wq_sync_buffer(void * data) +static void wq_sync_buffer(struct work_struct *work) { - struct oprofile_cpu_buffer * b = data; + struct oprofile_cpu_buffer * b = + container_of(work, struct oprofile_cpu_buffer, work.work); if (b->cpu != smp_processor_id()) { printk("WQ on CPU%d, prefer CPU%d\n", smp_processor_id(), b->cpu); diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 09abb80e057..49900d9e323 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -43,7 +43,7 @@ struct oprofile_cpu_buffer { unsigned long sample_lost_overflow; unsigned long backtrace_aborted; int cpu; - struct work_struct work; + struct delayed_work work; } ____cacheline_aligned; extern struct oprofile_cpu_buffer cpu_buffer[]; diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ea2087c3414..50757695844 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -70,7 +70,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct list_head slot_list; char name[SLOT_NAME_SIZE]; - struct work_struct work; /* work for button event */ + struct delayed_work work; /* work for button event */ struct mutex lock; }; @@ -187,7 +187,7 @@ extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); -extern void queue_pushbutton_work(void *data); +extern void queue_pushbutton_work(struct work_struct *work); #ifdef CONFIG_ACPI diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 235c18a2239..4eac85b3d90 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -159,7 +159,7 @@ static int init_slots(struct controller *ctrl) goto error_info; slot->number = sun; - INIT_WORK(&slot->work, queue_pushbutton_work, slot); + INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index c39901dbff2..158ac783609 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -36,7 +36,7 @@ #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(void *data); +static void interrupt_event_handler(struct work_struct *work); static int shpchp_enable_slot(struct slot *p_slot); static int shpchp_disable_slot(struct slot *p_slot); @@ -50,7 +50,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->event_type = event_type; info->p_slot = p_slot; - INIT_WORK(&info->work, interrupt_event_handler, info); + INIT_WORK(&info->work, interrupt_event_handler); schedule_work(&info->work); @@ -408,9 +408,10 @@ struct pushbutton_work_info { * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread(void *data) +static void shpchp_pushbutton_thread(struct work_struct *work) { - struct pushbutton_work_info *info = data; + struct pushbutton_work_info *info = + container_of(work, struct pushbutton_work_info, work); struct slot *p_slot = info->p_slot; mutex_lock(&p_slot->lock); @@ -436,9 +437,9 @@ static void shpchp_pushbutton_thread(void *data) kfree(info); } -void queue_pushbutton_work(void *data) +void queue_pushbutton_work(struct work_struct *work) { - struct slot *p_slot = data; + struct slot *p_slot = container_of(work, struct slot, work.work); struct pushbutton_work_info *info; info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -447,7 +448,7 @@ void queue_pushbutton_work(void *data) return; } info->p_slot = p_slot; - INIT_WORK(&info->work, shpchp_pushbutton_thread, info); + INIT_WORK(&info->work, shpchp_pushbutton_thread); mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -541,9 +542,9 @@ static void handle_button_press_event(struct slot *p_slot) } } -static void interrupt_event_handler(void *data) +static void interrupt_event_handler(struct work_struct *work) { - struct event_info *info = data; + struct event_info *info = container_of(work, struct event_info, work); struct slot *p_slot = info->p_slot; mutex_lock(&p_slot->lock); diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 04c43ef529a..55866b6b26f 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -160,7 +160,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev) rpc->e_lock = SPIN_LOCK_UNLOCKED; rpc->rpd = dev; - INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev); + INIT_WORK(&rpc->dpc_handler, aer_isr); rpc->prod_idx = rpc->cons_idx = 0; mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index daf0cad88fc..3c0a58f64dd 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -118,7 +118,7 @@ extern struct bus_type pcie_port_bus_type; extern void aer_enable_rootport(struct aer_rpc *rpc); extern void aer_delete_rootport(struct aer_rpc *rpc); extern int aer_init(struct pcie_device *dev); -extern void aer_isr(void *context); +extern void aer_isr(struct work_struct *work); extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); extern int aer_osc_setup(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 1c7e660d653..08e13033ced 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -690,14 +690,14 @@ static void aer_isr_one_error(struct pcie_device *p_device, /** * aer_isr - consume errors detected by root port - * @context: pointer to a private data of pcie device + * @work: definition of this work item * * Invoked, as DPC, when root port records new detected error **/ -void aer_isr(void *context) +void aer_isr(struct work_struct *work) { - struct pcie_device *p_device = (struct pcie_device *) context; - struct aer_rpc *rpc = get_service_data(p_device); + struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); + struct pcie_device *p_device = rpc->rpd; struct aer_err_source *e_src; mutex_lock(&rpc->rpc_mutex); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 45df12eda3c..7355eb455a8 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -675,9 +675,10 @@ static int pcmcia_card_add(struct pcmcia_socket *s) } -static void pcmcia_delayed_add_device(void *data) +static void pcmcia_delayed_add_device(struct work_struct *work) { - struct pcmcia_socket *s = data; + struct pcmcia_socket *s = + container_of(work, struct pcmcia_socket, device_add); ds_dbg(1, "adding additional device to %d\n", s->sock); pcmcia_device_add(s, s->pcmcia_state.mfc_pfc); s->pcmcia_state.device_add_pending = 0; @@ -1349,7 +1350,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, init_waitqueue_head(&socket->queue); #endif INIT_LIST_HEAD(&socket->devices_list); - INIT_WORK(&socket->device_add, pcmcia_delayed_add_device, socket); + INIT_WORK(&socket->device_add, pcmcia_delayed_add_device); memset(&socket->pcmcia_state, 0, sizeof(u8)); socket->device_count = 0; diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 814b9e1873f..828b329e08e 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -53,9 +53,10 @@ static int rtc_dev_open(struct inode *inode, struct file *file) * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -static void rtc_uie_task(void *data) +static void rtc_uie_task(struct work_struct *work) { - struct rtc_device *rtc = data; + struct rtc_device *rtc = + container_of(work, struct rtc_device, uie_task); struct rtc_time tm; int num = 0; int err; @@ -411,7 +412,7 @@ static int rtc_dev_add_device(struct class_device *class_dev, spin_lock_init(&rtc->irq_lock); init_waitqueue_head(&rtc->irq_queue); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc); + INIT_WORK(&rtc->uie_task, rtc_uie_task); setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); #endif diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index a2cef57d7bc..2af2d9b53d1 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -54,7 +54,7 @@ static void dasd_flush_request_queue(struct dasd_device *); static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); static int dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); -static void do_kick_device(void *data); +static void do_kick_device(struct work_struct *); /* * SECTION: Operations on the device structure. @@ -100,7 +100,7 @@ dasd_alloc_device(void) (unsigned long) device); INIT_LIST_HEAD(&device->ccw_queue); init_timer(&device->timer); - INIT_WORK(&device->kick_work, do_kick_device, device); + INIT_WORK(&device->kick_work, do_kick_device); device->state = DASD_STATE_NEW; device->target = DASD_STATE_NEW; @@ -407,11 +407,9 @@ dasd_change_state(struct dasd_device *device) * event daemon. */ static void -do_kick_device(void *data) +do_kick_device(struct work_struct *work) { - struct dasd_device *device; - - device = (struct dasd_device *) data; + struct dasd_device *device = container_of(work, struct dasd_device, kick_work); dasd_change_state(device); dasd_schedule_bh(device); dasd_put_device(device); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index ad7f7e1c016..26cf2f5ae2e 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -334,7 +334,7 @@ static LIST_HEAD(slow_subchannels_head); static DEFINE_SPINLOCK(slow_subchannel_lock); static void -css_trigger_slow_path(void) +css_trigger_slow_path(struct work_struct *unused) { CIO_TRACE_EVENT(4, "slowpath"); @@ -359,8 +359,7 @@ css_trigger_slow_path(void) spin_unlock_irq(&slow_subchannel_lock); } -typedef void (*workfunc)(void *); -DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); +DECLARE_WORK(slow_path_work, css_trigger_slow_path); struct workqueue_struct *slow_path_wq; /* Reprobe subchannel if unregistered. */ @@ -397,7 +396,7 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) } /* Work function used to reprobe all unregistered subchannels. */ -static void reprobe_all(void *data) +static void reprobe_all(struct work_struct *unused) { int ret; @@ -413,7 +412,7 @@ static void reprobe_all(void *data) need_reprobe); } -DECLARE_WORK(css_reprobe_work, reprobe_all, NULL); +DECLARE_WORK(css_reprobe_work, reprobe_all); /* Schedule reprobing of all unregistered subchannels. */ void css_schedule_reprobe(void) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 6a54334ffe0..e4dc947e74e 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -37,7 +37,7 @@ #include "ap_bus.h" /* Some prototypes. */ -static void ap_scan_bus(void *); +static void ap_scan_bus(struct work_struct *); static void ap_poll_all(unsigned long); static void ap_poll_timeout(unsigned long); static int ap_poll_thread_start(void); @@ -71,7 +71,7 @@ static struct device *ap_root_device = NULL; static struct workqueue_struct *ap_work_queue; static struct timer_list ap_config_timer; static int ap_config_time = AP_CONFIG_TIME; -static DECLARE_WORK(ap_config_work, ap_scan_bus, NULL); +static DECLARE_WORK(ap_config_work, ap_scan_bus); /** * Tasklet & timer for AP request polling. @@ -732,7 +732,7 @@ static void ap_device_release(struct device *dev) kfree(ap_dev); } -static void ap_scan_bus(void *data) +static void ap_scan_bus(struct work_struct *unused) { struct ap_device *ap_dev; struct device *dev; diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 08d4e47070b..e5665b6743a 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -67,7 +67,7 @@ static char debug_buffer[255]; * Some prototypes. */ static void lcs_tasklet(unsigned long); -static void lcs_start_kernel_thread(struct lcs_card *card); +static void lcs_start_kernel_thread(struct work_struct *); static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *); static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *); static int lcs_recovery(void *ptr); @@ -1724,8 +1724,9 @@ lcs_stopcard(struct lcs_card *card) * Kernel Thread helper functions for LGW initiated commands */ static void -lcs_start_kernel_thread(struct lcs_card *card) +lcs_start_kernel_thread(struct work_struct *work) { + struct lcs_card *card = container_of(work, struct lcs_card, kernel_thread_starter); LCS_DBF_TEXT(5, trace, "krnthrd"); if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD)) kernel_thread(lcs_recovery, (void *) card, SIGCHLD); @@ -2053,8 +2054,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) ccwgdev->cdev[0]->handler = lcs_irq; ccwgdev->cdev[1]->handler = lcs_irq; card->gdev = ccwgdev; - INIT_WORK(&card->kernel_thread_starter, - (void *) lcs_start_kernel_thread, card); + INIT_WORK(&card->kernel_thread_starter, lcs_start_kernel_thread); card->thread_start_mask = 0; card->thread_allowed_mask = 0; card->thread_running_mask = 0; diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 7fdc5272c44..2bde4f1fb9c 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1039,8 +1039,9 @@ qeth_do_start_thread(struct qeth_card *card, unsigned long thread) } static void -qeth_start_kernel_thread(struct qeth_card *card) +qeth_start_kernel_thread(struct work_struct *work) { + struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter); QETH_DBF_TEXT(trace , 2, "strthrd"); if (card->read.state != CH_STATE_UP && @@ -1103,8 +1104,7 @@ qeth_setup_card(struct qeth_card *card) card->thread_start_mask = 0; card->thread_allowed_mask = 0; card->thread_running_mask = 0; - INIT_WORK(&card->kernel_thread_starter, - (void *)qeth_start_kernel_thread,card); + INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread); INIT_LIST_HEAD(&card->ip_list); card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL); if (!card->ip_tbd_list) { diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a6aa9107288..bb3cb336054 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -849,7 +849,7 @@ static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; - INIT_WORK(&hostdata->coroutine, NCR5380_main, hostdata); + INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main); #ifdef NCR5380_STATS for (i = 0; i < 8; ++i) { @@ -1016,7 +1016,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* Run the coroutine if it isn't already running. */ /* Kick off command processing */ - schedule_work(&hostdata->coroutine); + schedule_delayed_work(&hostdata->coroutine, 0); return 0; } @@ -1033,9 +1033,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) * host lock and called routines may take the isa dma lock. */ -static void NCR5380_main(void *p) +static void NCR5380_main(struct work_struct *work) { - struct NCR5380_hostdata *hostdata = p; + struct NCR5380_hostdata *hostdata = + container_of(work, struct NCR5380_hostdata, coroutine.work); struct Scsi_Host *instance = hostdata->host; Scsi_Cmnd *tmp, *prev; int done; @@ -1221,7 +1222,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) } /* if BASR_IRQ */ spin_unlock_irqrestore(instance->host_lock, flags); if(!done) - schedule_work(&hostdata->coroutine); + schedule_delayed_work(&hostdata->coroutine, 0); } while (!done); return IRQ_HANDLED; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 1bc73de496b..713a108c02e 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -271,7 +271,7 @@ struct NCR5380_hostdata { unsigned long time_expires; /* in jiffies, set prior to sleeping */ int select_time; /* timer in select for target response */ volatile Scsi_Cmnd *selecting; - struct work_struct coroutine; /* our co-routine */ + struct delayed_work coroutine; /* our co-routine */ #ifdef NCR5380_STATS unsigned timebase; /* Base for time calcs */ long time_read[8]; /* time to do reads */ @@ -298,7 +298,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance); #ifndef DONT_USE_INTR static irqreturn_t NCR5380_intr(int irq, void *dev_id); #endif -static void NCR5380_main(void *ptr); +static void NCR5380_main(struct work_struct *work); static void NCR5380_print_options(struct Scsi_Host *instance); #ifdef NDEBUG static void NCR5380_print_phase(struct Scsi_Host *instance); diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 306f46b85a5..0cec742d12e 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -1443,7 +1443,7 @@ static struct work_struct aha152x_tq; * Run service completions on the card with interrupts enabled. * */ -static void run(void) +static void run(struct work_struct *work) { struct aha152x_hostdata *hd; @@ -1499,7 +1499,7 @@ static irqreturn_t intr(int irqno, void *dev_id) HOSTDATA(shpnt)->service=1; /* Poke the BH handler */ - INIT_WORK(&aha152x_tq, (void *) run, NULL); + INIT_WORK(&aha152x_tq, run); schedule_work(&aha152x_tq); } DO_UNLOCK(flags); diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 14d5d8c2ee1..75ed6b0569d 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -414,9 +414,10 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) } /* hard reset a phy later */ -static void do_phy_reset_later(void *data) +static void do_phy_reset_later(struct work_struct *work) { - struct sas_phy *sas_phy = data; + struct sas_phy *sas_phy = + container_of(work, struct sas_phy, reset_work); int error; ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__, @@ -430,7 +431,7 @@ static void do_phy_reset_later(void *data) static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost) { - INIT_WORK(&sas_phy->reset_work, do_phy_reset_later, sas_phy); + INIT_WORK(&sas_phy->reset_work, do_phy_reset_later); queue_work(shost->work_q, &sas_phy->reset_work); } @@ -442,7 +443,7 @@ static void task_kill_later(struct asd_ascb *ascb) struct Scsi_Host *shost = sas_ha->core.shost; struct sas_task *task = ascb->uldd_task; - INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task); + INIT_WORK(&task->abort_work, sas_task_abort); queue_work(shost->work_q, &task->abort_work); } diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 0e74174a1b3..e28260f05d6 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -67,6 +67,7 @@ struct vio_port { unsigned long liobn; unsigned long riobn; + struct srp_target *target; }; static struct workqueue_struct *vtgtd; @@ -685,10 +686,10 @@ static inline struct viosrp_crq *next_crq(struct crq_queue *queue) return crq; } -static void handle_crq(void *data) +static void handle_crq(struct work_struct *work) { - struct srp_target *target = (struct srp_target *) data; - struct vio_port *vport = target_to_port(target); + struct vio_port *vport = container_of(work, struct vio_port, crq_work); + struct srp_target *target = vport->target; struct viosrp_crq *crq; int done = 0; @@ -822,6 +823,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) target->shost = shost; vport->dma_dev = dev; target->ldata = vport; + vport->target = target; err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, SRP_MAX_IU_LEN); if (err) @@ -837,7 +839,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) vport->liobn = dma[0]; vport->riobn = dma[5]; - INIT_WORK(&vport->crq_work, handle_crq, target); + INIT_WORK(&vport->crq_work, handle_crq); err = crq_queue_create(&vport->crq_queue, target); if (err) diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index e31f6122106..0464c182c57 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -36,7 +36,7 @@ typedef struct { int base_hi; /* Hi Base address for ECP-ISA chipset */ int mode; /* Transfer mode */ struct scsi_cmnd *cur_cmd; /* Current queued command */ - struct work_struct imm_tq; /* Polling interrupt stuff */ + struct delayed_work imm_tq; /* Polling interrupt stuff */ unsigned long jstart; /* Jiffies at start */ unsigned failed:1; /* Failure flag */ unsigned dp:1; /* Data phase present */ @@ -733,9 +733,9 @@ static int imm_completion(struct scsi_cmnd *cmd) * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */ -static void imm_interrupt(void *data) +static void imm_interrupt(struct work_struct *work) { - imm_struct *dev = (imm_struct *) data; + imm_struct *dev = container_of(work, imm_struct, imm_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd; struct Scsi_Host *host = cmd->device->host; unsigned long flags; @@ -745,7 +745,6 @@ static void imm_interrupt(void *data) return; } if (imm_engine(dev, cmd)) { - INIT_WORK(&dev->imm_tq, imm_interrupt, (void *) dev); schedule_delayed_work(&dev->imm_tq, 1); return; } @@ -953,8 +952,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd, cmd->result = DID_ERROR << 16; /* default return code */ cmd->SCp.phase = 0; /* bus free */ - INIT_WORK(&dev->imm_tq, imm_interrupt, dev); - schedule_work(&dev->imm_tq); + schedule_delayed_work(&dev->imm_tq, 0); imm_pb_claim(dev); @@ -1225,7 +1223,7 @@ static int __imm_attach(struct parport *pb) else ports = 8; - INIT_WORK(&dev->imm_tq, imm_interrupt, dev); + INIT_DELAYED_WORK(&dev->imm_tq, imm_interrupt); err = -ENOMEM; host = scsi_host_alloc(&imm_template, sizeof(imm_struct *)); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2d83fbb806a..ccd4dafce8e 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2307,7 +2307,7 @@ static void ipr_release_dump(struct kref *kref) /** * ipr_worker_thread - Worker thread - * @data: ioa config struct + * @work: ioa config struct * * Called at task level from a work thread. This function takes care * of adding and removing device from the mid-layer as configuration @@ -2316,13 +2316,14 @@ static void ipr_release_dump(struct kref *kref) * Return value: * nothing **/ -static void ipr_worker_thread(void *data) +static void ipr_worker_thread(struct work_struct *work) { unsigned long lock_flags; struct ipr_resource_entry *res; struct scsi_device *sdev; struct ipr_dump *dump; - struct ipr_ioa_cfg *ioa_cfg = data; + struct ipr_ioa_cfg *ioa_cfg = + container_of(work, struct ipr_ioa_cfg, work_q); u8 bus, target, lun; int did_work; @@ -7121,7 +7122,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); INIT_LIST_HEAD(&ioa_cfg->free_res_q); INIT_LIST_HEAD(&ioa_cfg->used_res_q); - INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread, ioa_cfg); + INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); init_waitqueue_head(&ioa_cfg->reset_wait_q); ioa_cfg->sdt_state = INACTIVE; if (ipr_enable_cache) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 5d886218948..e11b23c641e 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -719,9 +719,10 @@ again: return rc; } -static void iscsi_xmitworker(void *data) +static void iscsi_xmitworker(struct work_struct *work) { - struct iscsi_conn *conn = data; + struct iscsi_conn *conn = + container_of(work, struct iscsi_conn, xmitwork); int rc; /* * serialize Xmit worker on a per-connection basis. @@ -1512,7 +1513,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) goto mgmtqueue_alloc_fail; - INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + INIT_WORK(&conn->xmitwork, iscsi_xmitworker); /* allocate login_mtask used for the login/text sequences */ spin_lock_bh(&session->lock); diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index d977bd492d8..fb7df7b7581 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -647,10 +647,12 @@ void sas_unregister_domain_devices(struct asd_sas_port *port) * Discover process only interrogates devices in order to discover the * domain. */ -static void sas_discover_domain(void *data) +static void sas_discover_domain(struct work_struct *work) { int error = 0; - struct asd_sas_port *port = data; + struct sas_discovery_event *ev = + container_of(work, struct sas_discovery_event, work); + struct asd_sas_port *port = ev->port; sas_begin_event(DISCE_DISCOVER_DOMAIN, &port->disc.disc_event_lock, &port->disc.pending); @@ -692,10 +694,12 @@ static void sas_discover_domain(void *data) current->pid, error); } -static void sas_revalidate_domain(void *data) +static void sas_revalidate_domain(struct work_struct *work) { int res = 0; - struct asd_sas_port *port = data; + struct sas_discovery_event *ev = + container_of(work, struct sas_discovery_event, work); + struct asd_sas_port *port = ev->port; sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock, &port->disc.pending); @@ -722,7 +726,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) BUG_ON(ev >= DISC_NUM_EVENTS); sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, - &disc->disc_work[ev], port->ha->core.shost); + &disc->disc_work[ev].work, port->ha->core.shost); return 0; } @@ -737,13 +741,15 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) { int i; - static void (*sas_event_fns[DISC_NUM_EVENTS])(void *) = { + static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, }; spin_lock_init(&disc->disc_event_lock); disc->pending = 0; - for (i = 0; i < DISC_NUM_EVENTS; i++) - INIT_WORK(&disc->disc_work[i], sas_event_fns[i], port); + for (i = 0; i < DISC_NUM_EVENTS; i++) { + INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]); + disc->disc_work[i].port = port; + } } diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 19110ed1c89..d83392ee682 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) BUG_ON(event >= HA_NUM_EVENTS); sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, - &sas_ha->ha_events[event], sas_ha->core.shost); + &sas_ha->ha_events[event].work, sas_ha->core.shost); } static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) @@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) BUG_ON(event >= PORT_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, - &phy->port_events[event], ha->core.shost); + &phy->port_events[event].work, ha->core.shost); } static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) @@ -51,12 +51,12 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) BUG_ON(event >= PHY_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, - &phy->phy_events[event], ha->core.shost); + &phy->phy_events[event].work, ha->core.shost); } int sas_init_events(struct sas_ha_struct *sas_ha) { - static void (*sas_ha_event_fns[HA_NUM_EVENTS])(void *) = { + static const work_func_t sas_ha_event_fns[HA_NUM_EVENTS] = { [HAE_RESET] = sas_hae_reset, }; @@ -64,8 +64,10 @@ int sas_init_events(struct sas_ha_struct *sas_ha) spin_lock_init(&sas_ha->event_lock); - for (i = 0; i < HA_NUM_EVENTS; i++) - INIT_WORK(&sas_ha->ha_events[i], sas_ha_event_fns[i], sas_ha); + for (i = 0; i < HA_NUM_EVENTS; i++) { + INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]); + sas_ha->ha_events[i].ha = sas_ha; + } sas_ha->notify_ha_event = notify_ha_event; sas_ha->notify_port_event = notify_port_event; diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 0fb347b4b1a..d65bc4e0f21 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -65,9 +65,11 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr) /* ---------- HA events ---------- */ -void sas_hae_reset(void *data) +void sas_hae_reset(struct work_struct *work) { - struct sas_ha_struct *ha = data; + struct sas_ha_event *ev = + container_of(work, struct sas_ha_event, work); + struct sas_ha_struct *ha = ev->ha; sas_begin_event(HAE_RESET, &ha->event_lock, &ha->pending); diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index bffcee47492..137d7e496b6 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -60,11 +60,11 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha); void sas_deform_port(struct asd_sas_phy *phy); -void sas_porte_bytes_dmaed(void *); -void sas_porte_broadcast_rcvd(void *); -void sas_porte_link_reset_err(void *); -void sas_porte_timer_event(void *); -void sas_porte_hard_reset(void *); +void sas_porte_bytes_dmaed(struct work_struct *work); +void sas_porte_broadcast_rcvd(struct work_struct *work); +void sas_porte_link_reset_err(struct work_struct *work); +void sas_porte_timer_event(struct work_struct *work); +void sas_porte_hard_reset(struct work_struct *work); int sas_notify_lldd_dev_found(struct domain_device *); void sas_notify_lldd_dev_gone(struct domain_device *); @@ -75,7 +75,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy); struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); -void sas_hae_reset(void *); +void sas_hae_reset(struct work_struct *work); static inline void sas_queue_event(int event, spinlock_t *lock, unsigned long *pending, diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c index 9340cdbae4a..b459c4b635b 100644 --- a/drivers/scsi/libsas/sas_phy.c +++ b/drivers/scsi/libsas/sas_phy.c @@ -30,9 +30,11 @@ /* ---------- Phy events ---------- */ -static void sas_phye_loss_of_signal(void *data) +static void sas_phye_loss_of_signal(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, &phy->phy_events_pending); @@ -40,18 +42,22 @@ static void sas_phye_loss_of_signal(void *data) sas_deform_port(phy); } -static void sas_phye_oob_done(void *data) +static void sas_phye_oob_done(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PHYE_OOB_DONE, &phy->ha->event_lock, &phy->phy_events_pending); phy->error = 0; } -static void sas_phye_oob_error(void *data) +static void sas_phye_oob_error(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; struct sas_ha_struct *sas_ha = phy->ha; struct asd_sas_port *port = phy->port; struct sas_internal *i = @@ -80,9 +86,11 @@ static void sas_phye_oob_error(void *data) } } -static void sas_phye_spinup_hold(void *data) +static void sas_phye_spinup_hold(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; struct sas_ha_struct *sas_ha = phy->ha; struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); @@ -100,14 +108,14 @@ int sas_register_phys(struct sas_ha_struct *sas_ha) { int i; - static void (*sas_phy_event_fns[PHY_NUM_EVENTS])(void *) = { + static const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = { [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal, [PHYE_OOB_DONE] = sas_phye_oob_done, [PHYE_OOB_ERROR] = sas_phye_oob_error, [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold, }; - static void (*sas_port_event_fns[PORT_NUM_EVENTS])(void *) = { + static const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = { [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed, [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd, [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err, @@ -122,13 +130,18 @@ int sas_register_phys(struct sas_ha_struct *sas_ha) phy->error = 0; INIT_LIST_HEAD(&phy->port_phy_el); - for (k = 0; k < PORT_NUM_EVENTS; k++) - INIT_WORK(&phy->port_events[k], sas_port_event_fns[k], - phy); + for (k = 0; k < PORT_NUM_EVENTS; k++) { + INIT_WORK(&phy->port_events[k].work, + sas_port_event_fns[k]); + phy->port_events[k].phy = phy; + } + + for (k = 0; k < PHY_NUM_EVENTS; k++) { + INIT_WORK(&phy->phy_events[k].work, + sas_phy_event_fns[k]); + phy->phy_events[k].phy = phy; + } - for (k = 0; k < PHY_NUM_EVENTS; k++) - INIT_WORK(&phy->phy_events[k], sas_phy_event_fns[k], - phy); phy->port = NULL; phy->ha = sas_ha; spin_lock_init(&phy->frame_rcvd_lock); diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 253cdcf306a..971c37ceecb 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -181,9 +181,11 @@ void sas_deform_port(struct asd_sas_phy *phy) /* ---------- SAS port events ---------- */ -void sas_porte_bytes_dmaed(void *data) +void sas_porte_bytes_dmaed(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_BYTES_DMAED, &phy->ha->event_lock, &phy->port_events_pending); @@ -191,11 +193,13 @@ void sas_porte_bytes_dmaed(void *data) sas_form_port(phy); } -void sas_porte_broadcast_rcvd(void *data) +void sas_porte_broadcast_rcvd(struct work_struct *work) { + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; unsigned long flags; u32 prim; - struct asd_sas_phy *phy = data; sas_begin_event(PORTE_BROADCAST_RCVD, &phy->ha->event_lock, &phy->port_events_pending); @@ -208,9 +212,11 @@ void sas_porte_broadcast_rcvd(void *data) sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN); } -void sas_porte_link_reset_err(void *data) +void sas_porte_link_reset_err(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, &phy->port_events_pending); @@ -218,9 +224,11 @@ void sas_porte_link_reset_err(void *data) sas_deform_port(phy); } -void sas_porte_timer_event(void *data) +void sas_porte_timer_event(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, &phy->port_events_pending); @@ -228,9 +236,11 @@ void sas_porte_timer_event(void *data) sas_deform_port(phy); } -void sas_porte_hard_reset(void *data) +void sas_porte_hard_reset(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, &phy->port_events_pending); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index e064aac06b9..22672d54aa2 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -846,8 +846,10 @@ static int do_sas_task_abort(struct sas_task *task) return -EAGAIN; } -void sas_task_abort(struct sas_task *task) +void sas_task_abort(struct work_struct *work) { + struct sas_task *task = + container_of(work, struct sas_task, abort_work); int i; for (i = 0; i < 5; i++) diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c index dd67a68c5c2..c116a6ae3c5 100644 --- a/drivers/scsi/oktagon_esp.c +++ b/drivers/scsi/oktagon_esp.c @@ -72,12 +72,12 @@ static void dma_advance_sg(Scsi_Cmnd *); static int oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x); #ifdef USE_BOTTOM_HALF -static void dma_commit(void *opaque); +static void dma_commit(struct work_struct *unused); long oktag_to_io(long *paddr, long *addr, long len); long oktag_from_io(long *addr, long *paddr, long len); -static DECLARE_WORK(tq_fake_dma, dma_commit, NULL); +static DECLARE_WORK(tq_fake_dma, dma_commit); #define DMA_MAXTRANSFER 0x8000 @@ -266,7 +266,7 @@ oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x) */ -static void dma_commit(void *opaque) +static void dma_commit(struct work_struct *unused) { long wait,len2,pos; struct NCR_ESP *esp; diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 89a2a9f11e4..584ba4d6e03 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -31,7 +31,7 @@ typedef struct { int base; /* Actual port address */ int mode; /* Transfer mode */ struct scsi_cmnd *cur_cmd; /* Current queued command */ - struct work_struct ppa_tq; /* Polling interrupt stuff */ + struct delayed_work ppa_tq; /* Polling interrupt stuff */ unsigned long jstart; /* Jiffies at start */ unsigned long recon_tmo; /* How many usecs to wait for reconnection (6th bit) */ unsigned int failed:1; /* Failure flag */ @@ -627,9 +627,9 @@ static int ppa_completion(struct scsi_cmnd *cmd) * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */ -static void ppa_interrupt(void *data) +static void ppa_interrupt(struct work_struct *work) { - ppa_struct *dev = (ppa_struct *) data; + ppa_struct *dev = container_of(work, ppa_struct, ppa_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd; if (!cmd) { @@ -637,7 +637,6 @@ static void ppa_interrupt(void *data) return; } if (ppa_engine(dev, cmd)) { - dev->ppa_tq.data = (void *) dev; schedule_delayed_work(&dev->ppa_tq, 1); return; } @@ -822,8 +821,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd, cmd->result = DID_ERROR << 16; /* default return code */ cmd->SCp.phase = 0; /* bus free */ - dev->ppa_tq.data = dev; - schedule_work(&dev->ppa_tq); + schedule_delayed_work(&dev->ppa_tq, 0); ppa_pb_claim(dev); @@ -1086,7 +1084,7 @@ static int __ppa_attach(struct parport *pb) else ports = 8; - INIT_WORK(&dev->ppa_tq, ppa_interrupt, dev); + INIT_DELAYED_WORK(&dev->ppa_tq, ppa_interrupt); err = -ENOMEM; host = scsi_host_alloc(&ppa_template, sizeof(ppa_struct *)); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index db9d88e7bee..969c9e43102 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -961,9 +961,10 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, * the mid-level tries to sleep when it reaches the driver threshold * "host->can_queue". This can cause a panic if we were in our interrupt code. **/ -static void qla4xxx_do_dpc(void *data) +static void qla4xxx_do_dpc(struct work_struct *work) { - struct scsi_qla_host *ha = (struct scsi_qla_host *) data; + struct scsi_qla_host *ha = + container_of(work, struct scsi_qla_host, dpc_work); struct ddb_entry *ddb_entry, *dtemp; DEBUG2(printk("scsi%ld: %s: DPC handler waking up." @@ -1253,7 +1254,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ret = -ENODEV; goto probe_failed; } - INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc, ha); + INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); ret = request_irq(pdev->irq, qla4xxx_intr_handler, SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 4d656148bd6..14e635aa44c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -437,9 +437,10 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, goto retry; } -static void scsi_target_reap_usercontext(void *data) +static void scsi_target_reap_usercontext(struct work_struct *work) { - struct scsi_target *starget = data; + struct scsi_target *starget = + container_of(work, struct scsi_target, ew.work); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; @@ -475,7 +476,7 @@ void scsi_target_reap(struct scsi_target *starget) starget->state = STARGET_DEL; spin_unlock_irqrestore(shost->host_lock, flags); execute_in_process_context(scsi_target_reap_usercontext, - starget, &starget->ew); + &starget->ew); return; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e1a91665d1c..259c90cfa36 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -218,16 +218,16 @@ static void scsi_device_cls_release(struct class_device *class_dev) put_device(&sdev->sdev_gendev); } -static void scsi_device_dev_release_usercontext(void *data) +static void scsi_device_dev_release_usercontext(struct work_struct *work) { - struct device *dev = data; struct scsi_device *sdev; struct device *parent; struct scsi_target *starget; unsigned long flags; - parent = dev->parent; - sdev = to_scsi_device(dev); + sdev = container_of(work, struct scsi_device, ew.work); + + parent = sdev->sdev_gendev.parent; starget = to_scsi_target(parent); spin_lock_irqsave(sdev->host->host_lock, flags); @@ -258,7 +258,7 @@ static void scsi_device_dev_release_usercontext(void *data) static void scsi_device_dev_release(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - execute_in_process_context(scsi_device_dev_release_usercontext, dev, + execute_in_process_context(scsi_device_dev_release_usercontext, &sdp->ew); } diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 39da5cd6fb6..386dbae17b4 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -185,10 +185,11 @@ static void cmd_hashlist_del(struct scsi_cmnd *cmd) spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); } -static void scsi_tgt_cmd_destroy(void *data) +static void scsi_tgt_cmd_destroy(struct work_struct *work) { - struct scsi_cmnd *cmd = data; - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + struct scsi_tgt_cmd *tcmd = + container_of(work, struct scsi_tgt_cmd, work); + struct scsi_cmnd *cmd = tcmd->rq->special; dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction, rq_data_dir(cmd->request)); @@ -214,6 +215,7 @@ static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, struct list_head *head; tcmd->tag = tag; + INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); spin_lock_irqsave(&qdata->cmd_hash_lock, flags); head = &qdata->cmd_hash[cmd_hashfn(tag)]; list_add(&tcmd->hash_list, head); @@ -303,7 +305,7 @@ void scsi_tgt_free_queue(struct Scsi_Host *shost) cmd = tcmd->rq->special; shost->hostt->eh_abort_handler(cmd); - scsi_tgt_cmd_destroy(cmd); + scsi_tgt_cmd_destroy(&tcmd->work); } } EXPORT_SYMBOL_GPL(scsi_tgt_free_queue); @@ -347,7 +349,6 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); scsi_tgt_uspace_send_status(cmd, tcmd->tag); - INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy, cmd); queue_work(scsi_tgtd, &tcmd->work); } @@ -549,13 +550,15 @@ static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { + struct scsi_tgt_cmd *tcmd; int err; err = shost->hostt->eh_abort_handler(cmd); if (err) eprintk("fail to abort %p\n", cmd); - scsi_tgt_cmd_destroy(cmd); + tcmd = cmd->request->end_io_data; + scsi_tgt_cmd_destroy(&tcmd->work); return err; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 38c215a78f6..3571ce8934e 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -241,9 +241,9 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names) #define FC_MGMTSRVR_PORTID 0x00000a -static void fc_timeout_deleted_rport(void *data); -static void fc_timeout_fail_rport_io(void *data); -static void fc_scsi_scan_rport(void *data); +static void fc_timeout_deleted_rport(struct work_struct *work); +static void fc_timeout_fail_rport_io(struct work_struct *work); +static void fc_scsi_scan_rport(struct work_struct *work); /* * Attribute counts pre object type... @@ -1613,7 +1613,7 @@ fc_flush_work(struct Scsi_Host *shost) * 1 on success / 0 already queued / < 0 for error **/ static int -fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, +fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work, unsigned long delay) { if (unlikely(!fc_host_devloss_work_q(shost))) { @@ -1625,9 +1625,6 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, return -EINVAL; } - if (delay == 0) - return queue_work(fc_host_devloss_work_q(shost), work); - return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay); } @@ -1712,12 +1709,13 @@ EXPORT_SYMBOL(fc_remove_host); * fc_starget_delete - called to delete the scsi decendents of an rport * (target and all sdevs) * - * @data: remote port to be operated on. + * @work: remote port to be operated on. **/ static void -fc_starget_delete(void *data) +fc_starget_delete(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, stgt_delete_work); struct Scsi_Host *shost = rport_to_shost(rport); unsigned long flags; struct fc_internal *i = to_fc_internal(shost->transportt); @@ -1751,12 +1749,13 @@ fc_starget_delete(void *data) /** * fc_rport_final_delete - finish rport termination and delete it. * - * @data: remote port to be deleted. + * @work: remote port to be deleted. **/ static void -fc_rport_final_delete(void *data) +fc_rport_final_delete(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, rport_delete_work); struct device *dev = &rport->dev; struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -1770,7 +1769,7 @@ fc_rport_final_delete(void *data) /* Delete SCSI target and sdevs */ if (rport->scsi_target_id != -1) - fc_starget_delete(data); + fc_starget_delete(&rport->stgt_delete_work); else if (i->f->dev_loss_tmo_callbk) i->f->dev_loss_tmo_callbk(rport); else if (i->f->terminate_rport_io) @@ -1829,11 +1828,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel, rport->channel = channel; rport->fast_io_fail_tmo = -1; - INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport); - INIT_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io, rport); - INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); - INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport); - INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport); + INIT_DELAYED_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport); + INIT_DELAYED_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io); + INIT_WORK(&rport->scan_work, fc_scsi_scan_rport); + INIT_WORK(&rport->stgt_delete_work, fc_starget_delete); + INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete); spin_lock_irqsave(shost->host_lock, flags); @@ -1963,7 +1962,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } if (match) { - struct work_struct *work = + struct delayed_work *work = &rport->dev_loss_work; memcpy(&rport->node_name, &ids->node_name, @@ -2267,12 +2266,13 @@ EXPORT_SYMBOL(fc_remote_port_rolechg); * was a SCSI target (thus was blocked), and failed * to return in the alloted time. * - * @data: rport target that failed to reappear in the alloted time. + * @work: rport target that failed to reappear in the alloted time. **/ static void -fc_timeout_deleted_rport(void *data) +fc_timeout_deleted_rport(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, dev_loss_work.work); struct Scsi_Host *shost = rport_to_shost(rport); struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; @@ -2366,15 +2366,16 @@ fc_timeout_deleted_rport(void *data) * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a * disconnected SCSI target. * - * @data: rport to terminate io on. + * @work: rport to terminate io on. * * Notes: Only requests the failure of the io, not that all are flushed * prior to returning. **/ static void -fc_timeout_fail_rport_io(void *data) +fc_timeout_fail_rport_io(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, fail_io_work.work); struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -2387,12 +2388,13 @@ fc_timeout_fail_rport_io(void *data) /** * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. * - * @data: remote port to be scanned. + * @work: remote port to be scanned. **/ static void -fc_scsi_scan_rport(void *data) +fc_scsi_scan_rport(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, scan_work); struct Scsi_Host *shost = rport_to_shost(rport); unsigned long flags; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 9b25124a989..9c22f134271 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -234,9 +234,11 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, return 0; } -static void session_recovery_timedout(void *data) +static void session_recovery_timedout(struct work_struct *work) { - struct iscsi_cls_session *session = data; + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, + recovery_work.work); dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " "out after %d secs\n", session->recovery_tmo); @@ -276,7 +278,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, session->transport = transport; session->recovery_tmo = 120; - INIT_WORK(&session->recovery_work, session_recovery_timedout, session); + INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); INIT_LIST_HEAD(&session->host_list); INIT_LIST_HEAD(&session->sess_list); diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 9f070f0d0f2..3fded483146 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -964,9 +964,10 @@ struct work_queue_wrapper { }; static void -spi_dv_device_work_wrapper(void *data) +spi_dv_device_work_wrapper(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct scsi_device *sdev = wqw->sdev; kfree(wqw); @@ -1006,7 +1007,7 @@ spi_schedule_dv_device(struct scsi_device *sdev) return; } - INIT_WORK(&wqw->work, spi_dv_device_work_wrapper, wqw); + INIT_WORK(&wqw->work, spi_dv_device_work_wrapper); wqw->sdev = sdev; schedule_work(&wqw->work); diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index aee1b31f1a1..3db206d29b3 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -60,7 +60,8 @@ struct timer_list mcfrs_timer_struct; #if defined(CONFIG_HW_FEITH) #define CONSOLE_BAUD_RATE 38400 #define DEFAULT_CBAUD B38400 -#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB) +#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \ + defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ @@ -109,12 +110,30 @@ static struct mcf_serial mcfrs_table[] = { .irq = IRQBASE, .flags = ASYNC_BOOT_AUTOCONF, }, +#ifdef MCFUART_BASE2 { /* ttyS1 */ .magic = 0, .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2), .irq = IRQBASE+1, .flags = ASYNC_BOOT_AUTOCONF, }, +#endif +#ifdef MCFUART_BASE3 + { /* ttyS2 */ + .magic = 0, + .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3), + .irq = IRQBASE+2, + .flags = ASYNC_BOOT_AUTOCONF, + }, +#endif +#ifdef MCFUART_BASE4 + { /* ttyS3 */ + .magic = 0, + .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4), + .irq = IRQBASE+3, + .flags = ASYNC_BOOT_AUTOCONF, + }, +#endif }; @@ -1516,6 +1535,22 @@ static void mcfrs_irqinit(struct mcf_serial *info) imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_IMRL); *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); +#if defined(CONFIG_M527x) + { + /* + * External Pin Mask Setting & Enable External Pin for Interface + * mrcbis@aliceposta.it + */ + unsigned short *serpin_enable_mask; + serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART); + if (info->line == 0) + *serpin_enable_mask |= UART0_ENABLE_MASK; + else if (info->line == 1) + *serpin_enable_mask |= UART1_ENABLE_MASK; + else if (info->line == 2) + *serpin_enable_mask |= UART2_ENABLE_MASK; + } +#endif #elif defined(CONFIG_M520x) volatile unsigned char *icrp, *uartp; volatile unsigned long *imrp; @@ -1713,7 +1748,7 @@ mcfrs_init(void) /* Initialize the tty_driver structure */ mcfrs_serial_driver->owner = THIS_MODULE; mcfrs_serial_driver->name = "ttyS"; - mcfrs_serial_driver->driver_name = "serial"; + mcfrs_serial_driver->driver_name = "mcfserial"; mcfrs_serial_driver->major = TTY_MAJOR; mcfrs_serial_driver->minor_start = 64; mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; @@ -1797,10 +1832,23 @@ void mcfrs_init_console(void) uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; +#ifdef CONFIG_M5272 +{ + /* + * For the MCF5272, also compute the baudrate fraction. + */ + int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud); + fraction *= 16; + fraction /= (32 * mcfrs_console_baud); + uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ + clk = (MCF_BUSCLK / mcfrs_console_baud) / 32; +} +#else clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */ +#endif + uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */ uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */ - uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index cfcc3caf49d..3b5f19ec212 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -775,7 +775,7 @@ static int sci_notifier(struct notifier_block *self, * * Clean this up later.. */ - clk = clk_get("module_clk"); + clk = clk_get(NULL, "module_clk"); port->uartclk = clk_get_rate(clk) * 16; clk_put(clk); } @@ -960,7 +960,7 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios, default: { #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) - struct clk *clk = clk_get("module_clk"); + struct clk *clk = clk_get(NULL, "module_clk"); t = SCBRR_VALUE(baud, clk_get_rate(clk)); clk_put(clk); #else @@ -1128,7 +1128,7 @@ static void __init sci_init_ports(void) * XXX: We should use a proper SCI/SCIF clock */ { - struct clk *clk = clk_get("module_clk"); + struct clk *clk = clk_get(NULL, "module_clk"); sci_ports[i].port.uartclk = clk_get_rate(clk) * 16; clk_put(clk); } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 7ee992146ae..e4557cc4f74 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -133,6 +133,20 @@ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ +# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ +# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ +# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ +# define SCSPTR1 0xf8410020 /* 16 bit SCIF */ +# define SCSPTR2 0xf8420020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #else # error CPU subtype not defined #endif @@ -365,6 +379,7 @@ SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8) SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) #if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) +SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) @@ -544,6 +559,28 @@ static inline int sci_rxd_in(struct uart_port *port) if (port->mapbase == 0xffe10000) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ } +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xfffe8000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe8800) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9800) + return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xf8400000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8410000) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8420000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ +} #endif /* diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 72025df5561..494d9b85648 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -148,7 +148,7 @@ struct chip_data { void (*cs_control)(u32 command); }; -static void pump_messages(void *data); +static void pump_messages(struct work_struct *work); static int flush(struct driver_data *drv_data) { @@ -884,9 +884,10 @@ static void pump_transfers(unsigned long data) } } -static void pump_messages(void *data) +static void pump_messages(struct work_struct *work) { - struct driver_data *drv_data = data; + struct driver_data *drv_data = + container_of(work, struct driver_data, pump_messages); unsigned long flags; /* Lock queue and check for queue work */ @@ -1098,7 +1099,7 @@ static int init_queue(struct driver_data *drv_data) tasklet_init(&drv_data->pump_transfers, pump_transfers, (unsigned long)drv_data); - INIT_WORK(&drv_data->pump_messages, pump_messages, drv_data); + INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = create_singlethread_workqueue( drv_data->master->cdev.dev->bus_id); if (drv_data->workqueue == NULL) diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index a23862ef72b..08c1c57c612 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -265,9 +265,10 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware. */ -static void bitbang_work(void *_bitbang) +static void bitbang_work(struct work_struct *work) { - struct spi_bitbang *bitbang = _bitbang; + struct spi_bitbang *bitbang = + container_of(work, struct spi_bitbang, work); unsigned long flags; spin_lock_irqsave(&bitbang->lock, flags); @@ -456,7 +457,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) if (!bitbang->master || !bitbang->chipselect) return -EINVAL; - INIT_WORK(&bitbang->work, bitbang_work, bitbang); + INIT_WORK(&bitbang->work, bitbang_work); spin_lock_init(&bitbang->lock); INIT_LIST_HEAD(&bitbang->queue); diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index e6565633ba0..3dfa3e40e14 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -158,7 +158,7 @@ struct cxacru_data { const struct cxacru_modem_type *modem_type; int line_status; - struct work_struct poll_work; + struct delayed_work poll_work; /* contol handles */ struct mutex cm_serialize; @@ -347,7 +347,7 @@ static int cxacru_card_status(struct cxacru_data *instance) return 0; } -static void cxacru_poll_status(struct cxacru_data *instance); +static void cxacru_poll_status(struct work_struct *work); static int cxacru_atm_start(struct usbatm_data *usbatm_instance, struct atm_dev *atm_dev) @@ -376,12 +376,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, } /* Start status polling */ - cxacru_poll_status(instance); + cxacru_poll_status(&instance->poll_work.work); return 0; } -static void cxacru_poll_status(struct cxacru_data *instance) +static void cxacru_poll_status(struct work_struct *work) { + struct cxacru_data *instance = + container_of(work, struct cxacru_data, poll_work.work); u32 buf[CXINF_MAX] = {}; struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; @@ -720,7 +722,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, mutex_init(&instance->cm_serialize); - INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance); + INIT_DELAYED_WORK(&instance->poll_work, cxacru_poll_status); usbatm_instance->driver_data = instance; diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index a823486495c..8ed6c75adf0 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -142,7 +142,7 @@ struct speedtch_instance_data { struct speedtch_params params; /* set in probe, constant afterwards */ - struct work_struct status_checker; + struct delayed_work status_checker; unsigned char last_status; @@ -498,8 +498,11 @@ static int speedtch_start_synchro(struct speedtch_instance_data *instance) return ret; } -static void speedtch_check_status(struct speedtch_instance_data *instance) +static void speedtch_check_status(struct work_struct *work) { + struct speedtch_instance_data *instance = + container_of(work, struct speedtch_instance_data, + status_checker.work); struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; unsigned char *buf = instance->scratch_buffer; @@ -576,7 +579,7 @@ static void speedtch_status_poll(unsigned long data) { struct speedtch_instance_data *instance = (void *)data; - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); /* The following check is racy, but the race is harmless */ if (instance->poll_delay < MAX_POLL_DELAY) @@ -596,7 +599,7 @@ static void speedtch_resubmit_int(unsigned long data) if (int_urb) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); if (!ret) - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); else { atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); @@ -640,7 +643,7 @@ static void speedtch_handle_int(struct urb *int_urb) if ((int_urb = instance->int_urb)) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); if (ret < 0) { atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); goto fail; @@ -855,7 +858,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); - INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); + INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status); instance->status_checker.timer.function = speedtch_status_poll; instance->status_checker.timer.data = (unsigned long)instance; diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index c137c041f7a..f2d196fa1e8 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -655,9 +655,9 @@ static int request_dsp(struct uea_softc *sc) /* * The uea_load_page() function must be called within a process context */ -static void uea_load_page(void *xsc) +static void uea_load_page(struct work_struct *work) { - struct uea_softc *sc = xsc; + struct uea_softc *sc = container_of(work, struct uea_softc, task); u16 pageno = sc->pageno; u16 ovl = sc->ovl; struct block_info bi; @@ -1348,7 +1348,7 @@ static int uea_boot(struct uea_softc *sc) uea_enters(INS_TO_USBDEV(sc)); - INIT_WORK(&sc->task, uea_load_page, sc); + INIT_WORK(&sc->task, uea_load_page); init_waitqueue_head(&sc->sync_q); init_waitqueue_head(&sc->cmv_ack_wait); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ec3438dc8ee..7f1fa956dcd 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -421,9 +421,9 @@ static void acm_write_bulk(struct urb *urb) schedule_work(&acm->work); } -static void acm_softint(void *private) +static void acm_softint(struct work_struct *work) { - struct acm *acm = private; + struct acm *acm = container_of(work, struct acm, work); dbg("Entering acm_softint."); if (!ACM_READY(acm)) @@ -927,7 +927,7 @@ skip_normal_probe: acm->rx_buflimit = num_rx_buf; acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; - INIT_WORK(&acm->work, acm_softint, acm); + INIT_WORK(&acm->work, acm_softint); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0ce393eb3c4..9be41ed1f9a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -68,7 +68,7 @@ struct usb_hub { unsigned has_indicators:1; u8 indicator[USB_MAXCHILDREN]; - struct work_struct leds; + struct delayed_work leds; }; @@ -218,9 +218,10 @@ static void set_port_led( #define LED_CYCLE_PERIOD ((2*HZ)/3) -static void led_work (void *__hub) +static void led_work (struct work_struct *work) { - struct usb_hub *hub = __hub; + struct usb_hub *hub = + container_of(work, struct usb_hub, leds.work); struct usb_device *hdev = hub->hdev; unsigned i; unsigned changed = 0; @@ -405,9 +406,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) * talking to TTs must queue control transfers (not just bulk and iso), so * both can talk to the same hub concurrently. */ -static void hub_tt_kevent (void *arg) +static void hub_tt_kevent (struct work_struct *work) { - struct usb_hub *hub = arg; + struct usb_hub *hub = + container_of(work, struct usb_hub, tt.kevent); unsigned long flags; spin_lock_irqsave (&hub->tt.lock, flags); @@ -694,7 +696,7 @@ static int hub_configure(struct usb_hub *hub, spin_lock_init (&hub->tt.lock); INIT_LIST_HEAD (&hub->tt.clear_list); - INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); + INIT_WORK (&hub->tt.kevent, hub_tt_kevent); switch (hdev->descriptor.bDeviceProtocol) { case 0: break; @@ -938,7 +940,7 @@ descriptor_error: INIT_LIST_HEAD(&hub->event_list); hub->intfdev = &intf->dev; hub->hdev = hdev; - INIT_WORK(&hub->leds, led_work, hub); + INIT_DELAYED_WORK(&hub->leds, led_work); usb_set_intfdata (intf, hub); intf->needs_remote_wakeup = 1; @@ -2381,7 +2383,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) /* hub LEDs are probably harder to miss than syslog */ if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_GREEN_BLINK; - schedule_work (&hub->leds); + schedule_delayed_work (&hub->leds, 0); } } kfree(qual); @@ -2555,7 +2557,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_AMBER_BLINK; - schedule_work (&hub->leds); + schedule_delayed_work (&hub->leds, 0); } status = -ENOTCONN; /* Don't retry */ goto loop_disable; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 29b0fa9ff9d..7390b67c609 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1501,9 +1501,10 @@ struct set_config_request { }; /* Worker routine for usb_driver_set_configuration() */ -static void driver_set_config_work(void *_req) +static void driver_set_config_work(struct work_struct *work) { - struct set_config_request *req = _req; + struct set_config_request *req = + container_of(work, struct set_config_request, work); usb_lock_device(req->udev); usb_set_configuration(req->udev, req->config); @@ -1541,7 +1542,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) return -ENOMEM; req->udev = udev; req->config = config; - INIT_WORK(&req->work, driver_set_config_work, req); + INIT_WORK(&req->work, driver_set_config_work); usb_get_dev(udev); if (!schedule_work(&req->work)) { diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 81cb52564e6..02426d0b9a3 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -203,9 +203,10 @@ static void ksuspend_usb_cleanup(void) #ifdef CONFIG_USB_SUSPEND /* usb_autosuspend_work - callback routine to autosuspend a USB device */ -static void usb_autosuspend_work(void *_udev) +static void usb_autosuspend_work(struct work_struct *work) { - struct usb_device *udev = _udev; + struct usb_device *udev = + container_of(work, struct usb_device, autosuspend.work); usb_pm_lock(udev); udev->auto_pm = 1; @@ -215,7 +216,7 @@ static void usb_autosuspend_work(void *_udev) #else -static void usb_autosuspend_work(void *_udev) +static void usb_autosuspend_work(struct work_struct *work) {} #endif /* CONFIG_USB_SUSPEND */ @@ -304,7 +305,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) #ifdef CONFIG_PM mutex_init(&dev->pm_mutex); - INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev); + INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); #endif return dev; } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 3bd1dfe565c..d15bf22b9a0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1833,9 +1833,9 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) spin_unlock_irqrestore(&dev->req_lock, flags); } -static void eth_work (void *_dev) +static void eth_work (struct work_struct *work) { - struct eth_dev *dev = _dev; + struct eth_dev *dev = container_of(work, struct eth_dev, work); if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) { if (netif_running (dev->net)) @@ -2398,7 +2398,7 @@ autoconf_fail: dev = netdev_priv(net); spin_lock_init (&dev->lock); spin_lock_init (&dev->req_lock); - INIT_WORK (&dev->work, eth_work, dev); + INIT_WORK (&dev->work, eth_work); INIT_LIST_HEAD (&dev->tx_reqs); INIT_LIST_HEAD (&dev->rx_reqs); diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index ef54e310bfc..a9d7119e317 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -163,7 +163,7 @@ struct u132_endp { u16 queue_next; struct urb *urb_list[ENDP_QUEUE_SIZE]; struct list_head urb_more; - struct work_struct scheduler; + struct delayed_work scheduler; }; struct u132_ring { unsigned in_use:1; @@ -171,7 +171,7 @@ struct u132_ring { u8 number; struct u132 *u132; struct u132_endp *curr_endp; - struct work_struct scheduler; + struct delayed_work scheduler; }; #define OHCI_QUIRK_AMD756 0x01 #define OHCI_QUIRK_SUPERIO 0x02 @@ -198,7 +198,7 @@ struct u132 { u32 hc_roothub_portstatus[MAX_ROOT_PORTS]; int flags; unsigned long next_statechange; - struct work_struct monitor; + struct delayed_work monitor; int num_endpoints; struct u132_addr addr[MAX_U132_ADDRS]; struct u132_udev udev[MAX_U132_UDEVS]; @@ -310,7 +310,7 @@ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring, if (delta > 0) { if (queue_delayed_work(workqueue, &ring->scheduler, delta)) return; - } else if (queue_work(workqueue, &ring->scheduler)) + } else if (queue_delayed_work(workqueue, &ring->scheduler, 0)) return; kref_put(&u132->kref, u132_hcd_delete); return; @@ -389,12 +389,8 @@ static inline void u132_endp_init_kref(struct u132 *u132, static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &endp->scheduler, delta)) - kref_get(&endp->kref); - } else if (queue_work(workqueue, &endp->scheduler)) - kref_get(&endp->kref); - return; + if (queue_delayed_work(workqueue, &endp->scheduler, delta)) + kref_get(&endp->kref); } static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp) @@ -410,24 +406,14 @@ static inline void u132_monitor_put_kref(struct u132 *u132) static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &u132->monitor, delta)) { - kref_get(&u132->kref); - } - } else if (queue_work(workqueue, &u132->monitor)) - kref_get(&u132->kref); - return; + if (queue_delayed_work(workqueue, &u132->monitor, delta)) + kref_get(&u132->kref); } static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &u132->monitor, delta)) - return; - } else if (queue_work(workqueue, &u132->monitor)) - return; - kref_put(&u132->kref, u132_hcd_delete); - return; + if (!queue_delayed_work(workqueue, &u132->monitor, delta)) + kref_put(&u132->kref, u132_hcd_delete); } static void u132_monitor_cancel_work(struct u132 *u132) @@ -489,9 +475,9 @@ static int read_roothub_info(struct u132 *u132) return 0; } -static void u132_hcd_monitor_work(void *data) +static void u132_hcd_monitor_work(struct work_struct *work) { - struct u132 *u132 = data; + struct u132 *u132 = container_of(work, struct u132, monitor.work); if (u132->going > 1) { dev_err(&u132->platform_dev->dev, "device has been removed %d\n" , u132->going); @@ -1315,15 +1301,14 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, } } -static void u132_hcd_ring_work_scheduler(void *data); -static void u132_hcd_endp_work_scheduler(void *data); /* * this work function is only executed from the work queue * */ -static void u132_hcd_ring_work_scheduler(void *data) +static void u132_hcd_ring_work_scheduler(struct work_struct *work) { - struct u132_ring *ring = data; + struct u132_ring *ring = + container_of(work, struct u132_ring, scheduler.work); struct u132 *u132 = ring->u132; down(&u132->scheduler_lock); if (ring->in_use) { @@ -1382,10 +1367,11 @@ static void u132_hcd_ring_work_scheduler(void *data) } } -static void u132_hcd_endp_work_scheduler(void *data) +static void u132_hcd_endp_work_scheduler(struct work_struct *work) { struct u132_ring *ring; - struct u132_endp *endp = data; + struct u132_endp *endp = + container_of(work, struct u132_endp, scheduler.work); struct u132 *u132 = endp->u132; down(&u132->scheduler_lock); ring = endp->ring; @@ -1943,7 +1929,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); ring = endp->ring = &u132->ring[0]; @@ -2032,7 +2018,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); endp->dequeueing = 0; @@ -2117,7 +2103,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); ring = endp->ring = &u132->ring[0]; @@ -3096,10 +3082,10 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) ring->number = rings + 1; ring->length = 0; ring->curr_endp = NULL; - INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler, - (void *)ring); + INIT_DELAYED_WORK(&ring->scheduler, + u132_hcd_ring_work_scheduler); } down(&u132->sw_lock); - INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132); + INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work); while (ports-- > 0) { struct u132_port *port = &u132->port[ports]; port->u132 = u132; diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index a49644b7c58..4295bab4f1e 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -969,9 +969,10 @@ static void hid_retry_timeout(unsigned long _hid) } /* Workqueue routine to reset the device or clear a halt */ -static void hid_reset(void *_hid) +static void hid_reset(struct work_struct *work) { - struct hid_device *hid = (struct hid_device *) _hid; + struct hid_device *hid = + container_of(work, struct hid_device, reset_work); int rc_lock, rc = 0; if (test_bit(HID_CLEAR_HALT, &hid->iofl)) { @@ -2043,7 +2044,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) init_waitqueue_head(&hid->wait); - INIT_WORK(&hid->reset_work, hid_reset, hid); + INIT_WORK(&hid->reset_work, hid_reset); setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); spin_lock_init(&hid->inlock); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index ba30ca6a14a..02cbb7fff24 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -76,7 +76,7 @@ struct appledisplay { char *urbdata; /* interrupt URB data buffer */ char *msgdata; /* control message data buffer */ - struct work_struct work; + struct delayed_work work; int button_pressed; spinlock_t lock; }; @@ -117,7 +117,7 @@ static void appledisplay_complete(struct urb *urb) case ACD_BTN_BRIGHT_UP: case ACD_BTN_BRIGHT_DOWN: pdata->button_pressed = 1; - queue_work(wq, &pdata->work); + queue_delayed_work(wq, &pdata->work, 0); break; case ACD_BTN_NONE: default: @@ -184,9 +184,10 @@ static struct backlight_properties appledisplay_bl_data = { .max_brightness = 0xFF }; -static void appledisplay_work(void *private) +static void appledisplay_work(struct work_struct *work) { - struct appledisplay *pdata = private; + struct appledisplay *pdata = + container_of(work, struct appledisplay, work.work); int retval; up(&pdata->bd->sem); @@ -238,7 +239,7 @@ static int appledisplay_probe(struct usb_interface *iface, pdata->udev = udev; spin_lock_init(&pdata->lock); - INIT_WORK(&pdata->work, appledisplay_work, pdata); + INIT_DELAYED_WORK(&pdata->work, appledisplay_work); /* Allocate buffer for control messages */ pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index cb0ba3107d7..18b1925032a 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -156,9 +156,9 @@ struct usb_ftdi { struct usb_device *udev; struct usb_interface *interface; struct usb_class_driver *class; - struct work_struct status_work; - struct work_struct command_work; - struct work_struct respond_work; + struct delayed_work status_work; + struct delayed_work command_work; + struct delayed_work respond_work; struct u132_platform_data platform_data; struct resource resources[0]; struct platform_device platform_dev; @@ -210,23 +210,14 @@ static void ftdi_elan_init_kref(struct usb_ftdi *ftdi) static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) - return; - } else if (queue_work(status_queue, &ftdi->status_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(status_queue, &ftdi->status_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) - kref_get(&ftdi->kref); - } else if (queue_work(status_queue, &ftdi->status_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) @@ -237,25 +228,14 @@ static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(command_queue, &ftdi->command_work, - delta)) - return; - } else if (queue_work(command_queue, &ftdi->command_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(command_queue, &ftdi->command_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(command_queue, &ftdi->command_work, - delta)) - kref_get(&ftdi->kref); - } else if (queue_work(command_queue, &ftdi->command_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(command_queue, &ftdi->command_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) @@ -267,25 +247,14 @@ static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) static void ftdi_response_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(respond_queue, &ftdi->respond_work, - delta)) - return; - } else if (queue_work(respond_queue, &ftdi->respond_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(respond_queue, &ftdi->respond_work, - delta)) - kref_get(&ftdi->kref); - } else if (queue_work(respond_queue, &ftdi->respond_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_response_cancel_work(struct usb_ftdi *ftdi) @@ -475,9 +444,11 @@ static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) return; } -static void ftdi_elan_command_work(void *data) +static void ftdi_elan_command_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, command_work.work); + if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); return; @@ -500,9 +471,10 @@ static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi) return; } -static void ftdi_elan_respond_work(void *data) +static void ftdi_elan_respond_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, respond_work.work); if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); return; @@ -534,9 +506,10 @@ static void ftdi_elan_respond_work(void *data) * after the FTDI has been synchronized * */ -static void ftdi_elan_status_work(void *data) +static void ftdi_elan_status_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, status_work.work); int work_delay_in_msec = 0; if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); @@ -2677,12 +2650,9 @@ static int ftdi_elan_probe(struct usb_interface *interface, ftdi->class = NULL; dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a" "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber); - INIT_WORK(&ftdi->status_work, ftdi_elan_status_work, - (void *)ftdi); - INIT_WORK(&ftdi->command_work, ftdi_elan_command_work, - (void *)ftdi); - INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work, - (void *)ftdi); + INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work); + INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work); + INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work); ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000)); return 0; } else { diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 9110793f81d..9659c79e187 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -81,8 +81,8 @@ struct interfacekit { unsigned char *data; dma_addr_t data_dma; - struct work_struct do_notify; - struct work_struct do_resubmit; + struct delayed_work do_notify; + struct delayed_work do_resubmit; unsigned long input_events; unsigned long sensor_events; }; @@ -374,7 +374,7 @@ static void interfacekit_irq(struct urb *urb) } if (kit->input_events || kit->sensor_events) - schedule_work(&kit->do_notify); + schedule_delayed_work(&kit->do_notify, 0); resubmit: status = usb_submit_urb(urb, SLAB_ATOMIC); @@ -384,9 +384,10 @@ resubmit: kit->udev->devpath, status); } -static void do_notify(void *data) +static void do_notify(struct work_struct *work) { - struct interfacekit *kit = data; + struct interfacekit *kit = + container_of(work, struct interfacekit, do_notify.work); int i; char sysfs_file[8]; @@ -405,9 +406,11 @@ static void do_notify(void *data) } } -static void do_resubmit(void *data) +static void do_resubmit(struct work_struct *work) { - set_outputs(data); + struct interfacekit *kit = + container_of(work, struct interfacekit, do_resubmit.work); + set_outputs(kit); } #define show_set_output(value) \ @@ -575,8 +578,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic kit->udev = usb_get_dev(dev); kit->intf = intf; - INIT_WORK(&kit->do_notify, do_notify, kit); - INIT_WORK(&kit->do_resubmit, do_resubmit, kit); + INIT_DELAYED_WORK(&kit->do_notify, do_notify); + INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit); usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, interfacekit_irq, kit, endpoint->bInterval); diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index c3469b0a67c..2bb4fa572bb 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -41,7 +41,7 @@ struct motorcontrol { unsigned char *data; dma_addr_t data_dma; - struct work_struct do_notify; + struct delayed_work do_notify; unsigned long input_events; unsigned long speed_events; unsigned long exceed_events; @@ -148,7 +148,7 @@ static void motorcontrol_irq(struct urb *urb) set_bit(1, &mc->exceed_events); if (mc->input_events || mc->exceed_events || mc->speed_events) - schedule_work(&mc->do_notify); + schedule_delayed_work(&mc->do_notify, 0); resubmit: status = usb_submit_urb(urb, SLAB_ATOMIC); @@ -159,9 +159,10 @@ resubmit: mc->udev->devpath, status); } -static void do_notify(void *data) +static void do_notify(struct work_struct *work) { - struct motorcontrol *mc = data; + struct motorcontrol *mc = + container_of(work, struct motorcontrol, do_notify.work); int i; char sysfs_file[8]; @@ -348,7 +349,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic mc->udev = usb_get_dev(dev); mc->intf = intf; mc->acceleration[0] = mc->acceleration[1] = 10; - INIT_WORK(&mc->do_notify, do_notify, mc); + INIT_DELAYED_WORK(&mc->do_notify, do_notify); usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, motorcontrol_irq, mc, endpoint->bInterval); diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 7c906a43e49..fa78326d0bf 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -222,7 +222,7 @@ struct kaweth_device int suspend_lowmem_ctrl; int linkstate; int opened; - struct work_struct lowmem_work; + struct delayed_work lowmem_work; struct usb_device *dev; struct net_device *net; @@ -530,9 +530,10 @@ resubmit: kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC); } -static void kaweth_resubmit_tl(void *d) +static void kaweth_resubmit_tl(struct work_struct *work) { - struct kaweth_device *kaweth = (struct kaweth_device *)d; + struct kaweth_device *kaweth = + container_of(work, struct kaweth_device, lowmem_work.work); if (IS_BLOCKED(kaweth->status)) return; @@ -1126,7 +1127,7 @@ err_fw: /* kaweth is zeroed as part of alloc_netdev */ - INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth); + INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); SET_MODULE_OWNER(netdev); diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 69eb0db399d..b5690b3834e 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -1281,9 +1281,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus) static struct workqueue_struct *pegasus_workqueue = NULL; #define CARRIER_CHECK_DELAY (2 * HZ) -static void check_carrier(void *data) +static void check_carrier(struct work_struct *work) { - pegasus_t *pegasus = data; + pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work); set_carrier(pegasus->net); if (!(pegasus->flags & PEGASUS_UNPLUG)) { queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, @@ -1319,7 +1319,7 @@ static int pegasus_probe(struct usb_interface *intf, tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); - INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus); + INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier); pegasus->intf = intf; pegasus->usb = dev; diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index 006438069b6..98f6898cae1 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h @@ -95,7 +95,7 @@ typedef struct pegasus { int dev_index; int intr_interval; struct tasklet_struct rx_tl; - struct work_struct carrier_check; + struct delayed_work carrier_check; struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb; struct sk_buff *rx_pool[RX_SKBS]; struct sk_buff *rx_skb; diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 7672e11c94c..327f9755567 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -782,9 +782,10 @@ static struct ethtool_ops usbnet_ethtool_ops = { * especially now that control transfers can be queued. */ static void -kevent (void *data) +kevent (struct work_struct *work) { - struct usbnet *dev = data; + struct usbnet *dev = + container_of(work, struct usbnet, kevent); int status; /* usb_clear_halt() needs a thread context */ @@ -1146,7 +1147,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) skb_queue_head_init (&dev->done); dev->bh.func = usbnet_bh; dev->bh.data = (unsigned long) dev; - INIT_WORK (&dev->kevent, kevent, dev); + INIT_WORK (&dev->kevent, kevent); dev->delay.function = usbnet_bh; dev->delay.data = (unsigned long) dev; init_timer (&dev->delay); diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index b1b5707bc99..86bcf63b6ba 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -92,6 +92,7 @@ struct aircable_private { struct circ_buf *rx_buf; /* read buffer */ int rx_flags; /* for throttilng */ struct work_struct rx_work; /* work cue for the receiving line */ + struct usb_serial_port *port; /* USB port with which associated */ }; /* Private methods */ @@ -251,10 +252,11 @@ static void aircable_send(struct usb_serial_port *port) schedule_work(&port->work); } -static void aircable_read(void *params) +static void aircable_read(struct work_struct *work) { - struct usb_serial_port *port = params; - struct aircable_private *priv = usb_get_serial_port_data(port); + struct aircable_private *priv = + container_of(work, struct aircable_private, rx_work); + struct usb_serial_port *port = priv->port; struct tty_struct *tty; unsigned char *data; int count; @@ -349,7 +351,8 @@ static int aircable_attach (struct usb_serial *serial) } priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); - INIT_WORK(&priv->rx_work, aircable_read, port); + priv->port = port; + INIT_WORK(&priv->rx_work, aircable_read); usb_set_serial_port_data(serial->port[0], priv); @@ -516,7 +519,7 @@ static void aircable_read_bulk_callback(struct urb *urb) package_length - shift); } } - aircable_read(port); + aircable_read(&priv->rx_work); } /* Schedule the next read _if_ we are still open */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 5e3ac281a2f..83d0e21145b 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -430,13 +430,14 @@ struct digi_port { int dp_in_close; /* close in progress */ wait_queue_head_t dp_close_wait; /* wait queue for close */ struct work_struct dp_wakeup_work; + struct usb_serial_port *dp_port; }; /* Local Function Declarations */ static void digi_wakeup_write( struct usb_serial_port *port ); -static void digi_wakeup_write_lock(void *); +static void digi_wakeup_write_lock(struct work_struct *work); static int digi_write_oob_command( struct usb_serial_port *port, unsigned char *buf, int count, int interruptible ); static int digi_write_inb_command( struct usb_serial_port *port, @@ -598,11 +599,12 @@ static inline long cond_wait_interruptible_timeout_irqrestore( * on writes. */ -static void digi_wakeup_write_lock(void *arg) +static void digi_wakeup_write_lock(struct work_struct *work) { - struct usb_serial_port *port = arg; + struct digi_port *priv = + container_of(work, struct digi_port, dp_wakeup_work); + struct usb_serial_port *port = priv->dp_port; unsigned long flags; - struct digi_port *priv = usb_get_serial_port_data(port); spin_lock_irqsave( &priv->dp_port_lock, flags ); @@ -1702,8 +1704,8 @@ dbg( "digi_startup: TOP" ); init_waitqueue_head( &priv->dp_flush_wait ); priv->dp_in_close = 0; init_waitqueue_head( &priv->dp_close_wait ); - INIT_WORK(&priv->dp_wakeup_work, - digi_wakeup_write_lock, serial->port[i]); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = serial->port[i]; /* initialize write wait queue for this port */ init_waitqueue_head( &serial->port[i]->write_wait ); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 89ce2775be1..72e4d48f51e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -559,7 +559,8 @@ struct ftdi_private { char prev_status, diff_status; /* Used for TIOCMIWAIT */ __u8 rx_flags; /* receive state flags (throttling) */ spinlock_t rx_lock; /* spinlock for receive state */ - struct work_struct rx_work; + struct delayed_work rx_work; + struct usb_serial_port *port; int rx_processed; unsigned long rx_bytes; @@ -593,7 +594,7 @@ static int ftdi_write_room (struct usb_serial_port *port); static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb); static void ftdi_read_bulk_callback (struct urb *urb); -static void ftdi_process_read (void *param); +static void ftdi_process_read (struct work_struct *work); static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); @@ -1201,7 +1202,8 @@ static int ftdi_sio_attach (struct usb_serial *serial) port->read_urb->transfer_buffer_length = BUFSZ; } - INIT_WORK(&priv->rx_work, ftdi_process_read, port); + INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read); + priv->port = port; /* Free port's existing write urb and transfer buffer. */ if (port->write_urb) { @@ -1640,17 +1642,18 @@ static void ftdi_read_bulk_callback (struct urb *urb) priv->rx_bytes += countread; spin_unlock_irqrestore(&priv->rx_lock, flags); - ftdi_process_read(port); + ftdi_process_read(&priv->rx_work.work); } /* ftdi_read_bulk_callback */ -static void ftdi_process_read (void *param) +static void ftdi_process_read (struct work_struct *work) { /* ftdi_process_read */ - struct usb_serial_port *port = (struct usb_serial_port*)param; + struct ftdi_private *priv = + container_of(work, struct ftdi_private, rx_work.work); + struct usb_serial_port *port = priv->port; struct urb *urb; struct tty_struct *tty; - struct ftdi_private *priv; char error_flag; unsigned char *data; @@ -2179,7 +2182,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port) spin_unlock_irqrestore(&priv->rx_lock, flags); if (actually_throttled) - schedule_work(&priv->rx_work); + schedule_delayed_work(&priv->rx_work, 0); } static int __init ftdi_init (void) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 909005107ea..e09a0bfe623 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -120,6 +120,8 @@ struct keyspan_pda_private { int tx_throttled; struct work_struct wakeup_work; struct work_struct unthrottle_work; + struct usb_serial *serial; + struct usb_serial_port *port; }; @@ -175,9 +177,11 @@ static struct usb_device_id id_table_fake_xircom [] = { }; #endif -static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) +static void keyspan_pda_wakeup_write(struct work_struct *work) { - + struct keyspan_pda_private *priv = + container_of(work, struct keyspan_pda_private, wakeup_work); + struct usb_serial_port *port = priv->port; struct tty_struct *tty = port->tty; /* wake up port processes */ @@ -187,8 +191,11 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) tty_wakeup(tty); } -static void keyspan_pda_request_unthrottle( struct usb_serial *serial ) +static void keyspan_pda_request_unthrottle(struct work_struct *work) { + struct keyspan_pda_private *priv = + container_of(work, struct keyspan_pda_private, unthrottle_work); + struct usb_serial *serial = priv->serial; int result; dbg(" request_unthrottle"); @@ -765,11 +772,10 @@ static int keyspan_pda_startup (struct usb_serial *serial) return (1); /* error */ usb_set_serial_port_data(serial->port[0], priv); init_waitqueue_head(&serial->port[0]->write_wait); - INIT_WORK(&priv->wakeup_work, (void *)keyspan_pda_wakeup_write, - (void *)(serial->port[0])); - INIT_WORK(&priv->unthrottle_work, - (void *)keyspan_pda_request_unthrottle, - (void *)(serial)); + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); + INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); + priv->serial = serial; + priv->port = serial->port[0]; return (0); } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c1257d5292f..3d5072f14b8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -533,9 +533,10 @@ void usb_serial_port_softint(struct usb_serial_port *port) schedule_work(&port->work); } -static void usb_serial_port_work(void *private) +static void usb_serial_port_work(struct work_struct *work) { - struct usb_serial_port *port = private; + struct usb_serial_port *port = + container_of(work, struct usb_serial_port, work); struct tty_struct *tty; dbg("%s - port %d", __FUNCTION__, port->number); @@ -799,7 +800,7 @@ int usb_serial_probe(struct usb_interface *interface, port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); - INIT_WORK(&port->work, usb_serial_port_work, port); + INIT_WORK(&port->work, usb_serial_port_work); serial->port[i] = port; } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 4d1cd7aeccd..154c7d29059 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -227,6 +227,7 @@ struct whiteheat_private { struct list_head rx_urbs_submitted; struct list_head rx_urb_q; struct work_struct rx_work; + struct usb_serial_port *port; struct list_head tx_urbs_free; struct list_head tx_urbs_submitted; }; @@ -241,7 +242,7 @@ static void command_port_read_callback(struct urb *urb); static int start_port_read(struct usb_serial_port *port); static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head); static struct list_head *list_first(struct list_head *head); -static void rx_data_softint(void *private); +static void rx_data_softint(struct work_struct *work); static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize); static int firm_open(struct usb_serial_port *port); @@ -424,7 +425,8 @@ static int whiteheat_attach (struct usb_serial *serial) spin_lock_init(&info->lock); info->flags = 0; info->mcr = 0; - INIT_WORK(&info->rx_work, rx_data_softint, port); + INIT_WORK(&info->rx_work, rx_data_softint); + info->port = port; INIT_LIST_HEAD(&info->rx_urbs_free); INIT_LIST_HEAD(&info->rx_urbs_submitted); @@ -949,7 +951,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port) spin_unlock_irqrestore(&info->lock, flags); if (actually_throttled) - rx_data_softint(port); + rx_data_softint(&info->rx_work); return; } @@ -1400,10 +1402,11 @@ static struct list_head *list_first(struct list_head *head) } -static void rx_data_softint(void *private) +static void rx_data_softint(struct work_struct *work) { - struct usb_serial_port *port = (struct usb_serial_port *)private; - struct whiteheat_private *info = usb_get_serial_port_data(port); + struct whiteheat_private *info = + container_of(work, struct whiteheat_private, rx_work); + struct usb_serial_port *port = info->port; struct tty_struct *tty = port->tty; struct whiteheat_urb_wrap *wrap; struct urb *urb; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 302174b8e47..31f476a6479 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -383,9 +383,9 @@ static void fbcon_update_softback(struct vc_data *vc) softback_top = 0; } -static void fb_flashcursor(void *private) +static void fb_flashcursor(struct work_struct *work) { - struct fb_info *info = private; + struct fb_info *info = container_of(work, struct fb_info, queue); struct fbcon_ops *ops = info->fbcon_par; struct display *p; struct vc_data *vc = NULL; @@ -442,7 +442,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info) if ((!info->queue.func || info->queue.func == fb_flashcursor) && !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) { if (!info->queue.func) - INIT_WORK(&info->queue, fb_flashcursor, info); + INIT_WORK(&info->queue, fb_flashcursor); init_timer(&ops->cursor_timer); ops->cursor_timer.function = cursor_timer_handler; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 8a8ae55a740..38eb0b69c2d 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -964,9 +964,10 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) * Our LCD controller task (which is called when we blank or unblank) * via keventd. */ -static void pxafb_task(void *dummy) +static void pxafb_task(struct work_struct *work) { - struct pxafb_info *fbi = dummy; + struct pxafb_info *fbi = + container_of(work, struct pxafb_info, task); u_int state = xchg(&fbi->task_state, -1); set_ctrlr_state(fbi, state); @@ -1159,7 +1160,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) } init_waitqueue_head(&fbi->ctrlr_wait); - INIT_WORK(&fbi->task, pxafb_task, fbi); + INIT_WORK(&fbi->task, pxafb_task); init_MUTEX(&fbi->ctrlr_sem); return fbi; diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 90a79c78454..944273c3dbf 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c @@ -110,8 +110,8 @@ struct v9fs_mux_rpc { }; static int v9fs_poll_proc(void *); -static void v9fs_read_work(void *); -static void v9fs_write_work(void *); +static void v9fs_read_work(struct work_struct *work); +static void v9fs_write_work(struct work_struct *work); static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, poll_table * p); static u16 v9fs_mux_get_tag(struct v9fs_mux_data *); @@ -297,8 +297,8 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, m->rbuf = NULL; m->wpos = m->wsize = 0; m->wbuf = NULL; - INIT_WORK(&m->rq, v9fs_read_work, m); - INIT_WORK(&m->wq, v9fs_write_work, m); + INIT_WORK(&m->rq, v9fs_read_work); + INIT_WORK(&m->wq, v9fs_write_work); m->wsched = 0; memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); m->poll_task = NULL; @@ -458,13 +458,13 @@ static int v9fs_poll_proc(void *a) /** * v9fs_write_work - called when a transport can send some data */ -static void v9fs_write_work(void *a) +static void v9fs_write_work(struct work_struct *work) { int n, err; struct v9fs_mux_data *m; struct v9fs_req *req; - m = a; + m = container_of(work, struct v9fs_mux_data, wq); if (m->err < 0) { clear_bit(Wworksched, &m->wsched); @@ -564,7 +564,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) /** * v9fs_read_work - called when there is some data to be read from a transport */ -static void v9fs_read_work(void *a) +static void v9fs_read_work(struct work_struct *work) { int n, err; struct v9fs_mux_data *m; @@ -572,7 +572,7 @@ static void v9fs_read_work(void *a) struct v9fs_fcall *rcall; char *rbuf; - m = a; + m = container_of(work, struct v9fs_mux_data, rq); if (m->err < 0) return; @@ -53,13 +53,13 @@ static kmem_cache_t *kioctx_cachep; static struct workqueue_struct *aio_wq; /* Used for rare fput completion. */ -static void aio_fput_routine(void *); -static DECLARE_WORK(fput_work, aio_fput_routine, NULL); +static void aio_fput_routine(struct work_struct *); +static DECLARE_WORK(fput_work, aio_fput_routine); static DEFINE_SPINLOCK(fput_lock); static LIST_HEAD(fput_head); -static void aio_kick_handler(void *); +static void aio_kick_handler(struct work_struct *); static void aio_queue_work(struct kioctx *); /* aio_setup @@ -227,7 +227,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) INIT_LIST_HEAD(&ctx->active_reqs); INIT_LIST_HEAD(&ctx->run_list); - INIT_WORK(&ctx->wq, aio_kick_handler, ctx); + INIT_DELAYED_WORK(&ctx->wq, aio_kick_handler); if (aio_setup_ring(ctx) < 0) goto out_freectx; @@ -469,7 +469,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) wake_up(&ctx->wait); } -static void aio_fput_routine(void *data) +static void aio_fput_routine(struct work_struct *data) { spin_lock_irq(&fput_lock); while (likely(!list_empty(&fput_head))) { @@ -857,9 +857,9 @@ static inline void aio_run_all_iocbs(struct kioctx *ctx) * space. * Run on aiod's context. */ -static void aio_kick_handler(void *data) +static void aio_kick_handler(struct work_struct *work) { - struct kioctx *ctx = data; + struct kioctx *ctx = container_of(work, struct kioctx, wq.work); mm_segment_t oldfs = get_fs(); int requeue; @@ -874,7 +874,7 @@ static void aio_kick_handler(void *data) * we're in a worker thread already, don't use queue_delayed_work, */ if (requeue) - queue_work(aio_wq, &ctx->wq); + queue_delayed_work(aio_wq, &ctx->wq, 0); } @@ -940,16 +940,16 @@ static void bio_release_pages(struct bio *bio) * run one bio_put() against the BIO. */ -static void bio_dirty_fn(void *data); +static void bio_dirty_fn(struct work_struct *work); -static DECLARE_WORK(bio_dirty_work, bio_dirty_fn, NULL); +static DECLARE_WORK(bio_dirty_work, bio_dirty_fn); static DEFINE_SPINLOCK(bio_dirty_lock); static struct bio *bio_dirty_list; /* * This runs in process context */ -static void bio_dirty_fn(void *data) +static void bio_dirty_fn(struct work_struct *work) { unsigned long flags; struct bio *bio; diff --git a/fs/file.c b/fs/file.c index 8e81775c5dc..3787e82f54c 100644 --- a/fs/file.c +++ b/fs/file.c @@ -91,8 +91,10 @@ out: spin_unlock(&fddef->lock); } -static void free_fdtable_work(struct fdtable_defer *f) +static void free_fdtable_work(struct work_struct *work) { + struct fdtable_defer *f = + container_of(work, struct fdtable_defer, wq); struct fdtable *fdt; spin_lock_bh(&f->lock); @@ -351,7 +353,7 @@ static void __devinit fdtable_defer_list_init(int cpu) { struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu); spin_lock_init(&fddef->lock); - INIT_WORK(&fddef->wq, (void (*)(void *))free_fdtable_work, fddef); + INIT_WORK(&fddef->wq, free_fdtable_work); init_timer(&fddef->timer); fddef->timer.data = (unsigned long)fddef; fddef->timer.function = fdtable_timer; diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 78fe0fae23f..55f5333dae9 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -35,7 +35,7 @@ struct greedy { struct gfs2_holder gr_gh; - struct work_struct gr_work; + struct delayed_work gr_work; }; struct gfs2_gl_hash_bucket { @@ -1368,9 +1368,9 @@ static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state, glops->go_xmote_th(gl, state, flags); } -static void greedy_work(void *data) +static void greedy_work(struct work_struct *work) { - struct greedy *gr = data; + struct greedy *gr = container_of(work, struct greedy, gr_work.work); struct gfs2_holder *gh = &gr->gr_gh; struct gfs2_glock *gl = gh->gh_gl; const struct gfs2_glock_operations *glops = gl->gl_ops; @@ -1422,7 +1422,7 @@ int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time) gfs2_holder_init(gl, 0, 0, gh); set_bit(HIF_GREEDY, &gh->gh_iflags); - INIT_WORK(&gr->gr_work, greedy_work, gr); + INIT_DELAYED_WORK(&gr->gr_work, greedy_work); set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); schedule_delayed_work(&gr->gr_work, time); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 42e3bef270c..72dad552aa0 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -577,12 +577,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) server->rcv.ptr = (unsigned char*)&server->rcv.buf; server->rcv.len = 10; server->rcv.state = 0; - INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc, server); - INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc, server); + INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); + INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); sock->sk->sk_write_space = ncp_tcp_write_space; } else { - INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc, server); - INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc, server); + INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); + INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); server->timeout_tm.data = (unsigned long)server; server->timeout_tm.function = ncpdgram_timeout_call; } diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index 11c2b252ebe..e496d8b65e9 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c @@ -350,9 +350,10 @@ static void info_server(struct ncp_server *server, unsigned int id, const void * } } -void ncpdgram_rcv_proc(void *s) +void ncpdgram_rcv_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); struct socket* sock; sock = server->ncp_sock; @@ -468,9 +469,10 @@ static void __ncpdgram_timeout_proc(struct ncp_server *server) } } -void ncpdgram_timeout_proc(void *s) +void ncpdgram_timeout_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, timeout_tq); mutex_lock(&server->rcv.creq_mutex); __ncpdgram_timeout_proc(server); mutex_unlock(&server->rcv.creq_mutex); @@ -652,18 +654,20 @@ skipdata:; } } -void ncp_tcp_rcv_proc(void *s) +void ncp_tcp_rcv_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); mutex_lock(&server->rcv.creq_mutex); __ncptcp_rcv_proc(server); mutex_unlock(&server->rcv.creq_mutex); } -void ncp_tcp_tx_proc(void *s) +void ncp_tcp_tx_proc(struct work_struct *work) { - struct ncp_server *server = s; + struct ncp_server *server = + container_of(work, struct ncp_server, tx.tq); mutex_lock(&server->rcv.creq_mutex); __ncptcp_try_send(server); diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 5fea638743e..23ab145daa2 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -143,7 +143,7 @@ static struct nfs_client *nfs_alloc_client(const char *hostname, INIT_LIST_HEAD(&clp->cl_state_owners); INIT_LIST_HEAD(&clp->cl_unused); spin_lock_init(&clp->cl_lock); - INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); + INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); clp->cl_boot_time = CURRENT_TIME; clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index ec1114b33d8..371b804e7cc 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -18,10 +18,10 @@ #define NFSDBG_FACILITY NFSDBG_VFS -static void nfs_expire_automounts(void *list); +static void nfs_expire_automounts(struct work_struct *work); LIST_HEAD(nfs_automount_list); -static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list); +static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts); int nfs_mountpoint_expiry_timeout = 500 * HZ; static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, @@ -164,9 +164,9 @@ struct inode_operations nfs_referral_inode_operations = { .follow_link = nfs_follow_mountpoint, }; -static void nfs_expire_automounts(void *data) +static void nfs_expire_automounts(struct work_struct *work) { - struct list_head *list = (struct list_head *)data; + struct list_head *list = &nfs_automount_list; mark_mounts_for_expiry(list); if (!list_empty(list)) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 6f346677332..c26cd978c7c 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -185,7 +185,7 @@ extern const u32 nfs4_fs_locations_bitmap[2]; extern void nfs4_schedule_state_renewal(struct nfs_client *); extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); extern void nfs4_kill_renewd(struct nfs_client *); -extern void nfs4_renew_state(void *); +extern void nfs4_renew_state(struct work_struct *); /* nfs4state.c */ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp); diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index 7b6df1852e7..823298561c0 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c @@ -59,9 +59,10 @@ #define NFSDBG_FACILITY NFSDBG_PROC void -nfs4_renew_state(void *data) +nfs4_renew_state(struct work_struct *work) { - struct nfs_client *clp = (struct nfs_client *)data; + struct nfs_client *clp = + container_of(work, struct nfs_client, cl_renewd.work); struct rpc_cred *cred; long lease, timeout; unsigned long last, now; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 293b6495829..e431e93ab50 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1829,9 +1829,8 @@ out: } static struct workqueue_struct *laundry_wq; -static struct work_struct laundromat_work; -static void laundromat_main(void *); -static DECLARE_WORK(laundromat_work, laundromat_main, NULL); +static void laundromat_main(struct work_struct *); +static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main); __be32 nfsd4_renew(clientid_t *clid) @@ -1940,7 +1939,7 @@ nfs4_laundromat(void) } void -laundromat_main(void *not_used) +laundromat_main(struct work_struct *not_used) { time_t t; diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 85a048b7a67..edc91ca3792 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1197,10 +1197,12 @@ int ocfs2_flush_truncate_log(struct ocfs2_super *osb) return status; } -static void ocfs2_truncate_log_worker(void *data) +static void ocfs2_truncate_log_worker(struct work_struct *work) { int status; - struct ocfs2_super *osb = data; + struct ocfs2_super *osb = + container_of(work, struct ocfs2_super, + osb_truncate_log_wq.work); mlog_entry_void(); @@ -1432,7 +1434,8 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) /* ocfs2_truncate_log_shutdown keys on the existence of * osb->osb_tl_inode so we don't set any of the osb variables * until we're sure all is well. */ - INIT_WORK(&osb->osb_truncate_log_wq, ocfs2_truncate_log_worker, osb); + INIT_DELAYED_WORK(&osb->osb_truncate_log_wq, + ocfs2_truncate_log_worker); osb->osb_tl_bh = tl_bh; osb->osb_tl_inode = tl_inode; diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 305cba3681f..4cd9a958045 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -141,7 +141,7 @@ struct o2hb_region { * recognizes a node going up and down in one iteration */ u64 hr_generation; - struct work_struct hr_write_timeout_work; + struct delayed_work hr_write_timeout_work; unsigned long hr_last_timeout_start; /* Used during o2hb_check_slot to hold a copy of the block @@ -156,9 +156,11 @@ struct o2hb_bio_wait_ctxt { int wc_error; }; -static void o2hb_write_timeout(void *arg) +static void o2hb_write_timeout(struct work_struct *work) { - struct o2hb_region *reg = arg; + struct o2hb_region *reg = + container_of(work, struct o2hb_region, + hr_write_timeout_work.work); mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u " "milliseconds\n", reg->hr_dev_name, @@ -1404,7 +1406,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, goto out; } - INIT_WORK(®->hr_write_timeout_work, o2hb_write_timeout, reg); + INIT_DELAYED_WORK(®->hr_write_timeout_work, o2hb_write_timeout); /* * A node is considered live after it has beat LIVE_THRESHOLD diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c index 7bba98fbfc1..4705d659fe5 100644 --- a/fs/ocfs2/cluster/quorum.c +++ b/fs/ocfs2/cluster/quorum.c @@ -88,7 +88,7 @@ void o2quo_disk_timeout(void) o2quo_fence_self(); } -static void o2quo_make_decision(void *arg) +static void o2quo_make_decision(struct work_struct *work) { int quorum; int lowest_hb, lowest_reachable = 0, fence = 0; @@ -306,7 +306,7 @@ void o2quo_init(void) struct o2quo_state *qs = &o2quo_state; spin_lock_init(&qs->qs_lock); - INIT_WORK(&qs->qs_work, o2quo_make_decision, NULL); + INIT_WORK(&qs->qs_work, o2quo_make_decision); } void o2quo_exit(void) diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index b650efa8c8b..9b3209dc0b1 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -140,11 +140,11 @@ static int o2net_sys_err_translations[O2NET_ERR_MAX] = [O2NET_ERR_DIED] = -EHOSTDOWN,}; /* can't quite avoid *all* internal declarations :/ */ -static void o2net_sc_connect_completed(void *arg); -static void o2net_rx_until_empty(void *arg); -static void o2net_shutdown_sc(void *arg); +static void o2net_sc_connect_completed(struct work_struct *work); +static void o2net_rx_until_empty(struct work_struct *work); +static void o2net_shutdown_sc(struct work_struct *work); static void o2net_listen_data_ready(struct sock *sk, int bytes); -static void o2net_sc_send_keep_req(void *arg); +static void o2net_sc_send_keep_req(struct work_struct *work); static void o2net_idle_timer(unsigned long data); static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); @@ -308,10 +308,10 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node) o2nm_node_get(node); sc->sc_node = node; - INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed, sc); - INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty, sc); - INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc, sc); - INIT_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req, sc); + INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed); + INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty); + INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc); + INIT_DELAYED_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req); init_timer(&sc->sc_idle_timeout); sc->sc_idle_timeout.function = o2net_idle_timer; @@ -342,7 +342,7 @@ static void o2net_sc_queue_work(struct o2net_sock_container *sc, sc_put(sc); } static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc, - struct work_struct *work, + struct delayed_work *work, int delay) { sc_get(sc); @@ -350,7 +350,7 @@ static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc, sc_put(sc); } static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc, - struct work_struct *work) + struct delayed_work *work) { if (cancel_delayed_work(work)) sc_put(sc); @@ -564,9 +564,11 @@ static void o2net_ensure_shutdown(struct o2net_node *nn, * ourselves as state_change couldn't get the nn_lock and call set_nn_state * itself. */ -static void o2net_shutdown_sc(void *arg) +static void o2net_shutdown_sc(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_shutdown_work); struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); sclog(sc, "shutting down\n"); @@ -1201,9 +1203,10 @@ out: /* this work func is triggerd by data ready. it reads until it can read no * more. it interprets 0, eof, as fatal. if data_ready hits while we're doing * our work the work struct will be marked and we'll be called again. */ -static void o2net_rx_until_empty(void *arg) +static void o2net_rx_until_empty(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, sc_rx_work); int ret; do { @@ -1249,9 +1252,11 @@ static int o2net_set_nodelay(struct socket *sock) /* called when a connect completes and after a sock is accepted. the * rx path will see the response and mark the sc valid */ -static void o2net_sc_connect_completed(void *arg) +static void o2net_sc_connect_completed(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_connect_work); mlog(ML_MSG, "sc sending handshake with ver %llu id %llx\n", (unsigned long long)O2NET_PROTOCOL_VERSION, @@ -1262,9 +1267,11 @@ static void o2net_sc_connect_completed(void *arg) } /* this is called as a work_struct func. */ -static void o2net_sc_send_keep_req(void *arg) +static void o2net_sc_send_keep_req(struct work_struct *work) { - struct o2net_sock_container *sc = arg; + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_keepalive_work.work); o2net_sendpage(sc, o2net_keep_req, sizeof(*o2net_keep_req)); sc_put(sc); @@ -1314,14 +1321,15 @@ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc) * having a connect attempt fail, etc. This centralizes the logic which decides * if a connect attempt should be made or if we should give up and all future * transmit attempts should fail */ -static void o2net_start_connect(void *arg) +static void o2net_start_connect(struct work_struct *work) { - struct o2net_node *nn = arg; + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_connect_work.work); struct o2net_sock_container *sc = NULL; struct o2nm_node *node = NULL, *mynode = NULL; struct socket *sock = NULL; struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; - int ret = 0; + int ret = 0, stop; /* if we're greater we initiate tx, otherwise we accept */ if (o2nm_this_node() <= o2net_num_from_nn(nn)) @@ -1342,10 +1350,9 @@ static void o2net_start_connect(void *arg) spin_lock(&nn->nn_lock); /* see if we already have one pending or have given up */ - if (nn->nn_sc || nn->nn_persistent_error) - arg = NULL; + stop = (nn->nn_sc || nn->nn_persistent_error); spin_unlock(&nn->nn_lock); - if (arg == NULL) /* *shrug*, needed some indicator */ + if (stop) goto out; nn->nn_last_connect_attempt = jiffies; @@ -1421,9 +1428,10 @@ out: return; } -static void o2net_connect_expired(void *arg) +static void o2net_connect_expired(struct work_struct *work) { - struct o2net_node *nn = arg; + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_connect_expired.work); spin_lock(&nn->nn_lock); if (!nn->nn_sc_valid) { @@ -1436,9 +1444,10 @@ static void o2net_connect_expired(void *arg) spin_unlock(&nn->nn_lock); } -static void o2net_still_up(void *arg) +static void o2net_still_up(struct work_struct *work) { - struct o2net_node *nn = arg; + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_still_up.work); o2quo_hb_still_up(o2net_num_from_nn(nn)); } @@ -1644,9 +1653,9 @@ out: return ret; } -static void o2net_accept_many(void *arg) +static void o2net_accept_many(struct work_struct *work) { - struct socket *sock = arg; + struct socket *sock = o2net_listen_sock; while (o2net_accept_one(sock) == 0) cond_resched(); } @@ -1700,7 +1709,7 @@ static int o2net_open_listening_sock(__be16 port) write_unlock_bh(&sock->sk->sk_callback_lock); o2net_listen_sock = sock; - INIT_WORK(&o2net_listen_work, o2net_accept_many, sock); + INIT_WORK(&o2net_listen_work, o2net_accept_many); sock->sk->sk_reuse = 1; ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); @@ -1819,9 +1828,10 @@ int o2net_init(void) struct o2net_node *nn = o2net_nn_from_num(i); spin_lock_init(&nn->nn_lock); - INIT_WORK(&nn->nn_connect_work, o2net_start_connect, nn); - INIT_WORK(&nn->nn_connect_expired, o2net_connect_expired, nn); - INIT_WORK(&nn->nn_still_up, o2net_still_up, nn); + INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect); + INIT_DELAYED_WORK(&nn->nn_connect_expired, + o2net_connect_expired); + INIT_DELAYED_WORK(&nn->nn_still_up, o2net_still_up); /* until we see hb from a node we'll return einval */ nn->nn_persistent_error = -ENOTCONN; init_waitqueue_head(&nn->nn_sc_wq); diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index 4b46aac7d24..daebbd3a2c8 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h @@ -86,18 +86,18 @@ struct o2net_node { * connect attempt fails and so can be self-arming. shutdown is * careful to first mark the nn such that no connects will be attempted * before canceling delayed connect work and flushing the queue. */ - struct work_struct nn_connect_work; + struct delayed_work nn_connect_work; unsigned long nn_last_connect_attempt; /* this is queued as nodes come up and is canceled when a connection is * established. this expiring gives up on the node and errors out * transmits */ - struct work_struct nn_connect_expired; + struct delayed_work nn_connect_expired; /* after we give up on a socket we wait a while before deciding * that it is still heartbeating and that we should do some * quorum work */ - struct work_struct nn_still_up; + struct delayed_work nn_still_up; }; struct o2net_sock_container { @@ -129,7 +129,7 @@ struct o2net_sock_container { struct work_struct sc_shutdown_work; struct timer_list sc_idle_timeout; - struct work_struct sc_keepalive_work; + struct delayed_work sc_keepalive_work; unsigned sc_handshake_ok:1; diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index fa968180b07..6b6ff76538c 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -153,7 +153,7 @@ static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned * called functions that cannot be directly called from the * net message handlers for some reason, usually because * they need to send net messages of their own. */ -void dlm_dispatch_work(void *data); +void dlm_dispatch_work(struct work_struct *work); struct dlm_lock_resource; struct dlm_work_item; diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index f6cdab3a2c6..420a375a394 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -1297,7 +1297,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, spin_lock_init(&dlm->work_lock); INIT_LIST_HEAD(&dlm->work_list); - INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work, dlm); + INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work); kref_init(&dlm->dlm_refs); dlm->dlm_state = DLM_CTXT_NEW; diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 9d950d7cea3..fb3e2b0817f 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -153,9 +153,10 @@ static inline void dlm_reset_recovery(struct dlm_ctxt *dlm) } /* Worker function used during recovery. */ -void dlm_dispatch_work(void *data) +void dlm_dispatch_work(struct work_struct *work) { - struct dlm_ctxt *dlm = (struct dlm_ctxt *)data; + struct dlm_ctxt *dlm = + container_of(work, struct dlm_ctxt, dispatched_work); LIST_HEAD(tmp_list); struct list_head *iter, *iter2; struct dlm_work_item *item; diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c index eead48bbfac..7d2f578b267 100644 --- a/fs/ocfs2/dlm/userdlm.c +++ b/fs/ocfs2/dlm/userdlm.c @@ -171,15 +171,14 @@ static inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres) BUG(); } -static void user_dlm_unblock_lock(void *opaque); +static void user_dlm_unblock_lock(struct work_struct *work); static void __user_dlm_queue_lockres(struct user_lock_res *lockres) { if (!(lockres->l_flags & USER_LOCK_QUEUED)) { user_dlm_grab_inode_ref(lockres); - INIT_WORK(&lockres->l_work, user_dlm_unblock_lock, - lockres); + INIT_WORK(&lockres->l_work, user_dlm_unblock_lock); queue_work(user_dlm_worker, &lockres->l_work); lockres->l_flags |= USER_LOCK_QUEUED; @@ -279,10 +278,11 @@ static inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres) iput(inode); } -static void user_dlm_unblock_lock(void *opaque) +static void user_dlm_unblock_lock(struct work_struct *work) { int new_level, status; - struct user_lock_res *lockres = (struct user_lock_res *) opaque; + struct user_lock_res *lockres = + container_of(work, struct user_lock_res, l_work); struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); mlog(0, "processing lockres %.*s\n", lockres->l_namelen, diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index c0ad7cb5952..1d7f4ab1e5e 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -703,11 +703,12 @@ struct ocfs2_la_recovery_item { * NOTE: This function can and will sleep on recovery of other nodes * during cluster locking, just like any other ocfs2 process. */ -void ocfs2_complete_recovery(void *data) +void ocfs2_complete_recovery(struct work_struct *work) { int ret; - struct ocfs2_super *osb = data; - struct ocfs2_journal *journal = osb->journal; + struct ocfs2_journal *journal = + container_of(work, struct ocfs2_journal, j_recovery_work); + struct ocfs2_super *osb = journal->j_osb; struct ocfs2_dinode *la_dinode, *tl_dinode; struct ocfs2_la_recovery_item *item; struct list_head *p, *n; diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index d86cb960b7e..899112ad813 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -133,7 +133,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, } /* Exported only for the journal struct init code in super.c. Do not call. */ -void ocfs2_complete_recovery(void *data); +void ocfs2_complete_recovery(struct work_struct *work); /* * Journal Control: diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 078883772bd..b767fd7da6e 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -285,7 +285,7 @@ struct ocfs2_super /* Truncate log info */ struct inode *osb_tl_inode; struct buffer_head *osb_tl_bh; - struct work_struct osb_truncate_log_wq; + struct delayed_work osb_truncate_log_wq; struct ocfs2_node_map osb_recovering_orphan_dirs; unsigned int *osb_orphan_wipes; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index b0992573dee..d9b4214a12d 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1365,7 +1365,7 @@ static int ocfs2_initialize_super(struct super_block *sb, spin_lock_init(&journal->j_lock); journal->j_trans_id = (unsigned long) 1; INIT_LIST_HEAD(&journal->j_la_cleanups); - INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery, osb); + INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); journal->j_state = OCFS2_JOURNAL_FREE; /* get some pseudo constants for clustersize bits */ diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index ac93174c963..7280a23ef34 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -104,7 +104,7 @@ static int release_journal_dev(struct super_block *super, struct reiserfs_journal *journal); static int dirty_one_transaction(struct super_block *s, struct reiserfs_journal_list *jl); -static void flush_async_commits(void *p); +static void flush_async_commits(struct work_struct *work); static void queue_log_writer(struct super_block *s); /* values for join in do_journal_begin_r */ @@ -2836,7 +2836,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, if (reiserfs_mounted_fs_count <= 1) commit_wq = create_workqueue("reiserfs"); - INIT_WORK(&journal->j_work, flush_async_commits, p_s_sb); + INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); + journal->j_work_sb = p_s_sb; return 0; free_and_return: free_journal_ram(p_s_sb); @@ -3447,10 +3448,11 @@ int journal_end_sync(struct reiserfs_transaction_handle *th, /* ** writeback the pending async commits to disk */ -static void flush_async_commits(void *p) +static void flush_async_commits(struct work_struct *work) { - struct super_block *p_s_sb = p; - struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); + struct reiserfs_journal *journal = + container_of(work, struct reiserfs_journal, j_work.work); + struct super_block *p_s_sb = journal->j_work_sb; struct reiserfs_journal_list *jl; struct list_head *entry; diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 09360cf1e1f..8e6b56fc1ca 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -149,9 +149,10 @@ xfs_destroy_ioend( */ STATIC void xfs_end_bio_delalloc( - void *data) + struct work_struct *work) { - xfs_ioend_t *ioend = data; + xfs_ioend_t *ioend = + container_of(work, xfs_ioend_t, io_work); xfs_destroy_ioend(ioend); } @@ -161,9 +162,10 @@ xfs_end_bio_delalloc( */ STATIC void xfs_end_bio_written( - void *data) + struct work_struct *work) { - xfs_ioend_t *ioend = data; + xfs_ioend_t *ioend = + container_of(work, xfs_ioend_t, io_work); xfs_destroy_ioend(ioend); } @@ -176,9 +178,10 @@ xfs_end_bio_written( */ STATIC void xfs_end_bio_unwritten( - void *data) + struct work_struct *work) { - xfs_ioend_t *ioend = data; + xfs_ioend_t *ioend = + container_of(work, xfs_ioend_t, io_work); bhv_vnode_t *vp = ioend->io_vnode; xfs_off_t offset = ioend->io_offset; size_t size = ioend->io_size; @@ -220,11 +223,11 @@ xfs_alloc_ioend( ioend->io_size = 0; if (type == IOMAP_UNWRITTEN) - INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend); + INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten); else if (type == IOMAP_DELAY) - INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc, ioend); + INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc); else - INIT_WORK(&ioend->io_work, xfs_end_bio_written, ioend); + INIT_WORK(&ioend->io_work, xfs_end_bio_written); return ioend; } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index d3382843698..eef4a0ba11e 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -994,9 +994,10 @@ xfs_buf_wait_unpin( STATIC void xfs_buf_iodone_work( - void *v) + struct work_struct *work) { - xfs_buf_t *bp = (xfs_buf_t *)v; + xfs_buf_t *bp = + container_of(work, xfs_buf_t, b_iodone_work); if (bp->b_iodone) (*(bp->b_iodone))(bp); @@ -1017,10 +1018,10 @@ xfs_buf_ioend( if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) { if (schedule) { - INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work, bp); + INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work); queue_work(xfslogd_workqueue, &bp->b_iodone_work); } else { - xfs_buf_iodone_work(bp); + xfs_buf_iodone_work(&bp->b_iodone_work); } } else { up(&bp->b_iodonesema); diff --git a/include/asm-arm/arch-omap/irda.h b/include/asm-arm/arch-omap/irda.h index 805ae3575e4..345a649ec83 100644 --- a/include/asm-arm/arch-omap/irda.h +++ b/include/asm-arm/arch-omap/irda.h @@ -24,7 +24,7 @@ struct omap_irda_config { /* Very specific to the needs of some platforms (h3,h4) * having calls which can sleep in irda_set_speed. */ - struct work_struct gpio_expa; + struct delayed_work gpio_expa; int rx_channel; int tx_channel; unsigned long dest_start; diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h index 51a16624252..a6c024e2506 100644 --- a/include/asm-i386/atomic.h +++ b/include/asm-i386/atomic.h @@ -14,7 +14,7 @@ * on us. We need to use _exactly_ the address the user gave us, * not some alias that contains the same information. */ -typedef struct { volatile int counter; } atomic_t; +typedef struct { int counter; } atomic_t; #define ATOMIC_INIT(i) { (i) } diff --git a/include/asm-i386/spinlock_types.h b/include/asm-i386/spinlock_types.h index 59efe849f35..4da9345c150 100644 --- a/include/asm-i386/spinlock_types.h +++ b/include/asm-i386/spinlock_types.h @@ -6,13 +6,13 @@ #endif typedef struct { - volatile unsigned int slock; + unsigned int slock; } raw_spinlock_t; #define __RAW_SPIN_LOCK_UNLOCKED { 1 } typedef struct { - volatile unsigned int lock; + unsigned int lock; } raw_rwlock_t; #define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h index 45e7a2fd168..7b8f874f842 100644 --- a/include/asm-m68knommu/irq.h +++ b/include/asm-m68knommu/irq.h @@ -86,5 +86,6 @@ extern void (*mach_disable_irq)(unsigned int); #define enable_irq(x) do { } while (0) #define disable_irq(x) do { } while (0) #define disable_irq_nosync(x) disable_irq(x) +#define irq_canonicalize(irq) (irq) #endif /* _M68K_IRQ_H_ */ diff --git a/include/asm-m68knommu/rtc.h b/include/asm-m68knommu/rtc.h new file mode 100644 index 00000000000..eaf18ec83c8 --- /dev/null +++ b/include/asm-m68knommu/rtc.h @@ -0,0 +1 @@ +#include <asm-m68k/rtc.h> diff --git a/include/asm-m68knommu/ucontext.h b/include/asm-m68knommu/ucontext.h index 5d570cedbb0..713a27f901c 100644 --- a/include/asm-m68knommu/ucontext.h +++ b/include/asm-m68knommu/ucontext.h @@ -5,21 +5,17 @@ typedef int greg_t; #define NGREG 18 typedef greg_t gregset_t[NGREG]; -#ifdef CONFIG_FPU typedef struct fpregset { int f_pcr; int f_psr; int f_fpiaddr; int f_fpregs[8][3]; } fpregset_t; -#endif struct mcontext { int version; gregset_t gregs; -#ifdef CONFIG_FPU fpregset_t fpregs; -#endif }; #define MCONTEXT_VERSION 2 @@ -29,9 +25,7 @@ struct ucontext { struct ucontext *uc_link; stack_t uc_stack; struct mcontext uc_mcontext; -#ifdef CONFIG_FPU unsigned long uc_filler[80]; -#endif sigset_t uc_sigmask; /* mask last for extensibility */ }; diff --git a/include/asm-mips/i8259.h b/include/asm-mips/i8259.h index 0214abe3f0a..4df8d8b118c 100644 --- a/include/asm-mips/i8259.h +++ b/include/asm-mips/i8259.h @@ -19,10 +19,31 @@ #include <asm/io.h> +/* i8259A PIC registers */ +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_IMR 0x21 +#define PIC_MASTER_ISR PIC_MASTER_CMD +#define PIC_MASTER_POLL PIC_MASTER_ISR +#define PIC_MASTER_OCW3 PIC_MASTER_ISR +#define PIC_SLAVE_CMD 0xa0 +#define PIC_SLAVE_IMR 0xa1 + +/* i8259A PIC related value */ +#define PIC_CASCADE_IR 2 +#define MASTER_ICW4_DEFAULT 0x01 +#define SLAVE_ICW4_DEFAULT 0x01 +#define PIC_ICW4_AEOI 2 + extern spinlock_t i8259A_lock; +extern void init_8259A(int auto_eoi); +extern void enable_8259A_irq(unsigned int irq); +extern void disable_8259A_irq(unsigned int irq); + extern void init_i8259_irqs(void); +#define I8259A_IRQ_BASE 0 + /* * Do the traditional i8259 interrupt polling thing. This is for the few * cases where no better interrupt acknowledge method is available and we @@ -35,15 +56,15 @@ static inline int i8259_irq(void) spin_lock(&i8259A_lock); /* Perform an interrupt acknowledge cycle on controller 1. */ - outb(0x0C, 0x20); /* prepare for poll */ - irq = inb(0x20) & 7; - if (irq == 2) { + outb(0x0C, PIC_MASTER_CMD); /* prepare for poll */ + irq = inb(PIC_MASTER_CMD) & 7; + if (irq == PIC_CASCADE_IR) { /* * Interrupt is cascaded so perform interrupt * acknowledge on controller 2. */ - outb(0x0C, 0xA0); /* prepare for poll */ - irq = (inb(0xA0) & 7) + 8; + outb(0x0C, PIC_SLAVE_CMD); /* prepare for poll */ + irq = (inb(PIC_SLAVE_CMD) & 7) + 8; } if (unlikely(irq == 7)) { @@ -54,14 +75,14 @@ static inline int i8259_irq(void) * significant bit is not set then there is no valid * interrupt. */ - outb(0x0B, 0x20); /* ISR register */ - if(~inb(0x20) & 0x80) + outb(0x0B, PIC_MASTER_ISR); /* ISR register */ + if(~inb(PIC_MASTER_ISR) & 0x80) irq = -1; } spin_unlock(&i8259A_lock); - return irq; + return likely(irq >= 0) ? irq + I8259A_IRQ_BASE : irq; } #endif /* _ASM_I8259_H */ diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h index d20f2e9b28b..2fbd47eba32 100644 --- a/include/asm-mips/pgtable-32.h +++ b/include/asm-mips/pgtable-32.h @@ -156,9 +156,9 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #define __pte_offset(address) \ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset(dir, address) \ - ((pte_t *) (pmd_page_vaddr(*dir)) + __pte_offset(address)) -#define pte_offset_kernel(dir, address) \ - ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) +#define pte_offset_kernel(dir, address) \ + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) #define pte_offset_map(dir, address) \ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h index b9b1e86493e..a5b18710b6a 100644 --- a/include/asm-mips/pgtable-64.h +++ b/include/asm-mips/pgtable-64.h @@ -212,9 +212,9 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) #define __pte_offset(address) \ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset(dir, address) \ - ((pte_t *) (pmd_page_vaddr(*dir)) + __pte_offset(address)) + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) #define pte_offset_kernel(dir, address) \ - ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) + ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) #define pte_offset_map(dir, address) \ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) #define pte_offset_map_nested(dir, address) \ diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h index 8bdc1ba56f7..28305c3cbdd 100644 --- a/include/asm-sh/atomic.h +++ b/include/asm-sh/atomic.h @@ -28,11 +28,11 @@ static inline void atomic_add(int i, atomic_t *v) unsigned long tmp; __asm__ __volatile__ ( -"1: movli.l @%3, %0 ! atomic_add \n" -" add %2, %0 \n" -" movco.l %0, @%3 \n" +"1: movli.l @%2, %0 ! atomic_add \n" +" add %1, %0 \n" +" movco.l %0, @%2 \n" " bf 1b \n" - : "=&z" (tmp), "=r" (&v->counter) + : "=&z" (tmp) : "r" (i), "r" (&v->counter) : "t"); #else @@ -50,11 +50,11 @@ static inline void atomic_sub(int i, atomic_t *v) unsigned long tmp; __asm__ __volatile__ ( -"1: movli.l @%3, %0 ! atomic_sub \n" -" sub %2, %0 \n" -" movco.l %0, @%3 \n" +"1: movli.l @%2, %0 ! atomic_sub \n" +" sub %1, %0 \n" +" movco.l %0, @%2 \n" " bf 1b \n" - : "=&z" (tmp), "=r" (&v->counter) + : "=&z" (tmp) : "r" (i), "r" (&v->counter) : "t"); #else @@ -80,12 +80,12 @@ static inline int atomic_add_return(int i, atomic_t *v) #ifdef CONFIG_CPU_SH4A __asm__ __volatile__ ( -"1: movli.l @%3, %0 ! atomic_add_return \n" -" add %2, %0 \n" -" movco.l %0, @%3 \n" +"1: movli.l @%2, %0 ! atomic_add_return \n" +" add %1, %0 \n" +" movco.l %0, @%2 \n" " bf 1b \n" " synco \n" - : "=&z" (temp), "=r" (&v->counter) + : "=&z" (temp) : "r" (i), "r" (&v->counter) : "t"); #else @@ -109,12 +109,12 @@ static inline int atomic_sub_return(int i, atomic_t *v) #ifdef CONFIG_CPU_SH4A __asm__ __volatile__ ( -"1: movli.l @%3, %0 ! atomic_sub_return \n" -" sub %2, %0 \n" -" movco.l %0, @%3 \n" +"1: movli.l @%2, %0 ! atomic_sub_return \n" +" sub %1, %0 \n" +" movco.l %0, @%2 \n" " bf 1b \n" " synco \n" - : "=&z" (temp), "=r" (&v->counter) + : "=&z" (temp) : "r" (i), "r" (&v->counter) : "t"); #else @@ -186,11 +186,11 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) unsigned long tmp; __asm__ __volatile__ ( -"1: movli.l @%3, %0 ! atomic_clear_mask \n" -" and %2, %0 \n" -" movco.l %0, @%3 \n" +"1: movli.l @%2, %0 ! atomic_clear_mask \n" +" and %1, %0 \n" +" movco.l %0, @%2 \n" " bf 1b \n" - : "=&z" (tmp), "=r" (&v->counter) + : "=&z" (tmp) : "r" (~mask), "r" (&v->counter) : "t"); #else @@ -208,11 +208,11 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) unsigned long tmp; __asm__ __volatile__ ( -"1: movli.l @%3, %0 ! atomic_set_mask \n" -" or %2, %0 \n" -" movco.l %0, @%3 \n" +"1: movli.l @%2, %0 ! atomic_set_mask \n" +" or %1, %0 \n" +" movco.l %0, @%2 \n" " bf 1b \n" - : "=&z" (tmp), "=r" (&v->counter) + : "=&z" (tmp) : "r" (mask), "r" (&v->counter) : "t"); #else diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h index beeea40f549..795047da5e1 100644 --- a/include/asm-sh/bugs.h +++ b/include/asm-sh/bugs.h @@ -23,16 +23,20 @@ static void __init check_bugs(void) cpu_data->loops_per_jiffy = loops_per_jiffy; switch (cpu_data->type) { - case CPU_SH7604: + case CPU_SH7604 ... CPU_SH7619: *p++ = '2'; break; + case CPU_SH7206: + *p++ = '2'; + *p++ = 'a'; + break; case CPU_SH7705 ... CPU_SH7300: *p++ = '3'; break; case CPU_SH7750 ... CPU_SH4_501: *p++ = '4'; break; - case CPU_SH7770 ... CPU_SH7781: + case CPU_SH7770 ... CPU_SH7785: *p++ = '4'; *p++ = 'a'; break; diff --git a/include/asm-sh/clock.h b/include/asm-sh/clock.h index fdfb75b30f0..1df92807f8c 100644 --- a/include/asm-sh/clock.h +++ b/include/asm-sh/clock.h @@ -4,6 +4,7 @@ #include <linux/kref.h> #include <linux/list.h> #include <linux/seq_file.h> +#include <linux/clk.h> struct clk; @@ -18,7 +19,7 @@ struct clk_ops { struct clk { struct list_head node; const char *name; - + int id; struct module *owner; struct clk *parent; @@ -40,22 +41,13 @@ void arch_init_clk_ops(struct clk_ops **, int type); int clk_init(void); int __clk_enable(struct clk *); -int clk_enable(struct clk *); - void __clk_disable(struct clk *); -void clk_disable(struct clk *); -int clk_set_rate(struct clk *, unsigned long rate); -unsigned long clk_get_rate(struct clk *); void clk_recalc_rate(struct clk *); -struct clk *clk_get(const char *id); -void clk_put(struct clk *); - int clk_register(struct clk *); void clk_unregister(struct clk *); int show_clocks(struct seq_file *m); #endif /* __ASM_SH_CLOCK_H */ - diff --git a/include/asm-sh/cpu-sh2/cache.h b/include/asm-sh/cpu-sh2/cache.h index cd96402e856..20b9796842d 100644 --- a/include/asm-sh/cpu-sh2/cache.h +++ b/include/asm-sh/cpu-sh2/cache.h @@ -12,6 +12,7 @@ #define L1_CACHE_SHIFT 4 +#if defined(CONFIG_CPU_SUBTYPE_SH7604) #define CCR 0xfffffe92 /* Address of Cache Control Register */ #define CCR_CACHE_CE 0x01 /* Cache enable */ @@ -27,5 +28,26 @@ #define CCR_CACHE_ORA CCR_CACHE_TW #define CCR_CACHE_WT 0x00 /* SH-2 is _always_ write-through */ +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +#define CCR1 0xffffffec +#define CCR CCR1 + +#define CCR_CACHE_CE 0x01 /* Cache enable */ +#define CCR_CACHE_WT 0x06 /* CCR[bit1=1,bit2=1] */ + /* 0x00000000-0x7fffffff: Write-through */ + /* 0x80000000-0x9fffffff: Write-back */ + /* 0xc0000000-0xdfffffff: Write-through */ +#define CCR_CACHE_CB 0x00 /* CCR[bit1=0,bit2=0] */ + /* 0x00000000-0x7fffffff: Write-back */ + /* 0x80000000-0x9fffffff: Write-through */ + /* 0xc0000000-0xdfffffff: Write-back */ +#define CCR_CACHE_CF 0x08 /* Cache invalidate */ + +#define CACHE_OC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_OC_DATA_ARRAY 0xf1000000 + +#define CCR_CACHE_ENABLE CCR_CACHE_CE +#define CCR_CACHE_INVALIDATE CCR_CACHE_CF +#endif #endif /* __ASM_CPU_SH2_CACHE_H */ diff --git a/include/asm-sh/cpu-sh2/freq.h b/include/asm-sh/cpu-sh2/freq.h new file mode 100644 index 00000000000..31de475da70 --- /dev/null +++ b/include/asm-sh/cpu-sh2/freq.h @@ -0,0 +1,18 @@ +/* + * include/asm-sh/cpu-sh2/freq.h + * + * Copyright (C) 2006 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_CPU_SH2_FREQ_H +#define __ASM_CPU_SH2_FREQ_H + +#if defined(CONFIG_CPU_SUBTYPE_SH7619) +#define FREQCR 0xf815ff80 +#endif + +#endif /* __ASM_CPU_SH2_FREQ_H */ + diff --git a/include/asm-sh/cpu-sh2/mmu_context.h b/include/asm-sh/cpu-sh2/mmu_context.h new file mode 100644 index 00000000000..beeb299e01e --- /dev/null +++ b/include/asm-sh/cpu-sh2/mmu_context.h @@ -0,0 +1,16 @@ +/* + * include/asm-sh/cpu-sh2/mmu_context.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_CPU_SH2_MMU_CONTEXT_H +#define __ASM_CPU_SH2_MMU_CONTEXT_H + +/* No MMU */ + +#endif /* __ASM_CPU_SH2_MMU_CONTEXT_H */ + diff --git a/include/asm-sh/cpu-sh2/timer.h b/include/asm-sh/cpu-sh2/timer.h new file mode 100644 index 00000000000..a39c241e819 --- /dev/null +++ b/include/asm-sh/cpu-sh2/timer.h @@ -0,0 +1,6 @@ +#ifndef __ASM_CPU_SH2_TIMER_H +#define __ASM_CPU_SH2_TIMER_H + +/* Nothing needed yet */ + +#endif /* __ASM_CPU_SH2_TIMER_H */ diff --git a/include/asm-sh/cpu-sh2a/addrspace.h b/include/asm-sh/cpu-sh2a/addrspace.h new file mode 100644 index 00000000000..3d2e9aa2152 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/addrspace.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/addrspace.h> diff --git a/include/asm-sh/cpu-sh2a/cache.h b/include/asm-sh/cpu-sh2a/cache.h new file mode 100644 index 00000000000..3e4b9e48098 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/cache.h @@ -0,0 +1,39 @@ +/* + * include/asm-sh/cpu-sh2a/cache.h + * + * Copyright (C) 2004 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_CPU_SH2A_CACHE_H +#define __ASM_CPU_SH2A_CACHE_H + +#define L1_CACHE_SHIFT 4 + +#define CCR1 0xfffc1000 +#define CCR2 0xfffc1004 + +/* CCR1 behaves more like the traditional CCR */ +#define CCR CCR1 + +/* + * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not + * listed here are reserved. + */ +#define CCR_CACHE_CB 0x0000 /* Hack */ +#define CCR_CACHE_OCE 0x0001 +#define CCR_CACHE_WT 0x0002 +#define CCR_CACHE_OCI 0x0008 /* OCF */ +#define CCR_CACHE_ICE 0x0100 +#define CCR_CACHE_ICI 0x0800 /* ICF */ + +#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_OC_ADDRESS_ARRAY 0xf0800000 + +#define CCR_CACHE_ENABLE (CCR_CACHE_OCE | CCR_CACHE_ICE) +#define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI) + +#endif /* __ASM_CPU_SH2A_CACHE_H */ + diff --git a/include/asm-sh/cpu-sh2a/cacheflush.h b/include/asm-sh/cpu-sh2a/cacheflush.h new file mode 100644 index 00000000000..fa3186c7335 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/cacheflush.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/cacheflush.h> diff --git a/include/asm-sh/cpu-sh2a/dma.h b/include/asm-sh/cpu-sh2a/dma.h new file mode 100644 index 00000000000..0d5ad85c1de --- /dev/null +++ b/include/asm-sh/cpu-sh2a/dma.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/dma.h> diff --git a/include/asm-sh/cpu-sh2a/freq.h b/include/asm-sh/cpu-sh2a/freq.h new file mode 100644 index 00000000000..e518fff6d10 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/freq.h @@ -0,0 +1,18 @@ +/* + * include/asm-sh/cpu-sh2a/freq.h + * + * Copyright (C) 2006 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_CPU_SH2A_FREQ_H +#define __ASM_CPU_SH2A_FREQ_H + +#if defined(CONFIG_CPU_SUBTYPE_SH7206) +#define FREQCR 0xfffe0010 +#endif + +#endif /* __ASM_CPU_SH2A_FREQ_H */ + diff --git a/include/asm-sh/cpu-sh2a/mmu_context.h b/include/asm-sh/cpu-sh2a/mmu_context.h new file mode 100644 index 00000000000..cd2387f7db9 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/mmu_context.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/mmu_context.h> diff --git a/include/asm-sh/cpu-sh2a/timer.h b/include/asm-sh/cpu-sh2a/timer.h new file mode 100644 index 00000000000..fee504adf11 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/timer.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/timer.h> diff --git a/include/asm-sh/cpu-sh2a/ubc.h b/include/asm-sh/cpu-sh2a/ubc.h new file mode 100644 index 00000000000..cf28062b96a --- /dev/null +++ b/include/asm-sh/cpu-sh2a/ubc.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/ubc.h> diff --git a/include/asm-sh/cpu-sh2a/watchdog.h b/include/asm-sh/cpu-sh2a/watchdog.h new file mode 100644 index 00000000000..c1b3e248847 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/watchdog.h @@ -0,0 +1 @@ +#include <asm/cpu-sh2/watchdog.h> diff --git a/include/asm-sh/dma.h b/include/asm-sh/dma.h index d9daa028689..faf3051cd42 100644 --- a/include/asm-sh/dma.h +++ b/include/asm-sh/dma.h @@ -14,9 +14,7 @@ #include <linux/spinlock.h> #include <linux/wait.h> #include <linux/sysdev.h> -#include <linux/device.h> #include <asm/cpu/dma.h> -#include <asm/semaphore.h> /* The maximum address that we can perform a DMA transfer to on this platform */ /* Don't define MAX_DMA_ADDRESS; it's useless on the SuperH and any @@ -46,16 +44,21 @@ * DMAC (dma_info) flags */ enum { - DMAC_CHANNELS_CONFIGURED = 0x00, - DMAC_CHANNELS_TEI_CAPABLE = 0x01, + DMAC_CHANNELS_CONFIGURED = 0x01, + DMAC_CHANNELS_TEI_CAPABLE = 0x02, /* Transfer end interrupt */ }; /* * DMA channel capabilities / flags */ enum { - DMA_TEI_CAPABLE = 0x01, - DMA_CONFIGURED = 0x02, + DMA_CONFIGURED = 0x01, + + /* + * Transfer end interrupt, inherited from DMAC. + * wait_queue used in dma_wait_for_completion. + */ + DMA_TEI_CAPABLE = 0x02, }; extern spinlock_t dma_spin_lock; @@ -68,28 +71,31 @@ struct dma_ops { int (*get_residue)(struct dma_channel *chan); int (*xfer)(struct dma_channel *chan); - void (*configure)(struct dma_channel *chan, unsigned long flags); + int (*configure)(struct dma_channel *chan, unsigned long flags); + int (*extend)(struct dma_channel *chan, unsigned long op, void *param); }; struct dma_channel { - char dev_id[16]; + char dev_id[16]; /* unique name per DMAC of channel */ - unsigned int chan; /* Physical channel number */ + unsigned int chan; /* DMAC channel number */ unsigned int vchan; /* Virtual channel number */ + unsigned int mode; unsigned int count; unsigned long sar; unsigned long dar; + const char **caps; + unsigned long flags; atomic_t busy; - struct semaphore sem; wait_queue_head_t wait_queue; struct sys_device dev; - char *name; + void *priv_data; }; struct dma_info { @@ -103,6 +109,12 @@ struct dma_info { struct dma_channel *channels; struct list_head list; + int first_channel_nr; +}; + +struct dma_chan_caps { + int ch_num; + const char **caplist; }; #define to_dma_channel(channel) container_of(channel, struct dma_channel, dev) @@ -121,6 +133,8 @@ extern int dma_xfer(unsigned int chan, unsigned long from, #define dma_read_page(chan, from, to) \ dma_read(chan, from, to, PAGE_SIZE) +extern int request_dma_bycap(const char **dmac, const char **caps, + const char *dev_id); extern int request_dma(unsigned int chan, const char *dev_id); extern void free_dma(unsigned int chan); extern int get_dma_residue(unsigned int chan); @@ -131,6 +145,10 @@ extern void dma_configure_channel(unsigned int chan, unsigned long flags); extern int register_dmac(struct dma_info *info); extern void unregister_dmac(struct dma_info *info); +extern struct dma_info *get_dma_info_by_name(const char *dmac_name); + +extern int dma_extend(unsigned int chan, unsigned long op, void *param); +extern int register_chan_caps(const char *dmac, struct dma_chan_caps *capslist); #ifdef CONFIG_SYSFS /* arch/sh/drivers/dma/dma-sysfs.c */ diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h index fc050fd7645..43ca244564b 100644 --- a/include/asm-sh/elf.h +++ b/include/asm-sh/elf.h @@ -74,7 +74,7 @@ typedef struct user_fpu_struct elf_fpregset_t; #define ELF_ARCH EM_SH #define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 +#define ELF_EXEC_PAGESIZE PAGE_SIZE /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of diff --git a/include/asm-sh/entry-macros.S b/include/asm-sh/entry-macros.S new file mode 100644 index 00000000000..500030eae7a --- /dev/null +++ b/include/asm-sh/entry-macros.S @@ -0,0 +1,33 @@ +! entry.S macro define + + .macro cli + stc sr, r0 + or #0xf0, r0 + ldc r0, sr + .endm + + .macro sti + mov #0xf0, r11 + extu.b r11, r11 + not r11, r11 + stc sr, r10 + and r11, r10 +#ifdef CONFIG_HAS_SR_RB + stc k_g_imask, r11 + or r11, r10 +#endif + ldc r10, sr + .endm + + .macro get_current_thread_info, ti, tmp +#ifdef CONFIG_HAS_SR_RB + stc r7_bank, \ti +#else + mov #((THREAD_SIZE - 1) >> 10) ^ 0xff, \tmp + shll8 \tmp + shll2 \tmp + mov r15, \ti + and \tmp, \ti +#endif + .endm + diff --git a/include/asm-sh/irq-sh73180.h b/include/asm-sh/irq-sh73180.h deleted file mode 100644 index b28af9a69d7..00000000000 --- a/include/asm-sh/irq-sh73180.h +++ /dev/null @@ -1,314 +0,0 @@ -#ifndef __ASM_SH_IRQ_SH73180_H -#define __ASM_SH_IRQ_SH73180_H - -/* - * linux/include/asm-sh/irq-sh73180.h - * - * Copyright (C) 2004 Takashi SHUDO <shudo@hitachi-ul.co.jp> - */ - -#undef INTC_IPRA -#undef INTC_IPRB -#undef INTC_IPRC -#undef INTC_IPRD - -#undef DMTE0_IRQ -#undef DMTE1_IRQ -#undef DMTE2_IRQ -#undef DMTE3_IRQ -#undef DMTE4_IRQ -#undef DMTE5_IRQ -#undef DMTE6_IRQ -#undef DMTE7_IRQ -#undef DMAE_IRQ -#undef DMA_IPR_ADDR -#undef DMA_IPR_POS -#undef DMA_PRIORITY - -#undef INTC_IMCR0 -#undef INTC_IMCR1 -#undef INTC_IMCR2 -#undef INTC_IMCR3 -#undef INTC_IMCR4 -#undef INTC_IMCR5 -#undef INTC_IMCR6 -#undef INTC_IMCR7 -#undef INTC_IMCR8 -#undef INTC_IMCR9 -#undef INTC_IMCR10 - - -#define INTC_IPRA 0xA4080000UL -#define INTC_IPRB 0xA4080004UL -#define INTC_IPRC 0xA4080008UL -#define INTC_IPRD 0xA408000CUL -#define INTC_IPRE 0xA4080010UL -#define INTC_IPRF 0xA4080014UL -#define INTC_IPRG 0xA4080018UL -#define INTC_IPRH 0xA408001CUL -#define INTC_IPRI 0xA4080020UL -#define INTC_IPRJ 0xA4080024UL -#define INTC_IPRK 0xA4080028UL - -#define INTC_IMR0 0xA4080080UL -#define INTC_IMR1 0xA4080084UL -#define INTC_IMR2 0xA4080088UL -#define INTC_IMR3 0xA408008CUL -#define INTC_IMR4 0xA4080090UL -#define INTC_IMR5 0xA4080094UL -#define INTC_IMR6 0xA4080098UL -#define INTC_IMR7 0xA408009CUL -#define INTC_IMR8 0xA40800A0UL -#define INTC_IMR9 0xA40800A4UL -#define INTC_IMR10 0xA40800A8UL -#define INTC_IMR11 0xA40800ACUL - -#define INTC_IMCR0 0xA40800C0UL -#define INTC_IMCR1 0xA40800C4UL -#define INTC_IMCR2 0xA40800C8UL -#define INTC_IMCR3 0xA40800CCUL -#define INTC_IMCR4 0xA40800D0UL -#define INTC_IMCR5 0xA40800D4UL -#define INTC_IMCR6 0xA40800D8UL -#define INTC_IMCR7 0xA40800DCUL -#define INTC_IMCR8 0xA40800E0UL -#define INTC_IMCR9 0xA40800E4UL -#define INTC_IMCR10 0xA40800E8UL -#define INTC_IMCR11 0xA40800ECUL - -#define INTC_ICR0 0xA4140000UL -#define INTC_ICR1 0xA414001CUL - -#define INTMSK0 0xa4140044 -#define INTMSKCLR0 0xa4140064 -#define INTC_INTPRI0 0xa4140010 - -/* - NOTE: - - *_IRQ = (INTEVT2 - 0x200)/0x20 -*/ - -/* TMU0 */ -#define TMU0_IRQ 16 -#define TMU0_IPR_ADDR INTC_IPRA -#define TMU0_IPR_POS 3 -#define TMU0_PRIORITY 2 - -#define TIMER_IRQ 16 -#define TIMER_IPR_ADDR INTC_IPRA -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -/* TMU1 */ -#define TMU1_IRQ 17 -#define TMU1_IPR_ADDR INTC_IPRA -#define TMU1_IPR_POS 2 -#define TMU1_PRIORITY 2 - -/* TMU2 */ -#define TMU2_IRQ 18 -#define TMU2_IPR_ADDR INTC_IPRA -#define TMU2_IPR_POS 1 -#define TMU2_PRIORITY 2 - -/* LCDC */ -#define LCDC_IRQ 28 -#define LCDC_IPR_ADDR INTC_IPRB -#define LCDC_IPR_POS 2 -#define LCDC_PRIORITY 2 - -/* VIO (Video I/O) */ -#define CEU_IRQ 52 -#define BEU_IRQ 53 -#define VEU_IRQ 54 -#define VOU_IRQ 55 -#define VIO_IPR_ADDR INTC_IPRE -#define VIO_IPR_POS 2 -#define VIO_PRIORITY 2 - -/* MFI (Multi Functional Interface) */ -#define MFI_IRQ 56 -#define MFI_IPR_ADDR INTC_IPRE -#define MFI_IPR_POS 1 -#define MFI_PRIORITY 2 - -/* VPU (Video Processing Unit) */ -#define VPU_IRQ 60 -#define VPU_IPR_ADDR INTC_IPRE -#define VPU_IPR_POS 0 -#define VPU_PRIORITY 2 - -/* 3DG */ -#define TDG_IRQ 63 -#define TDG_IPR_ADDR INTC_IPRJ -#define TDG_IPR_POS 2 -#define TDG_PRIORITY 2 - -/* DMAC(1) */ -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA1_IPR_ADDR INTC_IPRE -#define DMA1_IPR_POS 3 -#define DMA1_PRIORITY 7 - -/* DMAC(2) */ -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -/* SCIF0 */ -#define SCIF_ERI_IRQ 80 -#define SCIF_RXI_IRQ 81 -#define SCIF_BRI_IRQ 82 -#define SCIF_TXI_IRQ 83 -#define SCIF_IPR_ADDR INTC_IPRG -#define SCIF_IPR_POS 3 -#define SCIF_PRIORITY 3 - -/* SIOF0 */ -#define SIOF0_IRQ 84 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 3 -#define SIOF0_PRIORITY 3 - -/* FLCTL (Flash Memory Controller) */ -#define FLSTE_IRQ 92 -#define FLTEND_IRQ 93 -#define FLTRQ0_IRQ 94 -#define FLTRQ1_IRQ 95 -#define FLCTL_IPR_ADDR INTC_IPRH -#define FLCTL_IPR_POS 1 -#define FLCTL_PRIORITY 3 - -/* IIC(0) (IIC Bus Interface) */ -#define IIC0_ALI_IRQ 96 -#define IIC0_TACKI_IRQ 97 -#define IIC0_WAITI_IRQ 98 -#define IIC0_DTEI_IRQ 99 -#define IIC0_IPR_ADDR INTC_IPRH -#define IIC0_IPR_POS 0 -#define IIC0_PRIORITY 3 - -/* IIC(1) (IIC Bus Interface) */ -#define IIC1_ALI_IRQ 44 -#define IIC1_TACKI_IRQ 45 -#define IIC1_WAITI_IRQ 46 -#define IIC1_DTEI_IRQ 47 -#define IIC1_IPR_ADDR INTC_IPRG -#define IIC1_IPR_POS 0 -#define IIC1_PRIORITY 3 - -/* SIO0 */ -#define SIO0_IRQ 88 -#define SIO0_IPR_ADDR INTC_IPRI -#define SIO0_IPR_POS 3 -#define SIO0_PRIORITY 3 - -/* SDHI */ -#define SDHI_SDHII0_IRQ 100 -#define SDHI_SDHII1_IRQ 101 -#define SDHI_SDHII2_IRQ 102 -#define SDHI_SDHII3_IRQ 103 -#define SDHI_IPR_ADDR INTC_IPRK -#define SDHI_IPR_POS 0 -#define SDHI_PRIORITY 3 - -/* SIU (Sound Interface Unit) */ -#define SIU_IRQ 108 -#define SIU_IPR_ADDR INTC_IPRJ -#define SIU_IPR_POS 1 -#define SIU_PRIORITY 3 - -#define PORT_PACR 0xA4050100UL -#define PORT_PBCR 0xA4050102UL -#define PORT_PCCR 0xA4050104UL -#define PORT_PDCR 0xA4050106UL -#define PORT_PECR 0xA4050108UL -#define PORT_PFCR 0xA405010AUL -#define PORT_PGCR 0xA405010CUL -#define PORT_PHCR 0xA405010EUL -#define PORT_PJCR 0xA4050110UL -#define PORT_PKCR 0xA4050112UL -#define PORT_PLCR 0xA4050114UL -#define PORT_SCPCR 0xA4050116UL -#define PORT_PMCR 0xA4050118UL -#define PORT_PNCR 0xA405011AUL -#define PORT_PQCR 0xA405011CUL -#define PORT_PRCR 0xA405011EUL -#define PORT_PTCR 0xA405014CUL -#define PORT_PUCR 0xA405014EUL -#define PORT_PVCR 0xA4050150UL - -#define PORT_PSELA 0xA4050140UL -#define PORT_PSELB 0xA4050142UL -#define PORT_PSELC 0xA4050144UL -#define PORT_PSELE 0xA4050158UL - -#define PORT_HIZCRA 0xA4050146UL -#define PORT_HIZCRB 0xA4050148UL -#define PORT_DRVCR 0xA405014AUL - -#define PORT_PADR 0xA4050120UL -#define PORT_PBDR 0xA4050122UL -#define PORT_PCDR 0xA4050124UL -#define PORT_PDDR 0xA4050126UL -#define PORT_PEDR 0xA4050128UL -#define PORT_PFDR 0xA405012AUL -#define PORT_PGDR 0xA405012CUL -#define PORT_PHDR 0xA405012EUL -#define PORT_PJDR 0xA4050130UL -#define PORT_PKDR 0xA4050132UL -#define PORT_PLDR 0xA4050134UL -#define PORT_SCPDR 0xA4050136UL -#define PORT_PMDR 0xA4050138UL -#define PORT_PNDR 0xA405013AUL -#define PORT_PQDR 0xA405013CUL -#define PORT_PRDR 0xA405013EUL -#define PORT_PTDR 0xA405016CUL -#define PORT_PUDR 0xA405016EUL -#define PORT_PVDR 0xA4050170UL - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 -#define IRQ6_IRQ 38 -#define IRQ7_IRQ 39 - -#define INTPRI00 0xA4140010UL - -#define IRQ0_IPR_ADDR INTPRI00 -#define IRQ1_IPR_ADDR INTPRI00 -#define IRQ2_IPR_ADDR INTPRI00 -#define IRQ3_IPR_ADDR INTPRI00 -#define IRQ4_IPR_ADDR INTPRI00 -#define IRQ5_IPR_ADDR INTPRI00 -#define IRQ6_IPR_ADDR INTPRI00 -#define IRQ7_IPR_ADDR INTPRI00 - -#define IRQ0_IPR_POS 7 -#define IRQ1_IPR_POS 6 -#define IRQ2_IPR_POS 5 -#define IRQ3_IPR_POS 4 -#define IRQ4_IPR_POS 3 -#define IRQ5_IPR_POS 2 -#define IRQ6_IPR_POS 1 -#define IRQ7_IPR_POS 0 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 -#define IRQ6_PRIORITY 1 -#define IRQ7_PRIORITY 1 - -#endif /* __ASM_SH_IRQ_SH73180_H */ diff --git a/include/asm-sh/irq-sh7343.h b/include/asm-sh/irq-sh7343.h deleted file mode 100644 index 5d15419b53b..00000000000 --- a/include/asm-sh/irq-sh7343.h +++ /dev/null @@ -1,317 +0,0 @@ -#ifndef __ASM_SH_IRQ_SH7343_H -#define __ASM_SH_IRQ_SH7343_H - -/* - * linux/include/asm-sh/irq-sh7343.h - * - * Copyright (C) 2006 Kenati Technologies Inc. - * Andre Mccurdy <andre@kenati.com> - * Ranjit Deshpande <ranjit@kenati.com> - */ - -#undef INTC_IPRA -#undef INTC_IPRB -#undef INTC_IPRC -#undef INTC_IPRD - -#undef DMTE0_IRQ -#undef DMTE1_IRQ -#undef DMTE2_IRQ -#undef DMTE3_IRQ -#undef DMTE4_IRQ -#undef DMTE5_IRQ -#undef DMTE6_IRQ -#undef DMTE7_IRQ -#undef DMAE_IRQ -#undef DMA_IPR_ADDR -#undef DMA_IPR_POS -#undef DMA_PRIORITY - -#undef INTC_IMCR0 -#undef INTC_IMCR1 -#undef INTC_IMCR2 -#undef INTC_IMCR3 -#undef INTC_IMCR4 -#undef INTC_IMCR5 -#undef INTC_IMCR6 -#undef INTC_IMCR7 -#undef INTC_IMCR8 -#undef INTC_IMCR9 -#undef INTC_IMCR10 - - -#define INTC_IPRA 0xA4080000UL -#define INTC_IPRB 0xA4080004UL -#define INTC_IPRC 0xA4080008UL -#define INTC_IPRD 0xA408000CUL -#define INTC_IPRE 0xA4080010UL -#define INTC_IPRF 0xA4080014UL -#define INTC_IPRG 0xA4080018UL -#define INTC_IPRH 0xA408001CUL -#define INTC_IPRI 0xA4080020UL -#define INTC_IPRJ 0xA4080024UL -#define INTC_IPRK 0xA4080028UL -#define INTC_IPRL 0xA408002CUL - -#define INTC_IMR0 0xA4080080UL -#define INTC_IMR1 0xA4080084UL -#define INTC_IMR2 0xA4080088UL -#define INTC_IMR3 0xA408008CUL -#define INTC_IMR4 0xA4080090UL -#define INTC_IMR5 0xA4080094UL -#define INTC_IMR6 0xA4080098UL -#define INTC_IMR7 0xA408009CUL -#define INTC_IMR8 0xA40800A0UL -#define INTC_IMR9 0xA40800A4UL -#define INTC_IMR10 0xA40800A8UL -#define INTC_IMR11 0xA40800ACUL - -#define INTC_IMCR0 0xA40800C0UL -#define INTC_IMCR1 0xA40800C4UL -#define INTC_IMCR2 0xA40800C8UL -#define INTC_IMCR3 0xA40800CCUL -#define INTC_IMCR4 0xA40800D0UL -#define INTC_IMCR5 0xA40800D4UL -#define INTC_IMCR6 0xA40800D8UL -#define INTC_IMCR7 0xA40800DCUL -#define INTC_IMCR8 0xA40800E0UL -#define INTC_IMCR9 0xA40800E4UL -#define INTC_IMCR10 0xA40800E8UL -#define INTC_IMCR11 0xA40800ECUL - -#define INTC_ICR0 0xA4140000UL -#define INTC_ICR1 0xA414001CUL - -#define INTMSK0 0xa4140044 -#define INTMSKCLR0 0xa4140064 -#define INTC_INTPRI0 0xa4140010 - -/* - NOTE: - - *_IRQ = (INTEVT2 - 0x200)/0x20 -*/ - -/* TMU0 */ -#define TMU0_IRQ 16 -#define TMU0_IPR_ADDR INTC_IPRA -#define TMU0_IPR_POS 3 -#define TMU0_PRIORITY 2 - -#define TIMER_IRQ 16 -#define TIMER_IPR_ADDR INTC_IPRA -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -/* TMU1 */ -#define TMU1_IRQ 17 -#define TMU1_IPR_ADDR INTC_IPRA -#define TMU1_IPR_POS 2 -#define TMU1_PRIORITY 2 - -/* TMU2 */ -#define TMU2_IRQ 18 -#define TMU2_IPR_ADDR INTC_IPRA -#define TMU2_IPR_POS 1 -#define TMU2_PRIORITY 2 - -/* LCDC */ -#define LCDC_IRQ 28 -#define LCDC_IPR_ADDR INTC_IPRB -#define LCDC_IPR_POS 2 -#define LCDC_PRIORITY 2 - -/* VIO (Video I/O) */ -#define CEU_IRQ 52 -#define BEU_IRQ 53 -#define VEU_IRQ 54 -#define VOU_IRQ 55 -#define VIO_IPR_ADDR INTC_IPRE -#define VIO_IPR_POS 2 -#define VIO_PRIORITY 2 - -/* MFI (Multi Functional Interface) */ -#define MFI_IRQ 56 -#define MFI_IPR_ADDR INTC_IPRE -#define MFI_IPR_POS 1 -#define MFI_PRIORITY 2 - -/* VPU (Video Processing Unit) */ -#define VPU_IRQ 60 -#define VPU_IPR_ADDR INTC_IPRE -#define VPU_IPR_POS 0 -#define VPU_PRIORITY 2 - -/* 3DG */ -#define TDG_IRQ 63 -#define TDG_IPR_ADDR INTC_IPRJ -#define TDG_IPR_POS 2 -#define TDG_PRIORITY 2 - -/* DMAC(1) */ -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA1_IPR_ADDR INTC_IPRE -#define DMA1_IPR_POS 3 -#define DMA1_PRIORITY 7 - -/* DMAC(2) */ -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -/* SCIF0 */ -#define SCIF_ERI_IRQ 80 -#define SCIF_RXI_IRQ 81 -#define SCIF_BRI_IRQ 82 -#define SCIF_TXI_IRQ 83 -#define SCIF_IPR_ADDR INTC_IPRG -#define SCIF_IPR_POS 3 -#define SCIF_PRIORITY 3 - -/* SIOF0 */ -#define SIOF0_IRQ 84 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 3 -#define SIOF0_PRIORITY 3 - -/* FLCTL (Flash Memory Controller) */ -#define FLSTE_IRQ 92 -#define FLTEND_IRQ 93 -#define FLTRQ0_IRQ 94 -#define FLTRQ1_IRQ 95 -#define FLCTL_IPR_ADDR INTC_IPRH -#define FLCTL_IPR_POS 1 -#define FLCTL_PRIORITY 3 - -/* IIC(0) (IIC Bus Interface) */ -#define IIC0_ALI_IRQ 96 -#define IIC0_TACKI_IRQ 97 -#define IIC0_WAITI_IRQ 98 -#define IIC0_DTEI_IRQ 99 -#define IIC0_IPR_ADDR INTC_IPRH -#define IIC0_IPR_POS 0 -#define IIC0_PRIORITY 3 - -/* IIC(1) (IIC Bus Interface) */ -#define IIC1_ALI_IRQ 44 -#define IIC1_TACKI_IRQ 45 -#define IIC1_WAITI_IRQ 46 -#define IIC1_DTEI_IRQ 47 -#define IIC1_IPR_ADDR INTC_IPRI -#define IIC1_IPR_POS 0 -#define IIC1_PRIORITY 3 - -/* SIO0 */ -#define SIO0_IRQ 88 -#define SIO0_IPR_ADDR INTC_IPRI -#define SIO0_IPR_POS 3 -#define SIO0_PRIORITY 3 - -/* SDHI */ -#define SDHI_SDHII0_IRQ 100 -#define SDHI_SDHII1_IRQ 101 -#define SDHI_SDHII2_IRQ 102 -#define SDHI_SDHII3_IRQ 103 -#define SDHI_IPR_ADDR INTC_IPRK -#define SDHI_IPR_POS 0 -#define SDHI_PRIORITY 3 - -/* SIU (Sound Interface Unit) */ -#define SIU_IRQ 108 -#define SIU_IPR_ADDR INTC_IPRJ -#define SIU_IPR_POS 1 -#define SIU_PRIORITY 3 - -#define PORT_PACR 0xA4050100UL -#define PORT_PBCR 0xA4050102UL -#define PORT_PCCR 0xA4050104UL -#define PORT_PDCR 0xA4050106UL -#define PORT_PECR 0xA4050108UL -#define PORT_PFCR 0xA405010AUL -#define PORT_PGCR 0xA405010CUL -#define PORT_PHCR 0xA405010EUL -#define PORT_PJCR 0xA4050110UL -#define PORT_PKCR 0xA4050112UL -#define PORT_PLCR 0xA4050114UL -#define PORT_SCPCR 0xA4050116UL -#define PORT_PMCR 0xA4050118UL -#define PORT_PNCR 0xA405011AUL -#define PORT_PQCR 0xA405011CUL -#define PORT_PRCR 0xA405011EUL -#define PORT_PTCR 0xA405014CUL -#define PORT_PUCR 0xA405014EUL -#define PORT_PVCR 0xA4050150UL - -#define PORT_PSELA 0xA4050140UL -#define PORT_PSELB 0xA4050142UL -#define PORT_PSELC 0xA4050144UL -#define PORT_PSELE 0xA4050158UL - -#define PORT_HIZCRA 0xA4050146UL -#define PORT_HIZCRB 0xA4050148UL -#define PORT_DRVCR 0xA405014AUL - -#define PORT_PADR 0xA4050120UL -#define PORT_PBDR 0xA4050122UL -#define PORT_PCDR 0xA4050124UL -#define PORT_PDDR 0xA4050126UL -#define PORT_PEDR 0xA4050128UL -#define PORT_PFDR 0xA405012AUL -#define PORT_PGDR 0xA405012CUL -#define PORT_PHDR 0xA405012EUL -#define PORT_PJDR 0xA4050130UL -#define PORT_PKDR 0xA4050132UL -#define PORT_PLDR 0xA4050134UL -#define PORT_SCPDR 0xA4050136UL -#define PORT_PMDR 0xA4050138UL -#define PORT_PNDR 0xA405013AUL -#define PORT_PQDR 0xA405013CUL -#define PORT_PRDR 0xA405013EUL -#define PORT_PTDR 0xA405016CUL -#define PORT_PUDR 0xA405016EUL -#define PORT_PVDR 0xA4050170UL - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 -#define IRQ6_IRQ 38 -#define IRQ7_IRQ 39 - -#define INTPRI00 0xA4140010UL - -#define IRQ0_IPR_ADDR INTPRI00 -#define IRQ1_IPR_ADDR INTPRI00 -#define IRQ2_IPR_ADDR INTPRI00 -#define IRQ3_IPR_ADDR INTPRI00 -#define IRQ4_IPR_ADDR INTPRI00 -#define IRQ5_IPR_ADDR INTPRI00 -#define IRQ6_IPR_ADDR INTPRI00 -#define IRQ7_IPR_ADDR INTPRI00 - -#define IRQ0_IPR_POS 7 -#define IRQ1_IPR_POS 6 -#define IRQ2_IPR_POS 5 -#define IRQ3_IPR_POS 4 -#define IRQ4_IPR_POS 3 -#define IRQ5_IPR_POS 2 -#define IRQ6_IPR_POS 1 -#define IRQ7_IPR_POS 0 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 -#define IRQ6_PRIORITY 1 -#define IRQ7_PRIORITY 1 - -#endif /* __ASM_SH_IRQ_SH7343_H */ diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h deleted file mode 100644 index 19912ae6a7f..00000000000 --- a/include/asm-sh/irq-sh7780.h +++ /dev/null @@ -1,311 +0,0 @@ -#ifndef __ASM_SH_IRQ_SH7780_H -#define __ASM_SH_IRQ_SH7780_H - -/* - * linux/include/asm-sh/irq-sh7780.h - * - * Copyright (C) 2004 Takashi SHUDO <shudo@hitachi-ul.co.jp> - */ -#define INTC_BASE 0xffd00000 -#define INTC_ICR0 (INTC_BASE+0x0) -#define INTC_ICR1 (INTC_BASE+0x1c) -#define INTC_INTPRI (INTC_BASE+0x10) -#define INTC_INTREQ (INTC_BASE+0x24) -#define INTC_INTMSK0 (INTC_BASE+0x44) -#define INTC_INTMSK1 (INTC_BASE+0x48) -#define INTC_INTMSK2 (INTC_BASE+0x40080) -#define INTC_INTMSKCLR0 (INTC_BASE+0x64) -#define INTC_INTMSKCLR1 (INTC_BASE+0x68) -#define INTC_INTMSKCLR2 (INTC_BASE+0x40084) -#define INTC_NMIFCR (INTC_BASE+0xc0) -#define INTC_USERIMASK (INTC_BASE+0x30000) - -#define INTC_INT2PRI0 (INTC_BASE+0x40000) -#define INTC_INT2PRI1 (INTC_BASE+0x40004) -#define INTC_INT2PRI2 (INTC_BASE+0x40008) -#define INTC_INT2PRI3 (INTC_BASE+0x4000c) -#define INTC_INT2PRI4 (INTC_BASE+0x40010) -#define INTC_INT2PRI5 (INTC_BASE+0x40014) -#define INTC_INT2PRI6 (INTC_BASE+0x40018) -#define INTC_INT2PRI7 (INTC_BASE+0x4001c) -#define INTC_INT2A0 (INTC_BASE+0x40030) -#define INTC_INT2A1 (INTC_BASE+0x40034) -#define INTC_INT2MSKR (INTC_BASE+0x40038) -#define INTC_INT2MSKCR (INTC_BASE+0x4003c) -#define INTC_INT2B0 (INTC_BASE+0x40040) -#define INTC_INT2B1 (INTC_BASE+0x40044) -#define INTC_INT2B2 (INTC_BASE+0x40048) -#define INTC_INT2B3 (INTC_BASE+0x4004c) -#define INTC_INT2B4 (INTC_BASE+0x40050) -#define INTC_INT2B5 (INTC_BASE+0x40054) -#define INTC_INT2B6 (INTC_BASE+0x40058) -#define INTC_INT2B7 (INTC_BASE+0x4005c) -#define INTC_INT2GPIC (INTC_BASE+0x40090) -/* - NOTE: - *_IRQ = (INTEVT2 - 0x200)/0x20 -*/ -/* IRQ 0-7 line external int*/ -#define IRQ0_IRQ 2 -#define IRQ0_IPR_ADDR INTC_INTPRI -#define IRQ0_IPR_POS 7 -#define IRQ0_PRIORITY 2 - -#define IRQ1_IRQ 4 -#define IRQ1_IPR_ADDR INTC_INTPRI -#define IRQ1_IPR_POS 6 -#define IRQ1_PRIORITY 2 - -#define IRQ2_IRQ 6 -#define IRQ2_IPR_ADDR INTC_INTPRI -#define IRQ2_IPR_POS 5 -#define IRQ2_PRIORITY 2 - -#define IRQ3_IRQ 8 -#define IRQ3_IPR_ADDR INTC_INTPRI -#define IRQ3_IPR_POS 4 -#define IRQ3_PRIORITY 2 - -#define IRQ4_IRQ 10 -#define IRQ4_IPR_ADDR INTC_INTPRI -#define IRQ4_IPR_POS 3 -#define IRQ4_PRIORITY 2 - -#define IRQ5_IRQ 12 -#define IRQ5_IPR_ADDR INTC_INTPRI -#define IRQ5_IPR_POS 2 -#define IRQ5_PRIORITY 2 - -#define IRQ6_IRQ 14 -#define IRQ6_IPR_ADDR INTC_INTPRI -#define IRQ6_IPR_POS 1 -#define IRQ6_PRIORITY 2 - -#define IRQ7_IRQ 0 -#define IRQ7_IPR_ADDR INTC_INTPRI -#define IRQ7_IPR_POS 0 -#define IRQ7_PRIORITY 2 - -/* TMU */ -/* ch0 */ -#define TMU_IRQ 28 -#define TMU_IPR_ADDR INTC_INT2PRI0 -#define TMU_IPR_POS 3 -#define TMU_PRIORITY 2 - -#define TIMER_IRQ 28 -#define TIMER_IPR_ADDR INTC_INT2PRI0 -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -/* ch 1*/ -#define TMU_CH1_IRQ 29 -#define TMU_CH1_IPR_ADDR INTC_INT2PRI0 -#define TMU_CH1_IPR_POS 2 -#define TMU_CH1_PRIORITY 2 - -#define TIMER1_IRQ 29 -#define TIMER1_IPR_ADDR INTC_INT2PRI0 -#define TIMER1_IPR_POS 2 -#define TIMER1_PRIORITY 2 - -/* ch 2*/ -#define TMU_CH2_IRQ 30 -#define TMU_CH2_IPR_ADDR INTC_INT2PRI0 -#define TMU_CH2_IPR_POS 1 -#define TMU_CH2_PRIORITY 2 -/* ch 2 Input capture */ -#define TMU_CH2IC_IRQ 31 -#define TMU_CH2IC_IPR_ADDR INTC_INT2PRI0 -#define TMU_CH2IC_IPR_POS 0 -#define TMU_CH2IC_PRIORITY 2 -/* ch 3 */ -#define TMU_CH3_IRQ 96 -#define TMU_CH3_IPR_ADDR INTC_INT2PRI1 -#define TMU_CH3_IPR_POS 3 -#define TMU_CH3_PRIORITY 2 -/* ch 4 */ -#define TMU_CH4_IRQ 97 -#define TMU_CH4_IPR_ADDR INTC_INT2PRI1 -#define TMU_CH4_IPR_POS 2 -#define TMU_CH4_PRIORITY 2 -/* ch 5*/ -#define TMU_CH5_IRQ 98 -#define TMU_CH5_IPR_ADDR INTC_INT2PRI1 -#define TMU_CH5_IPR_POS 1 -#define TMU_CH5_PRIORITY 2 - -/* SCIF0 */ -#define SCIF0_ERI_IRQ 40 -#define SCIF0_RXI_IRQ 41 -#define SCIF0_BRI_IRQ 42 -#define SCIF0_TXI_IRQ 43 -#define SCIF0_IPR_ADDR INTC_INT2PRI2 -#define SCIF0_IPR_POS 3 -#define SCIF0_PRIORITY 3 - -/* SCIF1 */ -#define SCIF1_ERI_IRQ 76 -#define SCIF1_RXI_IRQ 77 -#define SCIF1_BRI_IRQ 78 -#define SCIF1_TXI_IRQ 79 -#define SCIF1_IPR_ADDR INTC_INT2PRI2 -#define SCIF1_IPR_POS 2 -#define SCIF1_PRIORITY 3 - -#define WDT_IRQ 27 -#define WDT_IPR_ADDR INTC_INT2PRI2 -#define WDT_IPR_POS 1 -#define WDT_PRIORITY 2 - -/* DMAC(0) */ -#define DMINT0_IRQ 34 -#define DMINT1_IRQ 35 -#define DMINT2_IRQ 36 -#define DMINT3_IRQ 37 -#define DMINT4_IRQ 44 -#define DMINT5_IRQ 45 -#define DMINT6_IRQ 46 -#define DMINT7_IRQ 47 -#define DMAE_IRQ 38 -#define DMA0_IPR_ADDR INTC_INT2PRI3 -#define DMA0_IPR_POS 2 -#define DMA0_PRIORITY 7 - -/* DMAC(1) */ -#define DMINT8_IRQ 92 -#define DMINT9_IRQ 93 -#define DMINT10_IRQ 94 -#define DMINT11_IRQ 95 -#define DMA1_IPR_ADDR INTC_INT2PRI3 -#define DMA1_IPR_POS 1 -#define DMA1_PRIORITY 7 - -#define DMTE0_IRQ DMINT0_IRQ -#define DMTE4_IRQ DMINT4_IRQ -#define DMA_IPR_ADDR DMA0_IPR_ADDR -#define DMA_IPR_POS DMA0_IPR_POS -#define DMA_PRIORITY DMA0_PRIORITY - -/* CMT */ -#define CMT_IRQ 56 -#define CMT_IPR_ADDR INTC_INT2PRI4 -#define CMT_IPR_POS 3 -#define CMT_PRIORITY 0 - -/* HAC */ -#define HAC_IRQ 60 -#define HAC_IPR_ADDR INTC_INT2PRI4 -#define HAC_IPR_POS 2 -#define CMT_PRIORITY 0 - -/* PCIC(0) */ -#define PCIC0_IRQ 64 -#define PCIC0_IPR_ADDR INTC_INT2PRI4 -#define PCIC0_IPR_POS 1 -#define PCIC0_PRIORITY 2 - -/* PCIC(1) */ -#define PCIC1_IRQ 65 -#define PCIC1_IPR_ADDR INTC_INT2PRI4 -#define PCIC1_IPR_POS 0 -#define PCIC1_PRIORITY 2 - -/* PCIC(2) */ -#define PCIC2_IRQ 66 -#define PCIC2_IPR_ADDR INTC_INT2PRI5 -#define PCIC2_IPR_POS 3 -#define PCIC2_PRIORITY 2 - -/* PCIC(3) */ -#define PCIC3_IRQ 67 -#define PCIC3_IPR_ADDR INTC_INT2PRI5 -#define PCIC3_IPR_POS 2 -#define PCIC3_PRIORITY 2 - -/* PCIC(4) */ -#define PCIC4_IRQ 68 -#define PCIC4_IPR_ADDR INTC_INT2PRI5 -#define PCIC4_IPR_POS 1 -#define PCIC4_PRIORITY 2 - -/* PCIC(5) */ -#define PCICERR_IRQ 69 -#define PCICPWD3_IRQ 70 -#define PCICPWD2_IRQ 71 -#define PCICPWD1_IRQ 72 -#define PCICPWD0_IRQ 73 -#define PCIC5_IPR_ADDR INTC_INT2PRI5 -#define PCIC5_IPR_POS 0 -#define PCIC5_PRIORITY 2 - -/* SIOF */ -#define SIOF_IRQ 80 -#define SIOF_IPR_ADDR INTC_INT2PRI6 -#define SIOF_IPR_POS 3 -#define SIOF_PRIORITY 3 - -/* HSPI */ -#define HSPI_IRQ 84 -#define HSPI_IPR_ADDR INTC_INT2PRI6 -#define HSPI_IPR_POS 2 -#define HSPI_PRIORITY 3 - -/* MMCIF */ -#define MMCIF_FSTAT_IRQ 88 -#define MMCIF_TRAN_IRQ 89 -#define MMCIF_ERR_IRQ 90 -#define MMCIF_FRDY_IRQ 91 -#define MMCIF_IPR_ADDR INTC_INT2PRI6 -#define MMCIF_IPR_POS 1 -#define HSPI_PRIORITY 3 - -/* SSI */ -#define SSI_IRQ 100 -#define SSI_IPR_ADDR INTC_INT2PRI6 -#define SSI_IPR_POS 0 -#define SSI_PRIORITY 3 - -/* FLCTL */ -#define FLCTL_FLSTE_IRQ 104 -#define FLCTL_FLTEND_IRQ 105 -#define FLCTL_FLTRQ0_IRQ 106 -#define FLCTL_FLTRQ1_IRQ 107 -#define FLCTL_IPR_ADDR INTC_INT2PRI7 -#define FLCTL_IPR_POS 3 -#define FLCTL_PRIORITY 3 - -/* GPIO */ -#define GPIO0_IRQ 108 -#define GPIO1_IRQ 109 -#define GPIO2_IRQ 110 -#define GPIO3_IRQ 111 -#define GPIO_IPR_ADDR INTC_INT2PRI7 -#define GPIO_IPR_POS 2 -#define GPIO_PRIORITY 3 - -#define INTC_TMU0_MSK 0 -#define INTC_TMU3_MSK 1 -#define INTC_RTC_MSK 2 -#define INTC_SCIF0_MSK 3 -#define INTC_SCIF1_MSK 4 -#define INTC_WDT_MSK 5 -#define INTC_HUID_MSK 7 -#define INTC_DMAC0_MSK 8 -#define INTC_DMAC1_MSK 9 -#define INTC_CMT_MSK 12 -#define INTC_HAC_MSK 13 -#define INTC_PCIC0_MSK 14 -#define INTC_PCIC1_MSK 15 -#define INTC_PCIC2_MSK 16 -#define INTC_PCIC3_MSK 17 -#define INTC_PCIC4_MSK 18 -#define INTC_PCIC5_MSK 19 -#define INTC_SIOF_MSK 20 -#define INTC_HSPI_MSK 21 -#define INTC_MMCIF_MSK 22 -#define INTC_SSI_MSK 23 -#define INTC_FLCTL_MSK 24 -#define INTC_GPIO_MSK 25 - -#endif /* __ASM_SH_IRQ_SH7780_H */ diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 6cd3e9e2a76..fd576088e47 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -1,233 +1,9 @@ #ifndef __ASM_SH_IRQ_H #define __ASM_SH_IRQ_H -/* - * - * linux/include/asm-sh/irq.h - * - * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi - * Copyright (C) 2000 Kazumoto Kojima - * Copyright (C) 2003 Paul Mundt - * - */ - #include <asm/machvec.h> #include <asm/ptrace.h> /* for pt_regs */ -#ifndef CONFIG_CPU_SUBTYPE_SH7780 - -#define INTC_DMAC0_MSK 0 - -#if defined(CONFIG_CPU_SH3) -#define INTC_IPRA 0xfffffee2UL -#define INTC_IPRB 0xfffffee4UL -#elif defined(CONFIG_CPU_SH4) -#define INTC_IPRA 0xffd00004UL -#define INTC_IPRB 0xffd00008UL -#define INTC_IPRC 0xffd0000cUL -#define INTC_IPRD 0xffd00010UL -#endif - -#define TIMER_IRQ 16 -#define TIMER_IPR_ADDR INTC_IPRA -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -#define TIMER1_IRQ 17 -#define TIMER1_IPR_ADDR INTC_IPRA -#define TIMER1_IPR_POS 2 -#define TIMER1_PRIORITY 4 - -#define RTC_IRQ 22 -#define RTC_IPR_ADDR INTC_IPRA -#define RTC_IPR_POS 0 -#define RTC_PRIORITY TIMER_PRIORITY - -#if defined(CONFIG_CPU_SH3) -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA_IPR_ADDR INTC_IPRE -#define DMA_IPR_POS 3 -#define DMA_PRIORITY 7 -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -/* TMU2 */ -#define TIMER2_IRQ 18 -#define TIMER2_IPR_ADDR INTC_IPRA -#define TIMER2_IPR_POS 1 -#define TIMER2_PRIORITY 2 - -/* WDT */ -#define WDT_IRQ 27 -#define WDT_IPR_ADDR INTC_IPRB -#define WDT_IPR_POS 3 -#define WDT_PRIORITY 2 - -/* SIM (SIM Card Module) */ -#define SIM_ERI_IRQ 23 -#define SIM_RXI_IRQ 24 -#define SIM_TXI_IRQ 25 -#define SIM_TEND_IRQ 26 -#define SIM_IPR_ADDR INTC_IPRB -#define SIM_IPR_POS 1 -#define SIM_PRIORITY 2 - -/* VIO (Video I/O) */ -#define VIO_IRQ 52 -#define VIO_IPR_ADDR INTC_IPRE -#define VIO_IPR_POS 2 -#define VIO_PRIORITY 2 - -/* MFI (Multi Functional Interface) */ -#define MFI_IRQ 56 -#define MFI_IPR_ADDR INTC_IPRE -#define MFI_IPR_POS 1 -#define MFI_PRIORITY 2 - -/* VPU (Video Processing Unit) */ -#define VPU_IRQ 60 -#define VPU_IPR_ADDR INTC_IPRE -#define VPU_IPR_POS 0 -#define VPU_PRIORITY 2 - -/* KEY (Key Scan Interface) */ -#define KEY_IRQ 79 -#define KEY_IPR_ADDR INTC_IPRF -#define KEY_IPR_POS 3 -#define KEY_PRIORITY 2 - -/* CMT (Compare Match Timer) */ -#define CMT_IRQ 104 -#define CMT_IPR_ADDR INTC_IPRF -#define CMT_IPR_POS 0 -#define CMT_PRIORITY 2 - -/* DMAC(1) */ -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA1_IPR_ADDR INTC_IPRE -#define DMA1_IPR_POS 3 -#define DMA1_PRIORITY 7 - -/* DMAC(2) */ -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -/* SIOF0 */ -#define SIOF0_IRQ 84 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 3 -#define SIOF0_PRIORITY 3 - -/* FLCTL (Flash Memory Controller) */ -#define FLSTE_IRQ 92 -#define FLTEND_IRQ 93 -#define FLTRQ0_IRQ 94 -#define FLTRQ1_IRQ 95 -#define FLCTL_IPR_ADDR INTC_IPRH -#define FLCTL_IPR_POS 1 -#define FLCTL_PRIORITY 3 - -/* IIC (IIC Bus Interface) */ -#define IIC_ALI_IRQ 96 -#define IIC_TACKI_IRQ 97 -#define IIC_WAITI_IRQ 98 -#define IIC_DTEI_IRQ 99 -#define IIC_IPR_ADDR INTC_IPRH -#define IIC_IPR_POS 0 -#define IIC_PRIORITY 3 - -/* SIO0 */ -#define SIO0_IRQ 88 -#define SIO0_IPR_ADDR INTC_IPRI -#define SIO0_IPR_POS 3 -#define SIO0_PRIORITY 3 - -/* SIU (Sound Interface Unit) */ -#define SIU_IRQ 108 -#define SIU_IPR_ADDR INTC_IPRJ -#define SIU_IPR_POS 1 -#define SIU_PRIORITY 3 - -#endif -#elif defined(CONFIG_CPU_SH4) -#define DMTE0_IRQ 34 -#define DMTE1_IRQ 35 -#define DMTE2_IRQ 36 -#define DMTE3_IRQ 37 -#define DMTE4_IRQ 44 /* 7751R only */ -#define DMTE5_IRQ 45 /* 7751R only */ -#define DMTE6_IRQ 46 /* 7751R only */ -#define DMTE7_IRQ 47 /* 7751R only */ -#define DMAE_IRQ 38 -#define DMA_IPR_ADDR INTC_IPRC -#define DMA_IPR_POS 2 -#define DMA_PRIORITY 7 -#endif - -#if defined (CONFIG_CPU_SUBTYPE_SH7707) || defined (CONFIG_CPU_SUBTYPE_SH7708) || \ - defined (CONFIG_CPU_SUBTYPE_SH7709) || defined (CONFIG_CPU_SUBTYPE_SH7750) || \ - defined (CONFIG_CPU_SUBTYPE_SH7751) || defined (CONFIG_CPU_SUBTYPE_SH7706) -#define SCI_ERI_IRQ 23 -#define SCI_RXI_IRQ 24 -#define SCI_TXI_IRQ 25 -#define SCI_IPR_ADDR INTC_IPRB -#define SCI_IPR_POS 1 -#define SCI_PRIORITY 3 -#endif - -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -#define SCIF0_IRQ 80 -#define SCIF0_IPR_ADDR INTC_IPRG -#define SCIF0_IPR_POS 3 -#define SCIF0_PRIORITY 3 -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -#define SCIF_ERI_IRQ 56 -#define SCIF_RXI_IRQ 57 -#define SCIF_BRI_IRQ 58 -#define SCIF_TXI_IRQ 59 -#define SCIF_IPR_ADDR INTC_IPRE -#define SCIF_IPR_POS 1 -#define SCIF_PRIORITY 3 - -#define IRDA_ERI_IRQ 52 -#define IRDA_RXI_IRQ 53 -#define IRDA_BRI_IRQ 54 -#define IRDA_TXI_IRQ 55 -#define IRDA_IPR_ADDR INTC_IPRE -#define IRDA_IPR_POS 2 -#define IRDA_PRIORITY 3 -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ - defined(CONFIG_CPU_SUBTYPE_ST40STB1) || defined(CONFIG_CPU_SUBTYPE_SH4_202) -#define SCIF_ERI_IRQ 40 -#define SCIF_RXI_IRQ 41 -#define SCIF_BRI_IRQ 42 -#define SCIF_TXI_IRQ 43 -#define SCIF_IPR_ADDR INTC_IPRC -#define SCIF_IPR_POS 1 -#define SCIF_PRIORITY 3 -#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) -#define SCIF1_ERI_IRQ 23 -#define SCIF1_RXI_IRQ 24 -#define SCIF1_BRI_IRQ 25 -#define SCIF1_TXI_IRQ 26 -#define SCIF1_IPR_ADDR INTC_IPRB -#define SCIF1_IPR_POS 1 -#define SCIF1_PRIORITY 3 -#endif /* ST40STB1 */ - -#endif /* 775x / SH4-202 / ST40STB1 */ -#endif /* 7780 */ - /* NR_IRQS is made from three components: * 1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules * 2. PINT_NR_IRQS - number of PINT interrupts @@ -265,6 +41,10 @@ # define ONCHIP_NR_IRQS 109 #elif defined(CONFIG_CPU_SUBTYPE_SH7780) # define ONCHIP_NR_IRQS 111 +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +# define ONCHIP_NR_IRQS 256 +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +# define ONCHIP_NR_IRQS 128 #elif defined(CONFIG_SH_UNKNOWN) /* Most be last */ # define ONCHIP_NR_IRQS 144 #endif @@ -312,9 +92,11 @@ /* NR_IRQS. 1+2+3 */ #define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS) -extern void disable_irq(unsigned int); -extern void disable_irq_nosync(unsigned int); -extern void enable_irq(unsigned int); +/* + * Convert back and forth between INTEVT and IRQ values. + */ +#define evt2irq(evt) (((evt) >> 5) - 16) +#define irq2evt(irq) (((irq) + 16) << 5) /* * Simple Mask Register Support @@ -327,362 +109,36 @@ extern unsigned short *irq_mask_register; */ void init_IRQ_pint(void); +/* + * The shift value is now the number of bits to shift, not the number of + * bits/4. This is to make it easier to read the value directly from the + * datasheets. The IPR address, addr, will be set from ipr_idx via the + * map_ipridx_to_addr function. + */ struct ipr_data { unsigned int irq; - unsigned int addr; /* Address of Interrupt Priority Register */ - int shift; /* Shifts of the 16-bit data */ + int ipr_idx; /* Index for the IPR registered */ + int shift; /* Number of bits to shift the data */ int priority; /* The priority */ + unsigned int addr; /* Address of Interrupt Priority Register */ }; /* - * Function for "on chip support modules". + * Given an IPR IDX, map the value to an IPR register address. */ -extern void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs); -extern void make_imask_irq(unsigned int irq); - -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -#undef INTC_IPRA -#undef INTC_IPRB -#define INTC_IPRA 0xA414FEE2UL -#define INTC_IPRB 0xA414FEE4UL -#define INTC_IPRC 0xA4140016UL -#define INTC_IPRD 0xA4140018UL -#define INTC_IPRE 0xA414001AUL -#define INTC_IPRF 0xA4080000UL -#define INTC_IPRG 0xA4080002UL -#define INTC_IPRH 0xA4080004UL -#define INTC_IPRI 0xA4080006UL -#define INTC_IPRJ 0xA4080008UL - -#define INTC_IMR0 0xA4080040UL -#define INTC_IMR1 0xA4080042UL -#define INTC_IMR2 0xA4080044UL -#define INTC_IMR3 0xA4080046UL -#define INTC_IMR4 0xA4080048UL -#define INTC_IMR5 0xA408004AUL -#define INTC_IMR6 0xA408004CUL -#define INTC_IMR7 0xA408004EUL -#define INTC_IMR8 0xA4080050UL -#define INTC_IMR9 0xA4080052UL -#define INTC_IMR10 0xA4080054UL - -#define INTC_IMCR0 0xA4080060UL -#define INTC_IMCR1 0xA4080062UL -#define INTC_IMCR2 0xA4080064UL -#define INTC_IMCR3 0xA4080066UL -#define INTC_IMCR4 0xA4080068UL -#define INTC_IMCR5 0xA408006AUL -#define INTC_IMCR6 0xA408006CUL -#define INTC_IMCR7 0xA408006EUL -#define INTC_IMCR8 0xA4080070UL -#define INTC_IMCR9 0xA4080072UL -#define INTC_IMCR10 0xA4080074UL - -#define INTC_ICR0 0xA414FEE0UL -#define INTC_ICR1 0xA4140010UL - -#define INTC_IRR0 0xA4140004UL - -#define PORT_PACR 0xA4050100UL -#define PORT_PBCR 0xA4050102UL -#define PORT_PCCR 0xA4050104UL -#define PORT_PDCR 0xA4050106UL -#define PORT_PECR 0xA4050108UL -#define PORT_PFCR 0xA405010AUL -#define PORT_PGCR 0xA405010CUL -#define PORT_PHCR 0xA405010EUL -#define PORT_PJCR 0xA4050110UL -#define PORT_PKCR 0xA4050112UL -#define PORT_PLCR 0xA4050114UL -#define PORT_SCPCR 0xA4050116UL -#define PORT_PMCR 0xA4050118UL -#define PORT_PNCR 0xA405011AUL -#define PORT_PQCR 0xA405011CUL - -#define PORT_PSELA 0xA4050140UL -#define PORT_PSELB 0xA4050142UL -#define PORT_PSELC 0xA4050144UL - -#define PORT_HIZCRA 0xA4050146UL -#define PORT_HIZCRB 0xA4050148UL -#define PORT_DRVCR 0xA4050150UL - -#define PORT_PADR 0xA4050120UL -#define PORT_PBDR 0xA4050122UL -#define PORT_PCDR 0xA4050124UL -#define PORT_PDDR 0xA4050126UL -#define PORT_PEDR 0xA4050128UL -#define PORT_PFDR 0xA405012AUL -#define PORT_PGDR 0xA405012CUL -#define PORT_PHDR 0xA405012EUL -#define PORT_PJDR 0xA4050130UL -#define PORT_PKDR 0xA4050132UL -#define PORT_PLDR 0xA4050134UL -#define PORT_SCPDR 0xA4050136UL -#define PORT_PMDR 0xA4050138UL -#define PORT_PNDR 0xA405013AUL -#define PORT_PQDR 0xA405013CUL - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 - -#define IRQ0_IPR_ADDR INTC_IPRC -#define IRQ1_IPR_ADDR INTC_IPRC -#define IRQ2_IPR_ADDR INTC_IPRC -#define IRQ3_IPR_ADDR INTC_IPRC -#define IRQ4_IPR_ADDR INTC_IPRD -#define IRQ5_IPR_ADDR INTC_IPRD - -#define IRQ0_IPR_POS 0 -#define IRQ1_IPR_POS 1 -#define IRQ2_IPR_POS 2 -#define IRQ3_IPR_POS 3 -#define IRQ4_IPR_POS 0 -#define IRQ5_IPR_POS 1 +unsigned int map_ipridx_to_addr(int idx); -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 - -extern int ipr_irq_demux(int irq); -#define __irq_demux(irq) ipr_irq_demux(irq) - -#elif defined(CONFIG_CPU_SUBTYPE_SH7604) -#define INTC_IPRA 0xfffffee2UL -#define INTC_IPRB 0xfffffe60UL - -#define INTC_VCRA 0xfffffe62UL -#define INTC_VCRB 0xfffffe64UL -#define INTC_VCRC 0xfffffe66UL -#define INTC_VCRD 0xfffffe68UL - -#define INTC_VCRWDT 0xfffffee4UL -#define INTC_VCRDIV 0xffffff0cUL -#define INTC_VCRDMA0 0xffffffa0UL -#define INTC_VCRDMA1 0xffffffa8UL - -#define INTC_ICR 0xfffffee0UL -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7710) -#define INTC_IRR0 0xa4000004UL -#define INTC_IRR1 0xa4000006UL -#define INTC_IRR2 0xa4000008UL - -#define INTC_ICR0 0xfffffee0UL -#define INTC_ICR1 0xa4000010UL -#define INTC_ICR2 0xa4000012UL -#define INTC_INTER 0xa4000014UL - -#define INTC_IPRC 0xa4000016UL -#define INTC_IPRD 0xa4000018UL -#define INTC_IPRE 0xa400001aUL -#if defined(CONFIG_CPU_SUBTYPE_SH7707) -#define INTC_IPRF 0xa400001cUL -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) -#define INTC_IPRF 0xa4080000UL -#define INTC_IPRG 0xa4080002UL -#define INTC_IPRH 0xa4080004UL -#elif defined(CONFIG_CPU_SUBTYPE_SH7710) -/* Interrupt Controller Registers */ -#undef INTC_IPRA -#undef INTC_IPRB -#define INTC_IPRA 0xA414FEE2UL -#define INTC_IPRB 0xA414FEE4UL -#define INTC_IPRF 0xA4080000UL -#define INTC_IPRG 0xA4080002UL -#define INTC_IPRH 0xA4080004UL -#define INTC_IPRI 0xA4080006UL - -#undef INTC_ICR0 -#undef INTC_ICR1 -#define INTC_ICR0 0xA414FEE0UL -#define INTC_ICR1 0xA4140010UL - -#define INTC_IRR0 0xa4000004UL -#define INTC_IRR1 0xa4000006UL -#define INTC_IRR2 0xa4000008UL -#define INTC_IRR3 0xa400000AUL -#define INTC_IRR4 0xa400000CUL -#define INTC_IRR5 0xa4080020UL -#define INTC_IRR7 0xa4080024UL -#define INTC_IRR8 0xa4080026UL - -/* Interrupt numbers */ -#define TIMER2_IRQ 18 -#define TIMER2_IPR_ADDR INTC_IPRA -#define TIMER2_IPR_POS 1 -#define TIMER2_PRIORITY 2 - -/* WDT */ -#define WDT_IRQ 27 -#define WDT_IPR_ADDR INTC_IPRB -#define WDT_IPR_POS 3 -#define WDT_PRIORITY 2 - -#define SCIF0_ERI_IRQ 52 -#define SCIF0_RXI_IRQ 53 -#define SCIF0_BRI_IRQ 54 -#define SCIF0_TXI_IRQ 55 -#define SCIF0_IPR_ADDR INTC_IPRE -#define SCIF0_IPR_POS 2 -#define SCIF0_PRIORITY 3 - -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -#define IPSEC_IRQ 79 -#define IPSEC_IPR_ADDR INTC_IPRF -#define IPSEC_IPR_POS 3 -#define IPSEC_PRIORITY 3 - -/* EDMAC */ -#define EDMAC0_IRQ 80 -#define EDMAC0_IPR_ADDR INTC_IPRG -#define EDMAC0_IPR_POS 3 -#define EDMAC0_PRIORITY 3 - -#define EDMAC1_IRQ 81 -#define EDMAC1_IPR_ADDR INTC_IPRG -#define EDMAC1_IPR_POS 2 -#define EDMAC1_PRIORITY 3 - -#define EDMAC2_IRQ 82 -#define EDMAC2_IPR_ADDR INTC_IPRG -#define EDMAC2_IPR_POS 1 -#define EDMAC2_PRIORITY 3 - -/* SIOF */ -#define SIOF0_ERI_IRQ 96 -#define SIOF0_TXI_IRQ 97 -#define SIOF0_RXI_IRQ 98 -#define SIOF0_CCI_IRQ 99 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 0 -#define SIOF0_PRIORITY 7 - -#define SIOF1_ERI_IRQ 100 -#define SIOF1_TXI_IRQ 101 -#define SIOF1_RXI_IRQ 102 -#define SIOF1_CCI_IRQ 103 -#define SIOF1_IPR_ADDR INTC_IPRI -#define SIOF1_IPR_POS 1 -#define SIOF1_PRIORITY 7 -#endif /* CONFIG_CPU_SUBTYPE_SH7710 */ - -#if defined(CONFIG_CPU_SUBTYPE_SH7710) -#define PORT_PACR 0xa4050100UL -#define PORT_PBCR 0xa4050102UL -#define PORT_PCCR 0xa4050104UL -#define PORT_PETCR 0xa4050106UL -#define PORT_PADR 0xa4050120UL -#define PORT_PBDR 0xa4050122UL -#define PORT_PCDR 0xa4050124UL -#else -#define PORT_PACR 0xa4000100UL -#define PORT_PBCR 0xa4000102UL -#define PORT_PCCR 0xa4000104UL -#define PORT_PFCR 0xa400010aUL -#define PORT_PADR 0xa4000120UL -#define PORT_PBDR 0xa4000122UL -#define PORT_PCDR 0xa4000124UL -#define PORT_PFDR 0xa400012aUL -#endif - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 - -#define IRQ0_IPR_ADDR INTC_IPRC -#define IRQ1_IPR_ADDR INTC_IPRC -#define IRQ2_IPR_ADDR INTC_IPRC -#define IRQ3_IPR_ADDR INTC_IPRC -#define IRQ4_IPR_ADDR INTC_IPRD -#define IRQ5_IPR_ADDR INTC_IPRD - -#define IRQ0_IPR_POS 0 -#define IRQ1_IPR_POS 1 -#define IRQ2_IPR_POS 2 -#define IRQ3_IPR_POS 3 -#define IRQ4_IPR_POS 0 -#define IRQ5_IPR_POS 1 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 - -#define PINT0_IRQ 40 -#define PINT8_IRQ 41 - -#define PINT0_IPR_ADDR INTC_IPRD -#define PINT8_IPR_ADDR INTC_IPRD - -#define PINT0_IPR_POS 3 -#define PINT8_IPR_POS 2 -#define PINT0_PRIORITY 2 -#define PINT8_PRIORITY 2 - -extern int ipr_irq_demux(int irq); -#define __irq_demux(irq) ipr_irq_demux(irq) -#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ - -#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ - defined(CONFIG_CPU_SUBTYPE_ST40STB1) || defined(CONFIG_CPU_SUBTYPE_SH4_202) -#define INTC_ICR 0xffd00000 -#define INTC_ICR_NMIL (1<<15) -#define INTC_ICR_MAI (1<<14) -#define INTC_ICR_NMIB (1<<9) -#define INTC_ICR_NMIE (1<<8) -#define INTC_ICR_IRLM (1<<7) -#endif - -#ifdef CONFIG_CPU_SUBTYPE_SH7780 -#include <asm/irq-sh7780.h> -#endif - -/* SH with INTC2-style interrupts */ -#ifdef CONFIG_CPU_HAS_INTC2_IRQ -#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) -#define INTC2_BASE 0xfe080000 -#define INTC2_FIRST_IRQ 64 -#define INTC2_INTREQ_OFFSET 0x20 -#define INTC2_INTMSK_OFFSET 0x40 -#define INTC2_INTMSKCLR_OFFSET 0x60 -#define NR_INTC2_IRQS 25 -#elif defined(CONFIG_CPU_SUBTYPE_SH7760) -#define INTC2_BASE 0xfe080000 -#define INTC2_FIRST_IRQ 48 /* INTEVT 0x800 */ -#define INTC2_INTREQ_OFFSET 0x20 -#define INTC2_INTMSK_OFFSET 0x40 -#define INTC2_INTMSKCLR_OFFSET 0x60 -#define NR_INTC2_IRQS 64 -#elif defined(CONFIG_CPU_SUBTYPE_SH7780) -#define INTC2_BASE 0xffd40000 -#define INTC2_FIRST_IRQ 21 -#define INTC2_INTMSK_OFFSET (0x38) -#define INTC2_INTMSKCLR_OFFSET (0x3c) -#define NR_INTC2_IRQS 60 -#endif +/* + * Enable individual interrupt mode for external IPR IRQs. + */ +void ipr_irq_enable_irlm(void); -#define INTC2_INTPRI_OFFSET 0x00 +/* + * Function for "on chip support modules". + */ +void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs); +void make_imask_irq(unsigned int irq); +void init_IRQ_ipr(void); struct intc2_data { unsigned short irq; @@ -693,20 +149,14 @@ struct intc2_data { void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs); void init_IRQ_intc2(void); -#endif - -extern int shmse_irq_demux(int irq); static inline int generic_irq_demux(int irq) { return irq; } -#ifndef __irq_demux -#define __irq_demux(irq) (irq) -#endif #define irq_canonicalize(irq) (irq) -#define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) +#define irq_demux(irq) sh_mv.mv_irq_demux(irq) #ifdef CONFIG_4KSTACKS extern void irq_ctx_init(int cpu); @@ -717,12 +167,4 @@ extern void irq_ctx_exit(int cpu); # define irq_ctx_exit(cpu) do { } while (0) #endif -#if defined(CONFIG_CPU_SUBTYPE_SH73180) -#include <asm/irq-sh73180.h> -#endif - -#if defined(CONFIG_CPU_SUBTYPE_SH7343) -#include <asm/irq-sh7343.h> -#endif - #endif /* __ASM_SH_IRQ_H */ diff --git a/include/asm-sh/irqflags.h b/include/asm-sh/irqflags.h new file mode 100644 index 00000000000..9dedc1b693e --- /dev/null +++ b/include/asm-sh/irqflags.h @@ -0,0 +1,123 @@ +#ifndef __ASM_SH_IRQFLAGS_H +#define __ASM_SH_IRQFLAGS_H + +static inline void raw_local_irq_enable(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and %1, %0\n\t" +#ifdef CONFIG_CPU_HAS_SR_RB + "stc r6_bank, %1\n\t" + "or %1, %0\n\t" +#endif + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "1" (~0x000000f0) + : "memory" + ); +} + +static inline void raw_local_irq_disable(void) +{ + unsigned long flags; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "or #0xf0, %0\n\t" + "ldc %0, sr\n\t" + : "=&z" (flags) + : /* no inputs */ + : "memory" + ); +} + +static inline void set_bl_bit(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "or %2, %0\n\t" + "and %3, %0\n\t" + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "r" (0x10000000), "r" (0xffffff0f) + : "memory" + ); +} + +static inline void clear_bl_bit(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and %2, %0\n\t" + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "1" (~0x10000000) + : "memory" + ); +} + +static inline unsigned long __raw_local_save_flags(void) +{ + unsigned long flags; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and #0xf0, %0\n\t" + : "=&z" (flags) + : /* no inputs */ + : "memory" + ); + + return flags; +} + +#define raw_local_save_flags(flags) \ + do { (flags) = __raw_local_save_flags(); } while (0) + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return (flags != 0); +} + +static inline int raw_irqs_disabled(void) +{ + unsigned long flags = __raw_local_save_flags(); + + return raw_irqs_disabled_flags(flags); +} + +static inline unsigned long __raw_local_irq_save(void) +{ + unsigned long flags, __dummy; + + __asm__ __volatile__ ( + "stc sr, %1\n\t" + "mov %1, %0\n\t" + "or #0xf0, %0\n\t" + "ldc %0, sr\n\t" + "mov %1, %0\n\t" + "and #0xf0, %0\n\t" + : "=&z" (flags), "=&r" (__dummy) + : /* no inputs */ + : "memory" + ); + + return flags; +} + +#define raw_local_irq_save(flags) \ + do { (flags) = __raw_local_irq_save(); } while (0) + +static inline void raw_local_irq_restore(unsigned long flags) +{ + if ((flags & 0xf0) != 0xf0) + raw_local_irq_enable(); +} + +#endif /* __ASM_SH_IRQFLAGS_H */ diff --git a/include/asm-sh/mmu_context.h b/include/asm-sh/mmu_context.h index c7088efe579..46f04e23bd4 100644 --- a/include/asm-sh/mmu_context.h +++ b/include/asm-sh/mmu_context.h @@ -10,7 +10,6 @@ #include <asm/cpu/mmu_context.h> #include <asm/tlbflush.h> -#include <asm/pgalloc.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -42,10 +41,8 @@ extern unsigned long mmu_context_cache; /* * Get MMU context if needed. */ -static __inline__ void -get_mmu_context(struct mm_struct *mm) +static inline void get_mmu_context(struct mm_struct *mm) { - extern void flush_tlb_all(void); unsigned long mc = mmu_context_cache; /* Check if we have old version of context. */ @@ -61,6 +58,7 @@ get_mmu_context(struct mm_struct *mm) * Flush all TLB and start new cycle. */ flush_tlb_all(); + /* * Fix version; Note that we avoid version #0 * to distingush NO_CONTEXT. @@ -75,11 +73,10 @@ get_mmu_context(struct mm_struct *mm) * Initialize the context related info for a new mm_struct * instance. */ -static __inline__ int init_new_context(struct task_struct *tsk, +static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { mm->context.id = NO_CONTEXT; - return 0; } @@ -87,12 +84,12 @@ static __inline__ int init_new_context(struct task_struct *tsk, * Destroy context related info for an mm_struct that is about * to be put to rest. */ -static __inline__ void destroy_context(struct mm_struct *mm) +static inline void destroy_context(struct mm_struct *mm) { /* Do nothing */ } -static __inline__ void set_asid(unsigned long asid) +static inline void set_asid(unsigned long asid) { unsigned long __dummy; @@ -105,7 +102,7 @@ static __inline__ void set_asid(unsigned long asid) "r" (0xffffff00)); } -static __inline__ unsigned long get_asid(void) +static inline unsigned long get_asid(void) { unsigned long asid; @@ -120,24 +117,29 @@ static __inline__ unsigned long get_asid(void) * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. */ -static __inline__ void activate_context(struct mm_struct *mm) +static inline void activate_context(struct mm_struct *mm) { get_mmu_context(mm); set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK); } -/* MMU_TTB can be used for optimizing the fault handling. - (Currently not used) */ -static __inline__ void switch_mm(struct mm_struct *prev, - struct mm_struct *next, - struct task_struct *tsk) +/* MMU_TTB is used for optimizing the fault handling. */ +static inline void set_TTB(pgd_t *pgd) { - if (likely(prev != next)) { - unsigned long __pgdir = (unsigned long)next->pgd; + ctrl_outl((unsigned long)pgd, MMU_TTB); +} - __asm__ __volatile__("mov.l %0, %1" - : /* no output */ - : "r" (__pgdir), "m" (__m(MMU_TTB))); +static inline pgd_t *get_TTB(void) +{ + return (pgd_t *)ctrl_inl(MMU_TTB); +} + +static inline void switch_mm(struct mm_struct *prev, + struct mm_struct *next, + struct task_struct *tsk) +{ + if (likely(prev != next)) { + set_TTB(next->pgd); activate_context(next); } } @@ -147,7 +149,7 @@ static __inline__ void switch_mm(struct mm_struct *prev, #define activate_mm(prev, next) \ switch_mm((prev),(next),NULL) -static __inline__ void +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index ca8b26d9047..380fd62dd05 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -13,9 +13,16 @@ [ P4 control ] 0xE0000000 */ - /* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 +#if defined(CONFIG_PAGE_SIZE_4KB) +# define PAGE_SHIFT 12 +#elif defined(CONFIG_PAGE_SIZE_8KB) +# define PAGE_SHIFT 13 +#elif defined(CONFIG_PAGE_SIZE_64KB) +# define PAGE_SHIFT 16 +#else +# error "Bogus kernel page size?" +#endif #ifdef __ASSEMBLY__ #define PAGE_SIZE (1 << PAGE_SHIFT) @@ -28,8 +35,14 @@ #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) #define HPAGE_SHIFT 16 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) +#define HPAGE_SHIFT 18 #elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) #define HPAGE_SHIFT 20 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +#define HPAGE_SHIFT 22 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) +#define HPAGE_SHIFT 26 #endif #ifdef CONFIG_HUGETLB_PAGE @@ -69,15 +82,25 @@ extern void __copy_user_page(void *to, void *from, void *orig_to); /* * These are used to make use of C type-checking.. */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pgd; } pgd_t; +#ifdef CONFIG_X2TLB +typedef struct { unsigned long pte_low, pte_high; } pte_t; +typedef struct { unsigned long long pgprot; } pgprot_t; +#define pte_val(x) \ + ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) +#define __pte(x) \ + ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) +#else +typedef struct { unsigned long pte_low; } pte_t; typedef struct { unsigned long pgprot; } pgprot_t; +#define pte_val(x) ((x).pte_low) +#define __pte(x) ((pte_t) { (x) } ) +#endif + +typedef struct { unsigned long pgd; } pgd_t; -#define pte_val(x) ((x).pte) #define pgd_val(x) ((x).pgd) #define pgprot_val(x) ((x).pgprot) -#define __pte(x) ((pte_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h index e841465ab4d..888e4529e6f 100644 --- a/include/asm-sh/pgalloc.h +++ b/include/asm-sh/pgalloc.h @@ -1,13 +1,16 @@ #ifndef __ASM_SH_PGALLOC_H #define __ASM_SH_PGALLOC_H -#define pmd_populate_kernel(mm, pmd, pte) \ - set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + set_pmd(pmd, __pmd((unsigned long)pte)); +} static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) { - set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); + set_pmd(pmd, __pmd((unsigned long)page_address(pte))); } /* @@ -15,7 +18,16 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, */ static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); + pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); + + if (pgd) { + memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); + memcpy(pgd + USER_PTRS_PER_PGD, + swapper_pg_dir + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + + return pgd; } static inline void pgd_free(pgd_t *pgd) diff --git a/include/asm-sh/pgtable-2level.h b/include/asm-sh/pgtable-2level.h deleted file mode 100644 index b525db6f61c..00000000000 --- a/include/asm-sh/pgtable-2level.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __ASM_SH_PGTABLE_2LEVEL_H -#define __ASM_SH_PGTABLE_2LEVEL_H - -/* - * traditional two-level paging structure: - */ - -#define PGDIR_SHIFT 22 -#define PTRS_PER_PGD 1024 - -/* - * this is two-level, so we don't really have any - * PMD directory physically. - */ -#define PMD_SHIFT 22 -#define PTRS_PER_PMD 1 - -#define PTRS_PER_PTE 1024 - -#ifndef __ASSEMBLY__ -#define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -#define pmd_ERROR(e) \ - printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -#define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) - -/* - * The "pgd_xxx()" functions here are trivial for a folded two-level - * setup: the pgd is never bad, and a pmd always exists (as it's folded - * into the pgd entry) - */ -static inline int pgd_none(pgd_t pgd) { return 0; } -static inline int pgd_bad(pgd_t pgd) { return 0; } -static inline int pgd_present(pgd_t pgd) { return 1; } -static inline void pgd_clear (pgd_t * pgdp) { } - -/* - * Certain architectures need to do special things when PTEs - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#define set_pte(pteptr, pteval) (*(pteptr) = pteval) -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) - -/* - * (pmds are folded into pgds so this doesn't get actually called, - * but the define is needed for a generic inline function.) - */ -#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) - -#define pgd_page_vaddr(pgd) \ -((unsigned long) __va(pgd_val(pgd) & PAGE_MASK)) - -#define pgd_page(pgd) \ - (phys_to_page(pgd_val(pgd))) - -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} - -#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) -#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) -#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_SH_PGTABLE_2LEVEL_H */ diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 2c8682ad101..c84901dbd8e 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -15,15 +15,10 @@ #include <asm-generic/pgtable-nopmd.h> #include <asm/page.h> -#define PTRS_PER_PGD 1024 - #ifndef __ASSEMBLY__ #include <asm/addrspace.h> #include <asm/fixmap.h> -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -extern void paging_init(void); - /* * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. @@ -33,15 +28,28 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #endif /* !__ASSEMBLY__ */ -/* traditional two-level paging structure */ -#define PGDIR_SHIFT 22 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PTE 1024 -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +/* + * traditional two-level paging structure + */ +/* PTE bits */ +#ifdef CONFIG_X2TLB +# define PTE_MAGNITUDE 3 /* 64-bit PTEs on extended mode SH-X2 TLB */ +#else +# define PTE_MAGNITUDE 2 /* 32-bit PTEs */ +#endif +#define PTE_SHIFT PAGE_SHIFT +#define PTE_BITS (PTE_SHIFT - PTE_MAGNITUDE) + +/* PGD bits */ +#define PGDIR_SHIFT (PTE_SHIFT + PTE_BITS) +#define PGDIR_BITS (32 - PGDIR_SHIFT) +#define PGDIR_SIZE (1 << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) +/* Entries per level */ +#define PTRS_PER_PTE (PAGE_SIZE / 4) +#define PTRS_PER_PGD (PAGE_SIZE / 4) + #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_ADDRESS 0 @@ -49,7 +57,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; /* * First 1MB map is used by fixed purpose. - * Currently only 4-enty (16kB) is used (see arch/sh/mm/cache.c) + * Currently only 4-entry (16kB) is used (see arch/sh/mm/cache.c) */ #define VMALLOC_START (P3SEG+0x00100000) #define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) @@ -57,7 +65,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; /* * Linux PTEL encoding. * - * Hardware and software bit definitions for the PTEL value: + * Hardware and software bit definitions for the PTEL value (see below for + * notes on SH-X2 MMUs and 64-bit PTEs): * * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4). * @@ -76,20 +85,57 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; * * - Bits 31, 30, and 29 remain unused by everyone and can be used for future * software flags, although care must be taken to update _PAGE_CLEAR_FLAGS. + * + * XXX: Leave the _PAGE_FILE and _PAGE_WT overhaul for a rainy day. + * + * SH-X2 MMUs and extended PTEs + * + * SH-X2 supports an extended mode TLB with split data arrays due to the + * number of bits needed for PR and SZ (now EPR and ESZ) encodings. The PR and + * SZ bit placeholders still exist in data array 1, but are implemented as + * reserved bits, with the real logic existing in data array 2. + * + * The downside to this is that we can no longer fit everything in to a 32-bit + * PTE encoding, so a 64-bit pte_t is necessary for these parts. On the plus + * side, this gives us quite a few spare bits to play with for future usage. */ +/* Legacy and compat mode bits */ #define _PAGE_WT 0x001 /* WT-bit on SH-4, 0 on SH-3 */ #define _PAGE_HW_SHARED 0x002 /* SH-bit : shared among processes */ #define _PAGE_DIRTY 0x004 /* D-bit : page changed */ #define _PAGE_CACHABLE 0x008 /* C-bit : cachable */ -#define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ -#define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ -#define _PAGE_USER 0x040 /* PR1-bit : user space access allowed */ -#define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */ +#ifndef CONFIG_X2TLB +# define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ +# define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ +# define _PAGE_USER 0x040 /* PR1-bit : user space access allowed*/ +# define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */ +#endif #define _PAGE_PRESENT 0x100 /* V-bit : page is valid */ #define _PAGE_PROTNONE 0x200 /* software: if not present */ #define _PAGE_ACCESSED 0x400 /* software: page referenced */ #define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */ +/* Extended mode bits */ +#define _PAGE_EXT_ESZ0 0x0010 /* ESZ0-bit: Size of page */ +#define _PAGE_EXT_ESZ1 0x0020 /* ESZ1-bit: Size of page */ +#define _PAGE_EXT_ESZ2 0x0040 /* ESZ2-bit: Size of page */ +#define _PAGE_EXT_ESZ3 0x0080 /* ESZ3-bit: Size of page */ + +#define _PAGE_EXT_USER_EXEC 0x0100 /* EPR0-bit: User space executable */ +#define _PAGE_EXT_USER_WRITE 0x0200 /* EPR1-bit: User space writable */ +#define _PAGE_EXT_USER_READ 0x0400 /* EPR2-bit: User space readable */ + +#define _PAGE_EXT_KERN_EXEC 0x0800 /* EPR3-bit: Kernel space executable */ +#define _PAGE_EXT_KERN_WRITE 0x1000 /* EPR4-bit: Kernel space writable */ +#define _PAGE_EXT_KERN_READ 0x2000 /* EPR5-bit: Kernel space readable */ + +/* Wrapper for extended mode pgprot twiddling */ +#ifdef CONFIG_X2TLB +# define _PAGE_EXT(x) ((unsigned long long)(x) << 32) +#else +# define _PAGE_EXT(x) (0) +#endif + /* software: moves to PTEA.TC (Timing Control) */ #define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ #define _PAGE_PCC_AREA6 0x80000000 /* use BSC registers for area6 */ @@ -114,37 +160,160 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define _PAGE_FLAGS_HARDWARE_MASK (0x1fffffff & ~(_PAGE_CLEAR_FLAGS)) -/* Hardware flags: SZ0=1 (4k-byte) */ -#define _PAGE_FLAGS_HARD _PAGE_SZ0 +/* Hardware flags, page size encoding */ +#if defined(CONFIG_X2TLB) +# if defined(CONFIG_PAGE_SIZE_4KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ0) +# elif defined(CONFIG_PAGE_SIZE_8KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ1) +# elif defined(CONFIG_PAGE_SIZE_64KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ2) +# endif +#else +# if defined(CONFIG_PAGE_SIZE_4KB) +# define _PAGE_FLAGS_HARD _PAGE_SZ0 +# elif defined(CONFIG_PAGE_SIZE_64KB) +# define _PAGE_FLAGS_HARD _PAGE_SZ1 +# endif +#endif -#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -#define _PAGE_SZHUGE (_PAGE_SZ1) -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) -#define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1) +#if defined(CONFIG_X2TLB) +# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ1 | _PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ3) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2 | _PAGE_EXT_ESZ3) +# endif +#else +# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +# define _PAGE_SZHUGE (_PAGE_SZ1) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1) +# endif +#endif + +/* + * Stub out _PAGE_SZHUGE if we don't have a good definition for it, + * to make pte_mkhuge() happy. + */ +#ifndef _PAGE_SZHUGE +# define _PAGE_SZHUGE (_PAGE_FLAGS_HARD) #endif -#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) +#define _PAGE_CHG_MASK \ + (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) #ifndef __ASSEMBLY__ -#ifdef CONFIG_MMU -#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) +#if defined(CONFIG_X2TLB) /* SH-X2 TLB */ +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_READ | \ + _PAGE_EXT_USER_WRITE)) + +#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_EXEC | \ + _PAGE_EXT_USER_READ)) + +#define PAGE_COPY PAGE_EXECREAD + +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_READ)) + +#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_WRITE)) + +#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_WRITE | \ + _PAGE_EXT_USER_READ | \ + _PAGE_EXT_USER_EXEC)) + +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC)) + #define PAGE_KERNEL_NOCACHE \ - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) -#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_HW_SHARED | \ + _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_PCC(slot, type) \ + __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC) \ + (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ + (type)) + +#elif defined(CONFIG_MMU) /* SH-X TLB */ +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ + _PAGE_CACHABLE | _PAGE_ACCESSED | \ + _PAGE_FLAGS_HARD) + +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_EXECREAD PAGE_READONLY +#define PAGE_RWX PAGE_SHARED +#define PAGE_WRITEONLY PAGE_SHARED + +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + +#define PAGE_KERNEL_NOCACHE \ + __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_HW_SHARED | \ + _PAGE_FLAGS_HARD) + +#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + #define PAGE_KERNEL_PCC(slot, type) \ - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_FLAGS_HARD | (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | (type)) + __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ + (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ + (type)) #else /* no mmu */ #define PAGE_NONE __pgprot(0) #define PAGE_SHARED __pgprot(0) #define PAGE_COPY __pgprot(0) +#define PAGE_EXECREAD __pgprot(0) +#define PAGE_RWX __pgprot(0) #define PAGE_READONLY __pgprot(0) +#define PAGE_WRITEONLY __pgprot(0) #define PAGE_KERNEL __pgprot(0) #define PAGE_KERNEL_NOCACHE __pgprot(0) #define PAGE_KERNEL_RO __pgprot(0) @@ -154,27 +323,32 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #endif /* __ASSEMBLY__ */ /* - * As i386 and MIPS, SuperH can't do page protection for execute, and - * considers that the same as a read. Also, write permissions imply - * read permissions. This is the closest we can get.. + * SH-X and lower (legacy) SuperH parts (SH-3, SH-4, some SH-4A) can't do page + * protection for execute, and considers it the same as a read. Also, write + * permission implies read permission. This is the closest we can get.. + * + * SH-X2 (SH7785) and later parts take this to the opposite end of the extreme, + * not only supporting separate execute, read, and write bits, but having + * completely separate permission bits for user and kernel space. */ + /*xwr*/ #define __P000 PAGE_NONE #define __P001 PAGE_READONLY #define __P010 PAGE_COPY #define __P011 PAGE_COPY -#define __P100 PAGE_READONLY -#define __P101 PAGE_READONLY +#define __P100 PAGE_EXECREAD +#define __P101 PAGE_EXECREAD #define __P110 PAGE_COPY #define __P111 PAGE_COPY #define __S000 PAGE_NONE #define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED +#define __S010 PAGE_WRITEONLY #define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY -#define __S101 PAGE_READONLY -#define __S110 PAGE_SHARED -#define __S111 PAGE_SHARED +#define __S100 PAGE_EXECREAD +#define __S101 PAGE_EXECREAD +#define __S110 PAGE_RWX +#define __S111 PAGE_RWX #ifndef __ASSEMBLY__ @@ -183,7 +357,17 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; * within a page table are directly modified. Thus, the following * hook is made available. */ +#ifdef CONFIG_X2TLB +static inline void set_pte(pte_t *ptep, pte_t pte) +{ + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +} +#else #define set_pte(pteptr, pteval) (*(pteptr) = pteval) +#endif + #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) /* @@ -192,18 +376,18 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; */ #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) +#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pte_none(x) (!pte_val(x)) #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) -#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) +#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) #define pmd_none(x) (!pmd_val(x)) -#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) +#define pmd_present(x) (pmd_val(x)) #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) -#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) +#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK) #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) #define pte_page(x) phys_to_page(pte_val(x)&PTE_PHYS_MASK) @@ -212,28 +396,52 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; * The following only work if pte_present() is true. * Undefined behaviour if not.. */ -static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; } -static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; } -static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } -static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; } -static inline int pte_not_present(pte_t pte){ return !(pte_val(pte) & _PAGE_PRESENT); } - -static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; } -static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; } -static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; } -static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; } -static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; } -static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; } -static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; } -static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } -static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } -static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } -#ifdef CONFIG_HUGETLB_PAGE -static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; } +#define pte_not_present(pte) (!(pte_val(pte) & _PAGE_PRESENT)) +#define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY) +#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED) +#define pte_file(pte) (pte_val(pte) & _PAGE_FILE) + +#ifdef CONFIG_X2TLB +#define pte_read(pte) ((pte).pte_high & _PAGE_EXT_USER_READ) +#define pte_exec(pte) ((pte).pte_high & _PAGE_EXT_USER_EXEC) +#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) +#else +#define pte_read(pte) (pte_val(pte) & _PAGE_USER) +#define pte_exec(pte) (pte_val(pte) & _PAGE_USER) +#define pte_write(pte) (pte_val(pte) & _PAGE_RW) #endif +#define PTE_BIT_FUNC(h,fn,op) \ +static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; } + +#ifdef CONFIG_X2TLB +/* + * We cheat a bit in the SH-X2 TLB case. As the permission bits are + * individually toggled (and user permissions are entirely decoupled from + * kernel permissions), we attempt to couple them a bit more sanely here. + */ +PTE_BIT_FUNC(high, rdprotect, &= ~_PAGE_EXT_USER_READ); +PTE_BIT_FUNC(high, mkread, |= _PAGE_EXT_USER_READ | _PAGE_EXT_KERN_READ); +PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE); +PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE); +PTE_BIT_FUNC(high, exprotect, &= ~_PAGE_EXT_USER_EXEC); +PTE_BIT_FUNC(high, mkexec, |= _PAGE_EXT_USER_EXEC | _PAGE_EXT_KERN_EXEC); +PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE); +#else +PTE_BIT_FUNC(low, rdprotect, &= ~_PAGE_USER); +PTE_BIT_FUNC(low, mkread, |= _PAGE_USER); +PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW); +PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW); +PTE_BIT_FUNC(low, exprotect, &= ~_PAGE_USER); +PTE_BIT_FUNC(low, mkexec, |= _PAGE_USER); +PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE); +#endif + +PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY); +PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY); +PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED); +PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED); + /* * Macro and implementation to make a page protection as uncachable. */ @@ -258,13 +466,14 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot) #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; } - -#define pmd_page_vaddr(pmd) \ -((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) +{ + set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | + pgprot_val(newprot))); + return pte; +} -#define pmd_page(pmd) \ - (phys_to_page(pmd_val(pmd))) +#define pmd_page_vaddr(pmd) pmd_val(pmd) +#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) /* to find an entry in a page-table-directory. */ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) @@ -283,8 +492,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pte_unmap(pte) do { } while (0) #define pte_unmap_nested(pte) do { } while (0) +#ifdef CONFIG_X2TLB +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \ + &(e), (e).pte_high, (e).pte_low) +#else #define pte_ERROR(e) \ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) +#endif + #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) @@ -337,6 +553,9 @@ extern unsigned int kobjsize(const void *objp); extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); #endif +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern void paging_init(void); + #include <asm-generic/pgtable.h> #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 45bb74e35d3..6f1dd7ca1b1 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -36,7 +36,10 @@ */ enum cpu_type { /* SH-2 types */ - CPU_SH7604, + CPU_SH7604, CPU_SH7619, + + /* SH-2A types */ + CPU_SH7206, /* SH-3 types */ CPU_SH7705, CPU_SH7706, CPU_SH7707, @@ -47,7 +50,10 @@ enum cpu_type { /* SH-4 types */ CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R, CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501, + + /* SH-4A types */ CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781, + CPU_SH7785, /* Unknown subtype */ CPU_SH_NONE @@ -130,12 +136,11 @@ union sh_fpu_union { }; struct thread_struct { + /* Saved registers when thread is descheduled */ unsigned long sp; unsigned long pc; - unsigned long trap_no, error_code; - unsigned long address; - /* Hardware debugging registers may come here */ + /* Hardware debugging registers */ unsigned long ubc_pc; /* floating point info */ @@ -150,12 +155,7 @@ typedef struct { extern int ubc_usercnt; #define INIT_THREAD { \ - sizeof(init_stack) + (long) &init_stack, /* sp */ \ - 0, /* pc */ \ - 0, 0, \ - 0, \ - 0, \ - {{{0,}},} /* fpu state */ \ + .sp = sizeof(init_stack) + (long) &init_stack, \ } /* @@ -259,8 +259,8 @@ void show_trace(struct task_struct *tsk, unsigned long *sp, struct pt_regs *regs); extern unsigned long get_wchan(struct task_struct *p); -#define KSTK_EIP(tsk) ((tsk)->thread.pc) -#define KSTK_ESP(tsk) ((tsk)->thread.sp) +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) #define cpu_sleep() __asm__ __volatile__ ("sleep" : : : "memory") #define cpu_relax() barrier() diff --git a/include/asm-sh/push-switch.h b/include/asm-sh/push-switch.h new file mode 100644 index 00000000000..dfc6bad567f --- /dev/null +++ b/include/asm-sh/push-switch.h @@ -0,0 +1,28 @@ +#ifndef __ASM_SH_PUSH_SWITCH_H +#define __ASM_SH_PUSH_SWITCH_H + +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> + +struct push_switch { + /* switch state */ + unsigned int state:1; + /* debounce timer */ + struct timer_list debounce; + /* workqueue */ + struct work_struct work; +}; + +struct push_switch_platform_info { + /* IRQ handler */ + irqreturn_t (*irq_handler)(int irq, void *data); + /* Special IRQ flags */ + unsigned int irq_flags; + /* Bit location of switch */ + unsigned int bit; + /* Symbolic switch name */ + const char *name; +}; + +#endif /* __ASM_SH_PUSH_SWITCH_H */ diff --git a/include/asm-sh/rwsem.h b/include/asm-sh/rwsem.h index 9d2aea5e848..4931ba817d7 100644 --- a/include/asm-sh/rwsem.h +++ b/include/asm-sh/rwsem.h @@ -25,11 +25,21 @@ struct rw_semaphore { #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) spinlock_t wait_lock; struct list_head wait_list; +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map dep_map; +#endif }; +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname } +#else +# define __RWSEM_DEP_MAP_INIT(lockname) +#endif + #define __RWSEM_INITIALIZER(name) \ { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \ - LIST_HEAD_INIT((name).wait_list) } + LIST_HEAD_INIT((name).wait_list) \ + __RWSEM_DEP_MAP_INIT(name) } #define DECLARE_RWSEM(name) \ struct rw_semaphore name = __RWSEM_INITIALIZER(name) @@ -39,6 +49,16 @@ extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); +extern void __init_rwsem(struct rw_semaphore *sem, const char *name, + struct lock_class_key *key); + +#define init_rwsem(sem) \ +do { \ + static struct lock_class_key __key; \ + \ + __init_rwsem((sem), #sem, &__key); \ +} while (0) + static inline void init_rwsem(struct rw_semaphore *sem) { sem->count = RWSEM_UNLOCKED_VALUE; @@ -141,6 +161,11 @@ static inline void __downgrade_write(struct rw_semaphore *sem) rwsem_downgrade_wake(sem); } +static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) +{ + __down_write(sem); +} + /* * implement exchange and add functionality */ diff --git a/include/asm-sh/se7206.h b/include/asm-sh/se7206.h new file mode 100644 index 00000000000..698eb80389a --- /dev/null +++ b/include/asm-sh/se7206.h @@ -0,0 +1,13 @@ +#ifndef __ASM_SH_SE7206_H +#define __ASM_SH_SE7206_H + +#define PA_SMSC 0x30000000 +#define PA_MRSHPC 0x34000000 +#define PA_LED 0x31400000 + +void init_se7206_IRQ(void); + +#define __IO_PREFIX se7206 +#include <asm/io_generic.h> + +#endif /* __ASM_SH_SE7206_H */ diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 3340126f4e0..b1e42e7f998 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h @@ -6,6 +6,7 @@ * Copyright (C) 2002 Paul Mundt */ +#include <linux/irqflags.h> #include <asm/types.h> /* @@ -131,103 +132,6 @@ static inline unsigned long tas(volatile int *m) #define set_mb(var, value) do { xchg(&var, value); } while (0) -/* Interrupt Control */ -#ifdef CONFIG_CPU_HAS_SR_RB -static inline void local_irq_enable(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__("stc sr, %0\n\t" - "and %1, %0\n\t" - "stc r6_bank, %1\n\t" - "or %1, %0\n\t" - "ldc %0, sr" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x000000f0) - : "memory"); -} -#else -static inline void local_irq_enable(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and %1, %0\n\t" - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x000000f0) - : "memory"); -} -#endif - -static inline void local_irq_disable(void) -{ - unsigned long __dummy; - __asm__ __volatile__("stc sr, %0\n\t" - "or #0xf0, %0\n\t" - "ldc %0, sr" - : "=&z" (__dummy) - : /* no inputs */ - : "memory"); -} - -static inline void set_bl_bit(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ("stc sr, %0\n\t" - "or %2, %0\n\t" - "and %3, %0\n\t" - "ldc %0, sr" - : "=&r" (__dummy0), "=r" (__dummy1) - : "r" (0x10000000), "r" (0xffffff0f) - : "memory"); -} - -static inline void clear_bl_bit(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ("stc sr, %0\n\t" - "and %2, %0\n\t" - "ldc %0, sr" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x10000000) - : "memory"); -} - -#define local_save_flags(x) \ - __asm__("stc sr, %0; and #0xf0, %0" : "=&z" (x) :/**/: "memory" ) - -#define irqs_disabled() \ -({ \ - unsigned long flags; \ - local_save_flags(flags); \ - (flags != 0); \ -}) - -static inline unsigned long local_irq_save(void) -{ - unsigned long flags, __dummy; - - __asm__ __volatile__("stc sr, %1\n\t" - "mov %1, %0\n\t" - "or #0xf0, %0\n\t" - "ldc %0, sr\n\t" - "mov %1, %0\n\t" - "and #0xf0, %0" - : "=&z" (flags), "=&r" (__dummy) - :/**/ - : "memory" ); - return flags; -} - -#define local_irq_restore(x) do { \ - if ((x & 0x000000f0) != 0x000000f0) \ - local_irq_enable(); \ -} while (0) - /* * Jump to P2 area. * When handling TLB or caches, we need to do it from P2 area. @@ -264,9 +168,6 @@ do { \ : "=&r" (__dummy)); \ } while (0) -/* For spinlocks etc */ -#define local_irq_save(x) x = local_irq_save() - static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) { unsigned long flags, retval; diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index 3ebc3f9039e..0c01dc55081 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h @@ -90,13 +90,7 @@ static inline struct thread_info *current_thread_info(void) #endif #define free_thread_info(ti) kfree(ti) -#else /* !__ASSEMBLY__ */ - -/* how to get the thread information struct from ASM */ -#define GET_THREAD_INFO(reg) \ - stc r7_bank, reg - -#endif +#endif /* __ASSEMBLY__ */ /* * thread information flags diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h index 5df842bcf7b..17b5e76a4c3 100644 --- a/include/asm-sh/timer.h +++ b/include/asm-sh/timer.h @@ -18,11 +18,32 @@ struct sys_timer { struct sys_device dev; struct sys_timer_ops *ops; + +#ifdef CONFIG_NO_IDLE_HZ + struct dyn_tick_timer *dyn_tick; +#endif }; +#ifdef CONFIG_NO_IDLE_HZ +#define DYN_TICK_ENABLED (1 << 1) + +struct dyn_tick_timer { + spinlock_t lock; + unsigned int state; /* Current state */ + int (*enable)(void); /* Enables dynamic tick */ + int (*disable)(void); /* Disables dynamic tick */ + void (*reprogram)(unsigned long); /* Reprograms the timer */ + int (*handler)(int, void *); +}; + +void timer_dyn_reprogram(void); +#else +#define timer_dyn_reprogram() do { } while (0) +#endif + #define TICK_SIZE (tick_nsec / 1000) -extern struct sys_timer tmu_timer; +extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer; extern struct sys_timer *sys_timer; #ifndef CONFIG_GENERIC_TIME diff --git a/include/asm-sh/titan.h b/include/asm-sh/titan.h index 270a4f4bc8a..03f3583c891 100644 --- a/include/asm-sh/titan.h +++ b/include/asm-sh/titan.h @@ -1,9 +1,8 @@ /* * Platform defintions for Titan */ - -#ifndef _ASM_SH_TITAN_TITAN_H -#define _ASM_SH_TITAN_TITAN_H +#ifndef _ASM_SH_TITAN_H +#define _ASM_SH_TITAN_H #define __IO_PREFIX titan #include <asm/io_generic.h> @@ -15,29 +14,4 @@ #define TITAN_IRQ_MPCIB 11 /* mPCI B */ #define TITAN_IRQ_USB 11 /* USB */ -/* - * The external interrupt lines, these take up ints 0 - 15 inclusive - * depending on the priority for the interrupt. In fact the priority - * is the interrupt :-) - */ -#define IRL0_IRQ 0 -#define IRL0_IPR_ADDR INTC_IPRD -#define IRL0_IPR_POS 3 -#define IRL0_PRIORITY 8 - -#define IRL1_IRQ 1 -#define IRL1_IPR_ADDR INTC_IPRD -#define IRL1_IPR_POS 2 -#define IRL1_PRIORITY 8 - -#define IRL2_IRQ 2 -#define IRL2_IPR_ADDR INTC_IPRD -#define IRL2_IPR_POS 1 -#define IRL2_PRIORITY 8 - -#define IRL3_IRQ 3 -#define IRL3_IPR_ADDR INTC_IPRD -#define IRL3_IPR_POS 0 -#define IRL3_PRIORITY 8 - -#endif +#endif /* __ASM_SH_TITAN_H */ diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index 1c2abde122c..0cae1d24876 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -349,12 +349,30 @@ do { \ return (type) (res); \ } while (0) +#if defined(__sh2__) || defined(__SH2E__) || defined(__SH2A__) +#define SYSCALL_ARG0 "trapa #0x20" +#define SYSCALL_ARG1 "trapa #0x21" +#define SYSCALL_ARG2 "trapa #0x22" +#define SYSCALL_ARG3 "trapa #0x23" +#define SYSCALL_ARG4 "trapa #0x24" +#define SYSCALL_ARG5 "trapa #0x25" +#define SYSCALL_ARG6 "trapa #0x26" +#else +#define SYSCALL_ARG0 "trapa #0x10" +#define SYSCALL_ARG1 "trapa #0x11" +#define SYSCALL_ARG2 "trapa #0x12" +#define SYSCALL_ARG3 "trapa #0x13" +#define SYSCALL_ARG4 "trapa #0x14" +#define SYSCALL_ARG5 "trapa #0x15" +#define SYSCALL_ARG6 "trapa #0x16" +#endif + /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ #define _syscall0(type,name) \ type name(void) \ { \ register long __sc0 __asm__ ("r3") = __NR_##name; \ -__asm__ __volatile__ ("trapa #0x10" \ +__asm__ __volatile__ (SYSCALL_ARG0 \ : "=z" (__sc0) \ : "0" (__sc0) \ : "memory" ); \ @@ -366,7 +384,7 @@ type name(type1 arg1) \ { \ register long __sc0 __asm__ ("r3") = __NR_##name; \ register long __sc4 __asm__ ("r4") = (long) arg1; \ -__asm__ __volatile__ ("trapa #0x11" \ +__asm__ __volatile__ (SYSCALL_ARG1 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4) \ : "memory"); \ @@ -379,7 +397,7 @@ type name(type1 arg1,type2 arg2) \ register long __sc0 __asm__ ("r3") = __NR_##name; \ register long __sc4 __asm__ ("r4") = (long) arg1; \ register long __sc5 __asm__ ("r5") = (long) arg2; \ -__asm__ __volatile__ ("trapa #0x12" \ +__asm__ __volatile__ (SYSCALL_ARG2 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5) \ : "memory"); \ @@ -393,7 +411,7 @@ register long __sc0 __asm__ ("r3") = __NR_##name; \ register long __sc4 __asm__ ("r4") = (long) arg1; \ register long __sc5 __asm__ ("r5") = (long) arg2; \ register long __sc6 __asm__ ("r6") = (long) arg3; \ -__asm__ __volatile__ ("trapa #0x13" \ +__asm__ __volatile__ (SYSCALL_ARG3 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) \ : "memory"); \ @@ -408,7 +426,7 @@ register long __sc4 __asm__ ("r4") = (long) arg1; \ register long __sc5 __asm__ ("r5") = (long) arg2; \ register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ -__asm__ __volatile__ ("trapa #0x14" \ +__asm__ __volatile__ (SYSCALL_ARG4 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), \ "r" (__sc7) \ @@ -425,7 +443,7 @@ register long __sc5 __asm__ ("r5") = (long) arg2; \ register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ register long __sc0 __asm__ ("r0") = (long) arg5; \ -__asm__ __volatile__ ("trapa #0x15" \ +__asm__ __volatile__ (SYSCALL_ARG5 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ "r" (__sc3) \ @@ -443,7 +461,7 @@ register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ register long __sc0 __asm__ ("r0") = (long) arg5; \ register long __sc1 __asm__ ("r1") = (long) arg6; \ -__asm__ __volatile__ ("trapa #0x16" \ +__asm__ __volatile__ (SYSCALL_ARG6 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ "r" (__sc3), "r" (__sc1) \ diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h index 007e88d6d43..93849f7abc2 100644 --- a/include/asm-x86_64/atomic.h +++ b/include/asm-x86_64/atomic.h @@ -21,7 +21,7 @@ * on us. We need to use _exactly_ the address the user gave us, * not some alias that contains the same information. */ -typedef struct { volatile int counter; } atomic_t; +typedef struct { int counter; } atomic_t; #define ATOMIC_INIT(i) { (i) } diff --git a/include/asm-x86_64/spinlock_types.h b/include/asm-x86_64/spinlock_types.h index 59efe849f35..4da9345c150 100644 --- a/include/asm-x86_64/spinlock_types.h +++ b/include/asm-x86_64/spinlock_types.h @@ -6,13 +6,13 @@ #endif typedef struct { - volatile unsigned int slock; + unsigned int slock; } raw_spinlock_t; #define __RAW_SPIN_LOCK_UNLOCKED { 1 } typedef struct { - volatile unsigned int lock; + unsigned int lock; } raw_rwlock_t; #define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } diff --git a/include/linux/aio.h b/include/linux/aio.h index 0d71c0041f1..9e350fd44d7 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -194,7 +194,7 @@ struct kioctx { struct aio_ring_info ring_info; - struct work_struct wq; + struct delayed_work wq; }; /* prototypes */ diff --git a/include/linux/connector.h b/include/linux/connector.h index 4c02119c6ab..3ea1cd58de9 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -133,7 +133,7 @@ struct cn_callback_data { struct cn_callback_entry { struct list_head callback_entry; struct cn_callback *cb; - struct work_struct work; + struct delayed_work work; struct cn_queue_dev *pdev; struct cn_callback_id id; @@ -170,7 +170,7 @@ void cn_queue_free_dev(struct cn_queue_dev *dev); int cn_cb_equal(struct cb_id *, struct cb_id *); -void cn_queue_wrapper(void *data); +void cn_queue_wrapper(struct work_struct *work); extern int cn_already_initialized; diff --git a/include/linux/i2o.h b/include/linux/i2o.h index c115e9e840b..1fb02e17f6f 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -461,7 +461,7 @@ struct i2o_driver { int (*reply) (struct i2o_controller *, u32, struct i2o_message *); /* Event handler */ - void (*event) (struct i2o_event *); + work_func_t event; struct workqueue_struct *event_queue; /* Event queue */ diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index efe0ee4cc80..06c58c423fe 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h @@ -158,7 +158,7 @@ static inline void con_schedule_flip(struct tty_struct *t) if (t->buf.tail != NULL) t->buf.tail->commit = t->buf.tail->used; spin_unlock_irqrestore(&t->buf.lock, flags); - schedule_work(&t->buf.work); + schedule_delayed_work(&t->buf.work, 0); } #endif diff --git a/include/linux/libata.h b/include/linux/libata.h index 202283b5df9..ab275483032 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -575,8 +575,9 @@ struct ata_port { struct ata_host *host; struct device *dev; - struct work_struct port_task; - struct work_struct hotplug_task; + void *port_task_data; + struct delayed_work port_task; + struct delayed_work hotplug_task; struct work_struct scsi_rescan_task; unsigned int hsm_task_state; @@ -755,7 +756,7 @@ extern void ata_host_resume(struct ata_host *host); extern int ata_ratelimit(void); extern int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); -extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), +extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay); extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, unsigned long interval_msec, diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 528e7d3fecb..c15ae1986b9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -110,7 +110,7 @@ struct mmc_host { struct mmc_card *card_busy; /* the MMC card claiming host */ struct mmc_card *card_selected; /* the selected MMC card */ - struct work_struct detect; + struct delayed_work detect; unsigned long private[0] ____cacheline_aligned; }; diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h index b089d950628..a503052138b 100644 --- a/include/linux/ncp_fs_sb.h +++ b/include/linux/ncp_fs_sb.h @@ -127,10 +127,10 @@ struct ncp_server { } unexpected_packet; }; -extern void ncp_tcp_rcv_proc(void *server); -extern void ncp_tcp_tx_proc(void *server); -extern void ncpdgram_rcv_proc(void *server); -extern void ncpdgram_timeout_proc(void *server); +extern void ncp_tcp_rcv_proc(struct work_struct *work); +extern void ncp_tcp_tx_proc(struct work_struct *work); +extern void ncpdgram_rcv_proc(struct work_struct *work); +extern void ncpdgram_timeout_proc(struct work_struct *work); extern void ncpdgram_timeout_call(unsigned long server); extern void ncp_tcp_data_ready(struct sock* sk, int len); extern void ncp_tcp_write_space(struct sock* sk); diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 2cc9867b162..29930b71a9a 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -32,7 +32,7 @@ struct netpoll_info { struct netpoll *rx_np; /* netpoll that registered an rx_hook */ struct sk_buff_head arp_tx; /* list of arp requests to reply to */ struct sk_buff_head txq; - struct work_struct tx_work; + struct delayed_work tx_work; }; void netpoll_poll(struct netpoll *np); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 7ccfc7ef0a8..95796e6924f 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -51,7 +51,7 @@ struct nfs_client { unsigned long cl_lease_time; unsigned long cl_last_renewal; - struct work_struct cl_renewd; + struct delayed_work cl_renewd; struct rpc_wait_queue cl_rpcwaitq; diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 62a7169aed8..3a28742d86f 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -249,7 +249,8 @@ struct reiserfs_journal { int j_errno; /* when flushing ordered buffers, throttle new ordered writers */ - struct work_struct j_work; + struct delayed_work j_work; + struct super_block *j_work_sb; atomic_t j_async_throttle; }; diff --git a/include/linux/relay.h b/include/linux/relay.h index 24accb48384..0e3d91b7699 100644 --- a/include/linux/relay.h +++ b/include/linux/relay.h @@ -38,7 +38,7 @@ struct rchan_buf size_t subbufs_consumed; /* count of sub-buffers consumed */ struct rchan *chan; /* associated channel */ wait_queue_head_t read_wait; /* reader wait queue */ - struct work_struct wake_readers; /* reader wake-up work struct */ + struct delayed_work wake_readers; /* reader wake-up work struct */ struct dentry *dentry; /* channel file dentry */ struct kref kref; /* channel buffer refcount */ struct page **page_array; /* array of current buffer pages */ diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index a2eb9b4a9de..4a68125b6de 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h @@ -30,7 +30,7 @@ struct rpc_inode { #define RPC_PIPE_WAIT_FOR_OPEN 1 int flags; struct rpc_pipe_ops *ops; - struct work_struct queue_timeout; + struct delayed_work queue_timeout; }; static inline struct rpc_inode * diff --git a/include/linux/tty.h b/include/linux/tty.h index 65321f911c1..f717f089823 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -53,7 +53,7 @@ struct tty_buffer { }; struct tty_bufhead { - struct work_struct work; + struct delayed_work work; struct semaphore pty_sem; spinlock_t lock; struct tty_buffer *head; /* Queue head */ diff --git a/include/linux/usb.h b/include/linux/usb.h index 0cd73edeef1..aab5b1b7202 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -388,7 +388,7 @@ struct usb_device { int pm_usage_cnt; /* usage counter for autosuspend */ #ifdef CONFIG_PM - struct work_struct autosuspend; /* for delayed autosuspends */ + struct delayed_work autosuspend; /* for delayed autosuspends */ struct mutex pm_mutex; /* protects PM operations */ unsigned auto_pm:1; /* autosuspend/resume in progress */ diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 9bca3539a1e..4a3ea83c6d1 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -11,12 +11,23 @@ struct workqueue_struct; +struct work_struct; +typedef void (*work_func_t)(struct work_struct *work); + struct work_struct { - unsigned long pending; + /* the first word is the work queue pointer and the flags rolled into + * one */ + unsigned long management; +#define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ +#define WORK_STRUCT_NOAUTOREL 1 /* F if work item automatically released on exec */ +#define WORK_STRUCT_FLAG_MASK (3UL) +#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) struct list_head entry; - void (*func)(void *); - void *data; - void *wq_data; + work_func_t func; +}; + +struct delayed_work { + struct work_struct work; struct timer_list timer; }; @@ -24,36 +35,117 @@ struct execute_work { struct work_struct work; }; -#define __WORK_INITIALIZER(n, f, d) { \ +#define __WORK_INITIALIZER(n, f) { \ + .management = 0, \ + .entry = { &(n).entry, &(n).entry }, \ + .func = (f), \ + } + +#define __WORK_INITIALIZER_NAR(n, f) { \ + .management = (1 << WORK_STRUCT_NOAUTOREL), \ .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ - .data = (d), \ + } + +#define __DELAYED_WORK_INITIALIZER(n, f) { \ + .work = __WORK_INITIALIZER((n).work, (f)), \ + .timer = TIMER_INITIALIZER(NULL, 0, 0), \ + } + +#define __DELAYED_WORK_INITIALIZER_NAR(n, f) { \ + .work = __WORK_INITIALIZER_NAR((n).work, (f)), \ .timer = TIMER_INITIALIZER(NULL, 0, 0), \ } -#define DECLARE_WORK(n, f, d) \ - struct work_struct n = __WORK_INITIALIZER(n, f, d) +#define DECLARE_WORK(n, f) \ + struct work_struct n = __WORK_INITIALIZER(n, f) + +#define DECLARE_WORK_NAR(n, f) \ + struct work_struct n = __WORK_INITIALIZER_NAR(n, f) + +#define DECLARE_DELAYED_WORK(n, f) \ + struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f) + +#define DECLARE_DELAYED_WORK_NAR(n, f) \ + struct dwork_struct n = __DELAYED_WORK_INITIALIZER_NAR(n, f) /* - * initialize a work-struct's func and data pointers: + * initialize a work item's function pointer */ -#define PREPARE_WORK(_work, _func, _data) \ +#define PREPARE_WORK(_work, _func) \ do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ + (_work)->func = (_func); \ } while (0) +#define PREPARE_DELAYED_WORK(_work, _func) \ + PREPARE_WORK(&(_work)->work, (_func)) + /* - * initialize all of a work-struct: + * initialize all of a work item in one go */ -#define INIT_WORK(_work, _func, _data) \ +#define INIT_WORK(_work, _func) \ do { \ + (_work)->management = 0; \ INIT_LIST_HEAD(&(_work)->entry); \ - (_work)->pending = 0; \ - PREPARE_WORK((_work), (_func), (_data)); \ + PREPARE_WORK((_work), (_func)); \ + } while (0) + +#define INIT_WORK_NAR(_work, _func) \ + do { \ + (_work)->management = (1 << WORK_STRUCT_NOAUTOREL); \ + INIT_LIST_HEAD(&(_work)->entry); \ + PREPARE_WORK((_work), (_func)); \ + } while (0) + +#define INIT_DELAYED_WORK(_work, _func) \ + do { \ + INIT_WORK(&(_work)->work, (_func)); \ + init_timer(&(_work)->timer); \ + } while (0) + +#define INIT_DELAYED_WORK_NAR(_work, _func) \ + do { \ + INIT_WORK_NAR(&(_work)->work, (_func)); \ init_timer(&(_work)->timer); \ } while (0) +/** + * work_pending - Find out whether a work item is currently pending + * @work: The work item in question + */ +#define work_pending(work) \ + test_bit(WORK_STRUCT_PENDING, &(work)->management) + +/** + * delayed_work_pending - Find out whether a delayable work item is currently + * pending + * @work: The work item in question + */ +#define delayed_work_pending(work) \ + test_bit(WORK_STRUCT_PENDING, &(work)->work.management) + +/** + * work_release - Release a work item under execution + * @work: The work item to release + * + * This is used to release a work item that has been initialised with automatic + * release mode disabled (WORK_STRUCT_NOAUTOREL is set). This gives the work + * function the opportunity to grab auxiliary data from the container of the + * work_struct before clearing the pending bit as the work_struct may be + * subject to deallocation the moment the pending bit is cleared. + * + * In such a case, this should be called in the work function after it has + * fetched any data it may require from the containter of the work_struct. + * After this function has been called, the work_struct may be scheduled for + * further execution or it may be deallocated unless other precautions are + * taken. + * + * This should also be used to release a delayed work item. + */ +#define work_release(work) \ + clear_bit(WORK_STRUCT_PENDING, &(work)->management) + + extern struct workqueue_struct *__create_workqueue(const char *name, int singlethread); #define create_workqueue(name) __create_workqueue((name), 0) @@ -62,39 +154,38 @@ extern struct workqueue_struct *__create_workqueue(const char *name, extern void destroy_workqueue(struct workqueue_struct *wq); extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work)); -extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay)); +extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay)); extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, - struct work_struct *work, unsigned long delay); + struct delayed_work *work, unsigned long delay); extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq)); extern int FASTCALL(schedule_work(struct work_struct *work)); -extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay)); +extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay)); -extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay); -extern int schedule_on_each_cpu(void (*func)(void *info), void *info); +extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay); +extern int schedule_on_each_cpu(work_func_t func); extern void flush_scheduled_work(void); extern int current_is_keventd(void); extern int keventd_up(void); extern void init_workqueues(void); -void cancel_rearming_delayed_work(struct work_struct *work); +void cancel_rearming_delayed_work(struct delayed_work *work); void cancel_rearming_delayed_workqueue(struct workqueue_struct *, - struct work_struct *); -int execute_in_process_context(void (*fn)(void *), void *, - struct execute_work *); + struct delayed_work *); +int execute_in_process_context(work_func_t fn, struct execute_work *); /* * Kill off a pending schedule_delayed_work(). Note that the work callback * function may still be running on return from cancel_delayed_work(). Run * flush_scheduled_work() to wait on it. */ -static inline int cancel_delayed_work(struct work_struct *work) +static inline int cancel_delayed_work(struct delayed_work *work) { int ret; ret = del_timer_sync(&work->timer); if (ret) - clear_bit(0, &work->pending); + clear_bit(WORK_STRUCT_PENDING, &work->work.management); return ret; } diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 617b672b113..89119277553 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h @@ -108,8 +108,8 @@ struct ieee80211softmac_assoc_info { /* Scan retries remaining */ int scan_retry; - struct work_struct work; - struct work_struct timeout; + struct delayed_work work; + struct delayed_work timeout; }; struct ieee80211softmac_bss_info { diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 5f48748fe01..f7be1ac7360 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -84,7 +84,7 @@ struct inet_timewait_death_row { }; extern void inet_twdr_hangman(unsigned long data); -extern void inet_twdr_twkill_work(void *data); +extern void inet_twdr_twkill_work(struct work_struct *work); extern void inet_twdr_twcal_tick(unsigned long data); #if (BITS_PER_LONG == 64) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index f8cbe40f52c..c089f93ba59 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1030,7 +1030,7 @@ void sctp_inq_init(struct sctp_inq *); void sctp_inq_free(struct sctp_inq *); void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet); struct sctp_chunk *sctp_inq_pop(struct sctp_inq *); -void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *); +void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t); /* This is the structure we use to hold outbound chunks. You push * chunks in and they automatically pop out the other end as bundled diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 44b2f82a6ee..9233ed5de66 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -201,9 +201,14 @@ struct domain_device { void *lldd_dev; }; +struct sas_discovery_event { + struct work_struct work; + struct asd_sas_port *port; +}; + struct sas_discovery { spinlock_t disc_event_lock; - struct work_struct disc_work[DISC_NUM_EVENTS]; + struct sas_discovery_event disc_work[DISC_NUM_EVENTS]; unsigned long pending; u8 fanout_sas_addr[8]; u8 eeds_a[8]; @@ -249,14 +254,19 @@ struct asd_sas_port { void *lldd_port; /* not touched by the sas class code */ }; +struct asd_sas_event { + struct work_struct work; + struct asd_sas_phy *phy; +}; + /* The phy pretty much is controlled by the LLDD. * The class only reads those fields. */ struct asd_sas_phy { /* private: */ /* protected by ha->event_lock */ - struct work_struct port_events[PORT_NUM_EVENTS]; - struct work_struct phy_events[PHY_NUM_EVENTS]; + struct asd_sas_event port_events[PORT_NUM_EVENTS]; + struct asd_sas_event phy_events[PHY_NUM_EVENTS]; unsigned long port_events_pending; unsigned long phy_events_pending; @@ -308,10 +318,15 @@ struct scsi_core { int queue_thread_kill; }; +struct sas_ha_event { + struct work_struct work; + struct sas_ha_struct *ha; +}; + struct sas_ha_struct { /* private: */ spinlock_t event_lock; - struct work_struct ha_events[HA_NUM_EVENTS]; + struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; struct scsi_core core; @@ -631,6 +646,6 @@ void sas_unregister_dev(struct domain_device *); void sas_init_dev(struct domain_device *); -void sas_task_abort(struct sas_task *task); +void sas_task_abort(struct work_struct *); #endif /* _SASLIB_H_ */ diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index fd352323378..798f7c7ee42 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -206,9 +206,9 @@ struct fc_rport { /* aka fc_starget_attrs */ u8 flags; struct list_head peers; struct device dev; - struct work_struct dev_loss_work; + struct delayed_work dev_loss_work; struct work_struct scan_work; - struct work_struct fail_io_work; + struct delayed_work fail_io_work; struct work_struct stgt_delete_work; struct work_struct rport_delete_work; } __attribute__((aligned(sizeof(unsigned long)))); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 4b95c89c95c..d5c218ddc52 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -176,7 +176,7 @@ struct iscsi_cls_session { /* recovery fields */ int recovery_tmo; - struct work_struct recovery_work; + struct delayed_work recovery_work; int target_id; diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 4c43521cc49..33720397a90 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -511,7 +511,7 @@ struct snd_ac97 { #ifdef CONFIG_SND_AC97_POWER_SAVE unsigned int power_up; /* power states */ struct workqueue_struct *power_workq; - struct work_struct power_work; + struct delayed_work power_work; #endif struct device dev; }; diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h index 11702aa0bea..2ee061625fd 100644 --- a/include/sound/ak4114.h +++ b/include/sound/ak4114.h @@ -182,7 +182,7 @@ struct ak4114 { unsigned char rcs0; unsigned char rcs1; struct workqueue_struct *workqueue; - struct work_struct work; + struct delayed_work work; void *change_callback_private; void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1); }; diff --git a/ipc/util.c b/ipc/util.c index cd8bb14a431..a9b7a227b8d 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -514,6 +514,11 @@ void ipc_rcu_getref(void *ptr) container_of(ptr, struct ipc_rcu_hdr, data)->refcount++; } +static void ipc_do_vfree(struct work_struct *work) +{ + vfree(container_of(work, struct ipc_rcu_sched, work)); +} + /** * ipc_schedule_free - free ipc + rcu space * @head: RCU callback structure for queued work @@ -528,7 +533,7 @@ static void ipc_schedule_free(struct rcu_head *head) struct ipc_rcu_sched *sched = container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]); - INIT_WORK(&sched->work, vfree, sched); + INIT_WORK(&sched->work, ipc_do_vfree); schedule_work(&sched->work); } diff --git a/kernel/kmod.c b/kernel/kmod.c index 2b76dee2849..8d2bea09a4e 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -114,6 +114,7 @@ EXPORT_SYMBOL(request_module); #endif /* CONFIG_KMOD */ struct subprocess_info { + struct work_struct work; struct completion *complete; char *path; char **argv; @@ -221,9 +222,10 @@ static int wait_for_helper(void *data) } /* This is run by khelper thread */ -static void __call_usermodehelper(void *data) +static void __call_usermodehelper(struct work_struct *work) { - struct subprocess_info *sub_info = data; + struct subprocess_info *sub_info = + container_of(work, struct subprocess_info, work); pid_t pid; int wait = sub_info->wait; @@ -264,6 +266,8 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp, { DECLARE_COMPLETION_ONSTACK(done); struct subprocess_info sub_info = { + .work = __WORK_INITIALIZER(sub_info.work, + __call_usermodehelper), .complete = &done, .path = path, .argv = argv, @@ -272,7 +276,6 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp, .wait = wait, .retval = 0, }; - DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; @@ -280,7 +283,7 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp, if (path[0] == '\0') return 0; - queue_work(khelper_wq, &work); + queue_work(khelper_wq, &sub_info.work); wait_for_completion(&done); return sub_info.retval; } @@ -291,6 +294,8 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, { DECLARE_COMPLETION(done); struct subprocess_info sub_info = { + .work = __WORK_INITIALIZER(sub_info.work, + __call_usermodehelper), .complete = &done, .path = path, .argv = argv, @@ -298,7 +303,6 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, .retval = 0, }; struct file *f; - DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; @@ -318,7 +322,7 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, } sub_info.stdin = f; - queue_work(khelper_wq, &work); + queue_work(khelper_wq, &sub_info.work); wait_for_completion(&done); return sub_info.retval; } diff --git a/kernel/kthread.c b/kernel/kthread.c index 4f9c60ef95e..1db8c72d0d3 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -31,6 +31,8 @@ struct kthread_create_info /* Result passed back to kthread_create() from keventd. */ struct task_struct *result; struct completion done; + + struct work_struct work; }; struct kthread_stop_info @@ -111,9 +113,10 @@ static int kthread(void *_create) } /* We are keventd: create a thread. */ -static void keventd_create_kthread(void *_create) +static void keventd_create_kthread(struct work_struct *work) { - struct kthread_create_info *create = _create; + struct kthread_create_info *create = + container_of(work, struct kthread_create_info, work); int pid; /* We want our own signal handler (we take no signals by default). */ @@ -154,20 +157,20 @@ struct task_struct *kthread_create(int (*threadfn)(void *data), ...) { struct kthread_create_info create; - DECLARE_WORK(work, keventd_create_kthread, &create); create.threadfn = threadfn; create.data = data; init_completion(&create.started); init_completion(&create.done); + INIT_WORK(&create.work, keventd_create_kthread); /* * The workqueue needs to start up first: */ if (!helper_wq) - work.func(work.data); + create.work.func(&create.work); else { - queue_work(helper_wq, &work); + queue_work(helper_wq, &create.work); wait_for_completion(&create.done); } if (!IS_ERR(create.result)) { diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c index f1f900ac316..678ec736076 100644 --- a/kernel/power/poweroff.c +++ b/kernel/power/poweroff.c @@ -16,12 +16,12 @@ * callback we use. */ -static void do_poweroff(void *dummy) +static void do_poweroff(struct work_struct *dummy) { kernel_power_off(); } -static DECLARE_WORK(poweroff_work, do_poweroff, NULL); +static DECLARE_WORK(poweroff_work, do_poweroff); static void handle_poweroff(int key, struct tty_struct *tty) { diff --git a/kernel/relay.c b/kernel/relay.c index f04bbdb56ac..2b92e8ece85 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -308,9 +308,10 @@ static struct rchan_callbacks default_channel_callbacks = { * reason waking is deferred is that calling directly from write * causes problems if you're writing from say the scheduler. */ -static void wakeup_readers(void *private) +static void wakeup_readers(struct work_struct *work) { - struct rchan_buf *buf = private; + struct rchan_buf *buf = + container_of(work, struct rchan_buf, wake_readers.work); wake_up_interruptible(&buf->read_wait); } @@ -328,7 +329,7 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) if (init) { init_waitqueue_head(&buf->read_wait); kref_init(&buf->kref); - INIT_WORK(&buf->wake_readers, NULL, NULL); + INIT_DELAYED_WORK(&buf->wake_readers, NULL); } else { cancel_delayed_work(&buf->wake_readers); flush_scheduled_work(); @@ -549,7 +550,8 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) buf->padding[old_subbuf]; smp_mb(); if (waitqueue_active(&buf->read_wait)) { - PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf); + PREPARE_DELAYED_WORK(&buf->wake_readers, + wakeup_readers); schedule_delayed_work(&buf->wake_readers, 1); } } diff --git a/kernel/sys.c b/kernel/sys.c index 98489d82801..c87b461de38 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -880,7 +880,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user return 0; } -static void deferred_cad(void *dummy) +static void deferred_cad(struct work_struct *dummy) { kernel_restart(NULL); } @@ -892,7 +892,7 @@ static void deferred_cad(void *dummy) */ void ctrl_alt_del(void) { - static DECLARE_WORK(cad_work, deferred_cad, NULL); + static DECLARE_WORK(cad_work, deferred_cad); if (C_A_D) schedule_work(&cad_work); diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 17c2f03d2c2..8d1e7cb8a51 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -80,6 +80,29 @@ static inline int is_single_threaded(struct workqueue_struct *wq) return list_empty(&wq->list); } +static inline void set_wq_data(struct work_struct *work, void *wq) +{ + unsigned long new, old, res; + + /* assume the pending flag is already set and that the task has already + * been queued on this workqueue */ + new = (unsigned long) wq | (1UL << WORK_STRUCT_PENDING); + res = work->management; + if (res != new) { + do { + old = res; + new = (unsigned long) wq; + new |= (old & WORK_STRUCT_FLAG_MASK); + res = cmpxchg(&work->management, old, new); + } while (res != old); + } +} + +static inline void *get_wq_data(struct work_struct *work) +{ + return (void *) (work->management & WORK_STRUCT_WQ_DATA_MASK); +} + /* Preempt must be disabled. */ static void __queue_work(struct cpu_workqueue_struct *cwq, struct work_struct *work) @@ -87,7 +110,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, unsigned long flags; spin_lock_irqsave(&cwq->lock, flags); - work->wq_data = cwq; + set_wq_data(work, cwq); list_add_tail(&work->entry, &cwq->worklist); cwq->insert_sequence++; wake_up(&cwq->more_work); @@ -108,7 +131,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work) { int ret = 0, cpu = get_cpu(); - if (!test_and_set_bit(0, &work->pending)) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { if (unlikely(is_single_threaded(wq))) cpu = singlethread_cpu; BUG_ON(!list_empty(&work->entry)); @@ -122,38 +145,42 @@ EXPORT_SYMBOL_GPL(queue_work); static void delayed_work_timer_fn(unsigned long __data) { - struct work_struct *work = (struct work_struct *)__data; - struct workqueue_struct *wq = work->wq_data; + struct delayed_work *dwork = (struct delayed_work *)__data; + struct workqueue_struct *wq = get_wq_data(&dwork->work); int cpu = smp_processor_id(); if (unlikely(is_single_threaded(wq))) cpu = singlethread_cpu; - __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); + __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), &dwork->work); } /** * queue_delayed_work - queue work on a workqueue after delay * @wq: workqueue to use - * @work: work to queue + * @work: delayable work to queue * @delay: number of jiffies to wait before queueing * * Returns 0 if @work was already on a queue, non-zero otherwise. */ int fastcall queue_delayed_work(struct workqueue_struct *wq, - struct work_struct *work, unsigned long delay) + struct delayed_work *dwork, unsigned long delay) { int ret = 0; - struct timer_list *timer = &work->timer; + struct timer_list *timer = &dwork->timer; + struct work_struct *work = &dwork->work; + + if (delay == 0) + return queue_work(wq, work); - if (!test_and_set_bit(0, &work->pending)) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { BUG_ON(timer_pending(timer)); BUG_ON(!list_empty(&work->entry)); /* This stores wq for the moment, for the timer_fn */ - work->wq_data = wq; + set_wq_data(work, wq); timer->expires = jiffies + delay; - timer->data = (unsigned long)work; + timer->data = (unsigned long)dwork; timer->function = delayed_work_timer_fn; add_timer(timer); ret = 1; @@ -172,19 +199,20 @@ EXPORT_SYMBOL_GPL(queue_delayed_work); * Returns 0 if @work was already on a queue, non-zero otherwise. */ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, - struct work_struct *work, unsigned long delay) + struct delayed_work *dwork, unsigned long delay) { int ret = 0; - struct timer_list *timer = &work->timer; + struct timer_list *timer = &dwork->timer; + struct work_struct *work = &dwork->work; - if (!test_and_set_bit(0, &work->pending)) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { BUG_ON(timer_pending(timer)); BUG_ON(!list_empty(&work->entry)); /* This stores wq for the moment, for the timer_fn */ - work->wq_data = wq; + set_wq_data(work, wq); timer->expires = jiffies + delay; - timer->data = (unsigned long)work; + timer->data = (unsigned long)dwork; timer->function = delayed_work_timer_fn; add_timer_on(timer, cpu); ret = 1; @@ -212,15 +240,15 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) while (!list_empty(&cwq->worklist)) { struct work_struct *work = list_entry(cwq->worklist.next, struct work_struct, entry); - void (*f) (void *) = work->func; - void *data = work->data; + work_func_t f = work->func; list_del_init(cwq->worklist.next); spin_unlock_irqrestore(&cwq->lock, flags); - BUG_ON(work->wq_data != cwq); - clear_bit(0, &work->pending); - f(data); + BUG_ON(get_wq_data(work) != cwq); + if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management)) + work_release(work); + f(work); spin_lock_irqsave(&cwq->lock, flags); cwq->remove_sequence++; @@ -468,38 +496,37 @@ EXPORT_SYMBOL(schedule_work); /** * schedule_delayed_work - put work task in global workqueue after delay - * @work: job to be done - * @delay: number of jiffies to wait + * @dwork: job to be done + * @delay: number of jiffies to wait or 0 for immediate execution * * After waiting for a given time this puts a job in the kernel-global * workqueue. */ -int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay) +int fastcall schedule_delayed_work(struct delayed_work *dwork, unsigned long delay) { - return queue_delayed_work(keventd_wq, work, delay); + return queue_delayed_work(keventd_wq, dwork, delay); } EXPORT_SYMBOL(schedule_delayed_work); /** * schedule_delayed_work_on - queue work in global workqueue on CPU after delay * @cpu: cpu to use - * @work: job to be done + * @dwork: job to be done * @delay: number of jiffies to wait * * After waiting for a given time this puts a job in the kernel-global * workqueue on the specified CPU. */ int schedule_delayed_work_on(int cpu, - struct work_struct *work, unsigned long delay) + struct delayed_work *dwork, unsigned long delay) { - return queue_delayed_work_on(cpu, keventd_wq, work, delay); + return queue_delayed_work_on(cpu, keventd_wq, dwork, delay); } EXPORT_SYMBOL(schedule_delayed_work_on); /** * schedule_on_each_cpu - call a function on each online CPU from keventd * @func: the function to call - * @info: a pointer to pass to func() * * Returns zero on success. * Returns -ve errno on failure. @@ -508,7 +535,7 @@ EXPORT_SYMBOL(schedule_delayed_work_on); * * schedule_on_each_cpu() is very slow. */ -int schedule_on_each_cpu(void (*func)(void *info), void *info) +int schedule_on_each_cpu(work_func_t func) { int cpu; struct work_struct *works; @@ -519,7 +546,7 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info) mutex_lock(&workqueue_mutex); for_each_online_cpu(cpu) { - INIT_WORK(per_cpu_ptr(works, cpu), func, info); + INIT_WORK(per_cpu_ptr(works, cpu), func); __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), per_cpu_ptr(works, cpu)); } @@ -539,12 +566,12 @@ EXPORT_SYMBOL(flush_scheduled_work); * cancel_rearming_delayed_workqueue - reliably kill off a delayed * work whose handler rearms the delayed work. * @wq: the controlling workqueue structure - * @work: the delayed work struct + * @dwork: the delayed work struct */ void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq, - struct work_struct *work) + struct delayed_work *dwork) { - while (!cancel_delayed_work(work)) + while (!cancel_delayed_work(dwork)) flush_workqueue(wq); } EXPORT_SYMBOL(cancel_rearming_delayed_workqueue); @@ -552,18 +579,17 @@ EXPORT_SYMBOL(cancel_rearming_delayed_workqueue); /** * cancel_rearming_delayed_work - reliably kill off a delayed keventd * work whose handler rearms the delayed work. - * @work: the delayed work struct + * @dwork: the delayed work struct */ -void cancel_rearming_delayed_work(struct work_struct *work) +void cancel_rearming_delayed_work(struct delayed_work *dwork) { - cancel_rearming_delayed_workqueue(keventd_wq, work); + cancel_rearming_delayed_workqueue(keventd_wq, dwork); } EXPORT_SYMBOL(cancel_rearming_delayed_work); /** * execute_in_process_context - reliably execute the routine with user context * @fn: the function to execute - * @data: data to pass to the function * @ew: guaranteed storage for the execute work structure (must * be available when the work executes) * @@ -573,15 +599,14 @@ EXPORT_SYMBOL(cancel_rearming_delayed_work); * Returns: 0 - function was executed * 1 - function was scheduled for execution */ -int execute_in_process_context(void (*fn)(void *data), void *data, - struct execute_work *ew) +int execute_in_process_context(work_func_t fn, struct execute_work *ew) { if (!in_interrupt()) { - fn(data); + fn(&ew->work); return 0; } - INIT_WORK(&ew->work, fn, data); + INIT_WORK(&ew->work, fn); schedule_work(&ew->work); return 1; diff --git a/mm/nommu.c b/mm/nommu.c index 8bdde9508f3..6a2a8aada40 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -497,15 +497,17 @@ static int validate_mmap_request(struct file *file, (flags & MAP_TYPE) != MAP_SHARED) return -EINVAL; - if (PAGE_ALIGN(len) == 0) - return addr; - - if (len > TASK_SIZE) + if (!len) return -EINVAL; + /* Careful about overflows.. */ + len = PAGE_ALIGN(len); + if (!len || len > TASK_SIZE) + return -ENOMEM; + /* offset overflow? */ if ((pgoff + (len >> PAGE_SHIFT)) < pgoff) - return -EINVAL; + return -EOVERFLOW; if (file) { /* validate file mapping requests */ diff --git a/mm/slab.c b/mm/slab.c index 3c4a7e34edd..5de81473df3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -313,7 +313,7 @@ static int drain_freelist(struct kmem_cache *cache, static void free_block(struct kmem_cache *cachep, void **objpp, int len, int node); static int enable_cpucache(struct kmem_cache *cachep); -static void cache_reap(void *unused); +static void cache_reap(struct work_struct *unused); /* * This function must be completely optimized away if a constant is passed to @@ -753,7 +753,7 @@ int slab_is_available(void) return g_cpucache_up == FULL; } -static DEFINE_PER_CPU(struct work_struct, reap_work); +static DEFINE_PER_CPU(struct delayed_work, reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) { @@ -916,16 +916,16 @@ static void next_reap_node(void) */ static void __devinit start_cpu_timer(int cpu) { - struct work_struct *reap_work = &per_cpu(reap_work, cpu); + struct delayed_work *reap_work = &per_cpu(reap_work, cpu); /* * When this gets called from do_initcalls via cpucache_init(), * init_workqueues() has already run, so keventd will be setup * at that time. */ - if (keventd_up() && reap_work->func == NULL) { + if (keventd_up() && reap_work->work.func == NULL) { init_reap_node(cpu); - INIT_WORK(reap_work, cache_reap, NULL); + INIT_DELAYED_WORK(reap_work, cache_reap); schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu); } } @@ -3815,7 +3815,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3, * If we cannot acquire the cache chain mutex then just give up - we'll try * again on the next iteration. */ -static void cache_reap(void *unused) +static void cache_reap(struct work_struct *unused) { struct kmem_cache *searchp; struct kmem_list3 *l3; diff --git a/mm/swap.c b/mm/swap.c index 2e0e871f542..d9a3770d8f3 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -216,7 +216,7 @@ void lru_add_drain(void) } #ifdef CONFIG_NUMA -static void lru_add_drain_per_cpu(void *dummy) +static void lru_add_drain_per_cpu(struct work_struct *dummy) { lru_add_drain(); } @@ -226,7 +226,7 @@ static void lru_add_drain_per_cpu(void *dummy) */ int lru_add_drain_all(void) { - return schedule_on_each_cpu(lru_add_drain_per_cpu, NULL); + return schedule_on_each_cpu(lru_add_drain_per_cpu); } #else diff --git a/net/atm/lec.c b/net/atm/lec.c index 5946ec63724..3fc0abeeaf3 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -1454,7 +1454,7 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr, #define LEC_ARP_REFRESH_INTERVAL (3*HZ) -static void lec_arp_check_expire(void *data); +static void lec_arp_check_expire(struct work_struct *work); static void lec_arp_expire_arp(unsigned long data); /* @@ -1477,7 +1477,7 @@ static void lec_arp_init(struct lec_priv *priv) INIT_HLIST_HEAD(&priv->lec_no_forward); INIT_HLIST_HEAD(&priv->mcast_fwds); spin_lock_init(&priv->lec_arp_lock); - INIT_WORK(&priv->lec_arp_work, lec_arp_check_expire, priv); + INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire); schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL); } @@ -1875,10 +1875,11 @@ static void lec_arp_expire_vcc(unsigned long data) * to ESI_FORWARD_DIRECT. This causes the flush period to end * regardless of the progress of the flush protocol. */ -static void lec_arp_check_expire(void *data) +static void lec_arp_check_expire(struct work_struct *work) { unsigned long flags; - struct lec_priv *priv = data; + struct lec_priv *priv = + container_of(work, struct lec_priv, lec_arp_work.work); struct hlist_node *node, *next; struct lec_arp_table *entry; unsigned long now; diff --git a/net/atm/lec.h b/net/atm/lec.h index 24cc95f8674..99136babd53 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -92,7 +92,7 @@ struct lec_priv { spinlock_t lec_arp_lock; struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ struct atm_vcc *lecd; - struct work_struct lec_arp_work; /* C10 */ + struct delayed_work lec_arp_work; /* C10 */ unsigned int maximum_unknown_frame_count; /* * Within the period of time defined by this variable, the client will send diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 3eeeb7a86e7..d4c935692cc 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -237,9 +237,9 @@ static void bt_release(struct device *dev) kfree(data); } -static void add_conn(void *data) +static void add_conn(struct work_struct *work) { - struct hci_conn *conn = data; + struct hci_conn *conn = container_of(work, struct hci_conn, work); int i; if (device_register(&conn->dev) < 0) { @@ -272,14 +272,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) dev_set_drvdata(&conn->dev, conn); - INIT_WORK(&conn->work, add_conn, (void *) conn); + INIT_WORK(&conn->work, add_conn); schedule_work(&conn->work); } -static void del_conn(void *data) +static void del_conn(struct work_struct *work) { - struct hci_conn *conn = data; + struct hci_conn *conn = container_of(work, struct hci_conn, work); device_del(&conn->dev); } @@ -287,7 +287,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - INIT_WORK(&conn->work, del_conn, (void *) conn); + INIT_WORK(&conn->work, del_conn); schedule_work(&conn->work); } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f753c40c11d..55bb2634c08 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -77,12 +77,16 @@ static int port_cost(struct net_device *dev) * Called from work queue to allow for calling functions that * might sleep (such as speed check), and to debounce. */ -static void port_carrier_check(void *arg) +static void port_carrier_check(struct work_struct *work) { - struct net_device *dev = arg; struct net_bridge_port *p; + struct net_device *dev; struct net_bridge *br; + dev = container_of(work, struct net_bridge_port, + carrier_check.work)->dev; + work_release(work); + rtnl_lock(); p = dev->br_port; if (!p) @@ -276,7 +280,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->port_no = index; br_init_port(p); p->state = BR_STATE_DISABLED; - INIT_WORK(&p->carrier_check, port_carrier_check, dev); + INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check); br_stp_port_timer_init(p); kobject_init(&p->kobj); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 74258d86f25..3a534e94c7f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -82,7 +82,7 @@ struct net_bridge_port struct timer_list hold_timer; struct timer_list message_age_timer; struct kobject kobj; - struct work_struct carrier_check; + struct delayed_work carrier_check; struct rcu_head rcu; }; diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 4b36114744c..549a2ce951b 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -34,8 +34,8 @@ enum lw_bits { static unsigned long linkwatch_flags; static unsigned long linkwatch_nextevent; -static void linkwatch_event(void *dummy); -static DECLARE_WORK(linkwatch_work, linkwatch_event, NULL); +static void linkwatch_event(struct work_struct *dummy); +static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); static LIST_HEAD(lweventlist); static DEFINE_SPINLOCK(lweventlist_lock); @@ -127,7 +127,7 @@ void linkwatch_run_queue(void) } -static void linkwatch_event(void *dummy) +static void linkwatch_event(struct work_struct *dummy) { /* Limit the number of linkwatch events to one * per second so that a runaway driver does not @@ -171,10 +171,9 @@ void linkwatch_fire_event(struct net_device *dev) unsigned long delay = linkwatch_nextevent - jiffies; /* If we wrap around we'll delay it by at most HZ. */ - if (!delay || delay > HZ) - schedule_work(&linkwatch_work); - else - schedule_delayed_work(&linkwatch_work, delay); + if (delay > HZ) + delay = 0; + schedule_delayed_work(&linkwatch_work, delay); } } } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 3c58846fcaa..b3c559b9ac3 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -50,9 +50,10 @@ static atomic_t trapped; static void zap_completion_queue(void); static void arp_reply(struct sk_buff *skb); -static void queue_process(void *p) +static void queue_process(struct work_struct *work) { - struct netpoll_info *npinfo = p; + struct netpoll_info *npinfo = + container_of(work, struct netpoll_info, tx_work.work); struct sk_buff *skb; while ((skb = skb_dequeue(&npinfo->txq))) { @@ -72,8 +73,6 @@ static void queue_process(void *p) schedule_delayed_work(&npinfo->tx_work, HZ/10); return; } - - netif_tx_unlock_bh(dev); } } @@ -263,7 +262,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) if (status != NETDEV_TX_OK) { skb_queue_tail(&npinfo->txq, skb); - schedule_work(&npinfo->tx_work); + schedule_delayed_work(&npinfo->tx_work,0); } } @@ -628,7 +627,7 @@ int netpoll_setup(struct netpoll *np) spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); skb_queue_head_init(&npinfo->txq); - INIT_WORK(&npinfo->tx_work, queue_process, npinfo); + INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); atomic_set(&npinfo->refcnt, 1); } else { diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 7b52f2a03ee..4c9e26775f7 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -32,8 +32,7 @@ struct inet_timewait_death_row dccp_death_row = { .tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0, (unsigned long)&dccp_death_row), .twkill_work = __WORK_INITIALIZER(dccp_death_row.twkill_work, - inet_twdr_twkill_work, - &dccp_death_row), + inet_twdr_twkill_work), /* Short-time timewait calendar */ .twcal_hand = -1, diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index cf51c87a971..08386c10295 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -58,9 +58,11 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft } void -ieee80211softmac_assoc_timeout(void *d) +ieee80211softmac_assoc_timeout(struct work_struct *work) { - struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_device *mac = + container_of(work, struct ieee80211softmac_device, + associnfo.timeout.work); struct ieee80211softmac_network *n; mutex_lock(&mac->associnfo.mutex); @@ -186,9 +188,11 @@ ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void /* This function is called to handle userspace requests (asynchronously) */ void -ieee80211softmac_assoc_work(void *d) +ieee80211softmac_assoc_work(struct work_struct *work) { - struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_device *mac = + container_of(work, struct ieee80211softmac_device, + associnfo.work.work); struct ieee80211softmac_network *found = NULL; struct ieee80211_network *net = NULL, *best = NULL; int bssvalid; @@ -412,7 +416,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, network->authenticated = 0; /* we don't want to do this more than once ... */ network->auth_desynced_once = 1; - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); break; } default: @@ -446,7 +450,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, ieee80211softmac_disassoc(mac); /* try to reassociate */ - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } @@ -466,7 +470,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev, dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); return 0; } - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 0612015f1c7..6012705aa4f 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -26,7 +26,7 @@ #include "ieee80211softmac_priv.h" -static void ieee80211softmac_auth_queue(void *data); +static void ieee80211softmac_auth_queue(struct work_struct *work); /* Queues an auth request to the desired AP */ int @@ -54,14 +54,14 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, auth->mac = mac; auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT; auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST; - INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth); + INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue); /* Lock (for list) */ spin_lock_irqsave(&mac->lock, flags); /* add to list */ list_add_tail(&auth->list, &mac->auth_queue); - schedule_work(&auth->work); + schedule_delayed_work(&auth->work, 0); spin_unlock_irqrestore(&mac->lock, flags); return 0; @@ -70,14 +70,15 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, /* Sends an auth request to the desired AP and handles timeouts */ static void -ieee80211softmac_auth_queue(void *data) +ieee80211softmac_auth_queue(struct work_struct *work) { struct ieee80211softmac_device *mac; struct ieee80211softmac_auth_queue_item *auth; struct ieee80211softmac_network *net; unsigned long flags; - auth = (struct ieee80211softmac_auth_queue_item *)data; + auth = container_of(work, struct ieee80211softmac_auth_queue_item, + work.work); net = auth->net; mac = auth->mac; @@ -118,9 +119,11 @@ ieee80211softmac_auth_queue(void *data) /* Sends a response to an auth challenge (for shared key auth). */ static void -ieee80211softmac_auth_challenge_response(void *_aq) +ieee80211softmac_auth_challenge_response(struct work_struct *work) { - struct ieee80211softmac_auth_queue_item *aq = _aq; + struct ieee80211softmac_auth_queue_item *aq = + container_of(work, struct ieee80211softmac_auth_queue_item, + work.work); /* Send our response */ ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); @@ -234,8 +237,8 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) * we have obviously already sent the initial auth * request. */ cancel_delayed_work(&aq->work); - INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq); - schedule_work(&aq->work); + INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response); + schedule_delayed_work(&aq->work, 0); spin_unlock_irqrestore(&mac->lock, flags); return 0; case IEEE80211SOFTMAC_AUTH_SHARED_PASS: @@ -398,6 +401,6 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de ieee80211softmac_deauth_from_net(mac, net); /* let's try to re-associate */ - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index f34fa2ef666..b9015656cfb 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -73,10 +73,12 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { static void -ieee80211softmac_notify_callback(void *d) +ieee80211softmac_notify_callback(struct work_struct *work) { - struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d; - kfree(d); + struct ieee80211softmac_event *pevent = + container_of(work, struct ieee80211softmac_event, work.work); + struct ieee80211softmac_event event = *pevent; + kfree(pevent); event.fun(event.mac->dev, event.event_type, event.context); } @@ -99,7 +101,7 @@ ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, return -ENOMEM; eventptr->event_type = event; - INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr); + INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback); eventptr->fun = fun; eventptr->context = context; eventptr->mac = mac; @@ -170,7 +172,7 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve /* User may have subscribed to ANY event, so * we tell them which event triggered it. */ eventptr->event_type = event; - schedule_work(&eventptr->work); + schedule_delayed_work(&eventptr->work, 0); } } } diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 33aff4f4a47..256207b71dc 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -58,8 +58,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) INIT_LIST_HEAD(&softmac->events); mutex_init(&softmac->associnfo.mutex); - INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); - INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); + INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work); + INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout); softmac->start_scan = ieee80211softmac_start_scan_implementation; softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; softmac->stop_scan = ieee80211softmac_stop_scan_implementation; diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h index 0642e090b8a..c0dbe070e54 100644 --- a/net/ieee80211/softmac/ieee80211softmac_priv.h +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h @@ -78,7 +78,7 @@ /* private definitions and prototypes */ /*** prototypes from _scan.c */ -void ieee80211softmac_scan(void *sm); +void ieee80211softmac_scan(struct work_struct *work); /* for internal use if scanning is needed */ int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac); void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac); @@ -149,7 +149,7 @@ int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *au int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth); /*** prototypes from _assoc.c */ -void ieee80211softmac_assoc_work(void *d); +void ieee80211softmac_assoc_work(struct work_struct *work); int ieee80211softmac_handle_assoc_response(struct net_device * dev, struct ieee80211_assoc_response * resp, struct ieee80211_network * network); @@ -157,7 +157,7 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev, struct ieee80211_disassoc * disassoc); int ieee80211softmac_handle_reassoc_req(struct net_device * dev, struct ieee80211_reassoc_request * reassoc); -void ieee80211softmac_assoc_timeout(void *d); +void ieee80211softmac_assoc_timeout(struct work_struct *work); void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason); void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac); @@ -207,7 +207,7 @@ struct ieee80211softmac_auth_queue_item { struct ieee80211softmac_device *mac; /* SoftMAC device */ u8 retry; /* Retry limit */ u8 state; /* Auth State */ - struct work_struct work; /* Work queue */ + struct delayed_work work; /* Work queue */ }; /* scanning information */ @@ -219,7 +219,8 @@ struct ieee80211softmac_scaninfo { stop:1; u8 skip_flags; struct completion finished; - struct work_struct softmac_scan; + struct delayed_work softmac_scan; + struct ieee80211softmac_device *mac; }; /* private event struct */ @@ -227,7 +228,7 @@ struct ieee80211softmac_event { struct list_head list; int event_type; void *event_context; - struct work_struct work; + struct delayed_work work; notify_function_ptr fun; void *context; struct ieee80211softmac_device *mac; diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index 5507feab32d..0c85d6c24cd 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -90,12 +90,14 @@ ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm) /* internal scanning implementation follows */ -void ieee80211softmac_scan(void *d) +void ieee80211softmac_scan(struct work_struct *work) { int invalid_channel; u8 current_channel_idx; - struct ieee80211softmac_device *sm = (struct ieee80211softmac_device *)d; - struct ieee80211softmac_scaninfo *si = sm->scaninfo; + struct ieee80211softmac_scaninfo *si = + container_of(work, struct ieee80211softmac_scaninfo, + softmac_scan.work); + struct ieee80211softmac_device *sm = si->mac; unsigned long flags; while (!(si->stop) && (si->current_channel_idx < si->number_channels)) { @@ -146,7 +148,8 @@ static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee802 struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC); if (unlikely(!info)) return NULL; - INIT_WORK(&info->softmac_scan, ieee80211softmac_scan, mac); + INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan); + info->mac = mac; init_completion(&info->finished); return info; } @@ -187,7 +190,7 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev) sm->scaninfo->started = 1; sm->scaninfo->stop = 0; INIT_COMPLETION(sm->scaninfo->finished); - schedule_work(&sm->scaninfo->softmac_scan); + schedule_delayed_work(&sm->scaninfo->softmac_scan, 0); spin_unlock_irqrestore(&sm->lock, flags); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 23068a830f7..2ffaebd21c5 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -122,7 +122,7 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, sm->associnfo.associating = 1; /* queue lower level code to do work (if necessary) */ - schedule_work(&sm->associnfo.work); + schedule_delayed_work(&sm->associnfo.work, 0); out: mutex_unlock(&sm->associnfo.mutex); @@ -356,7 +356,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, /* force reassociation */ mac->associnfo.bssvalid = 0; if (mac->associnfo.associated) - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is no longer fixed */ mac->associnfo.bssfixed = 0; @@ -373,7 +373,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, /* tell the other code that this bssid should be used no matter what */ mac->associnfo.bssfixed = 1; /* queue associate if new bssid or (old one again and not associated) */ - schedule_work(&mac->associnfo.work); + schedule_delayed_work(&mac->associnfo.work, 0); } out: diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index cdd805344c6..8c74f9168b7 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -197,9 +197,10 @@ EXPORT_SYMBOL_GPL(inet_twdr_hangman); extern void twkill_slots_invalid(void); -void inet_twdr_twkill_work(void *data) +void inet_twdr_twkill_work(struct work_struct *work) { - struct inet_timewait_death_row *twdr = data; + struct inet_timewait_death_row *twdr = + container_of(work, struct inet_timewait_death_row, twkill_work); int i; if ((INET_TWDR_TWKILL_SLOTS - 1) > (sizeof(twdr->thread_slots) * 8)) diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index f261616e460..9b933381ebb 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -221,10 +221,10 @@ static void update_defense_level(void) * Timer for checking the defense */ #define DEFENSE_TIMER_PERIOD 1*HZ -static void defense_work_handler(void *data); -static DECLARE_WORK(defense_work, defense_work_handler, NULL); +static void defense_work_handler(struct work_struct *work); +static DECLARE_DELAYED_WORK(defense_work, defense_work_handler); -static void defense_work_handler(void *data) +static void defense_work_handler(struct work_struct *work) { update_defense_level(); if (atomic_read(&ip_vs_dropentry)) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 6dddf59c1fb..4a3889dd194 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -45,8 +45,7 @@ struct inet_timewait_death_row tcp_death_row = { .tw_timer = TIMER_INITIALIZER(inet_twdr_hangman, 0, (unsigned long)&tcp_death_row), .twkill_work = __WORK_INITIALIZER(tcp_death_row.twkill_work, - inet_twdr_twkill_work, - &tcp_death_row), + inet_twdr_twkill_work), /* Short-time timewait calendar */ .twcal_hand = -1, diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index d50a02030ad..262bda808d9 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -61,7 +61,7 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty); static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch); static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout); static void ircomm_tty_hangup(struct tty_struct *tty); -static void ircomm_tty_do_softint(void *private_); +static void ircomm_tty_do_softint(struct work_struct *work); static void ircomm_tty_shutdown(struct ircomm_tty_cb *self); static void ircomm_tty_stop(struct tty_struct *tty); @@ -389,7 +389,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) self->flow = FLOW_STOP; self->line = line; - INIT_WORK(&self->tqueue, ircomm_tty_do_softint, self); + INIT_WORK(&self->tqueue, ircomm_tty_do_softint); self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED; self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; self->close_delay = 5*HZ/10; @@ -594,15 +594,16 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty) } /* - * Function ircomm_tty_do_softint (private_) + * Function ircomm_tty_do_softint (work) * * We use this routine to give the write wakeup to the user at at a * safe time (as fast as possible after write have completed). This * can be compared to the Tx interrupt. */ -static void ircomm_tty_do_softint(void *private_) +static void ircomm_tty_do_softint(struct work_struct *work) { - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_; + struct ircomm_tty_cb *self = + container_of(work, struct ircomm_tty_cb, tqueue); struct tty_struct *tty; unsigned long flags; struct sk_buff *skb, *ctrl_skb; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 39471d3b31b..ad0057db0f9 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -61,7 +61,7 @@ #include <net/sctp/sm.h> /* Forward declarations for internal functions. */ -static void sctp_assoc_bh_rcv(struct sctp_association *asoc); +static void sctp_assoc_bh_rcv(struct work_struct *work); /* 1st Level Abstractions. */ @@ -269,9 +269,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a /* Create an input queue. */ sctp_inq_init(&asoc->base.inqueue); - sctp_inq_set_th_handler(&asoc->base.inqueue, - (void (*)(void *))sctp_assoc_bh_rcv, - asoc); + sctp_inq_set_th_handler(&asoc->base.inqueue, sctp_assoc_bh_rcv); /* Create an output queue. */ sctp_outq_init(asoc, &asoc->outqueue); @@ -946,8 +944,11 @@ out: } /* Do delayed input processing. This is scheduled by sctp_rcv(). */ -static void sctp_assoc_bh_rcv(struct sctp_association *asoc) +static void sctp_assoc_bh_rcv(struct work_struct *work) { + struct sctp_association *asoc = + container_of(work, struct sctp_association, + base.inqueue.immediate); struct sctp_endpoint *ep; struct sctp_chunk *chunk; struct sock *sk; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 33a42e90c32..129756908da 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -61,7 +61,7 @@ #include <net/sctp/sm.h> /* Forward declarations for internal helpers. */ -static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep); +static void sctp_endpoint_bh_rcv(struct work_struct *work); /* * Initialize the base fields of the endpoint structure. @@ -89,8 +89,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, sctp_inq_init(&ep->base.inqueue); /* Set its top-half handler */ - sctp_inq_set_th_handler(&ep->base.inqueue, - (void (*)(void *))sctp_endpoint_bh_rcv, ep); + sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv); /* Initialize the bind addr area */ sctp_bind_addr_init(&ep->base.bind_addr, 0); @@ -318,8 +317,11 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, /* Do delayed input processing. This is scheduled by sctp_rcv(). * This may be called on BH or task time. */ -static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep) +static void sctp_endpoint_bh_rcv(struct work_struct *work) { + struct sctp_endpoint *ep = + container_of(work, struct sctp_endpoint, + base.inqueue.immediate); struct sctp_association *asoc; struct sock *sk; struct sctp_transport *transport; diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index cf6deed7e84..71b07466e88 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -54,7 +54,7 @@ void sctp_inq_init(struct sctp_inq *queue) queue->in_progress = NULL; /* Create a task for delivering data. */ - INIT_WORK(&queue->immediate, NULL, NULL); + INIT_WORK(&queue->immediate, NULL); queue->malloced = 0; } @@ -97,7 +97,7 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) * on the BH related data structures. */ list_add_tail(&chunk->list, &q->in_chunk_list); - q->immediate.func(q->immediate.data); + q->immediate.func(&q->immediate); } /* Extract a chunk from an SCTP inqueue. @@ -205,9 +205,8 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) * The intent is that this routine will pull stuff out of the * inqueue and process it. */ -void sctp_inq_set_th_handler(struct sctp_inq *q, - void (*callback)(void *), void *arg) +void sctp_inq_set_th_handler(struct sctp_inq *q, work_func_t callback) { - INIT_WORK(&q->immediate, callback, arg); + INIT_WORK(&q->immediate, callback); } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 00cb388ece0..d96fd466a9a 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -284,8 +284,8 @@ static struct file_operations cache_file_operations; static struct file_operations content_file_operations; static struct file_operations cache_flush_operations; -static void do_cache_clean(void *data); -static DECLARE_WORK(cache_cleaner, do_cache_clean, NULL); +static void do_cache_clean(struct work_struct *work); +static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); void cache_register(struct cache_detail *cd) { @@ -337,7 +337,7 @@ void cache_register(struct cache_detail *cd) spin_unlock(&cache_list_lock); /* start the cleaning process */ - schedule_work(&cache_cleaner); + schedule_delayed_work(&cache_cleaner, 0); } int cache_unregister(struct cache_detail *cd) @@ -461,7 +461,7 @@ static int cache_clean(void) /* * We want to regularly clean the cache, so we need to schedule some work ... */ -static void do_cache_clean(void *data) +static void do_cache_clean(struct work_struct *work) { int delay = 5; if (cache_clean() == -1) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9a0b41a97f9..49dba5febbb 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -54,10 +54,11 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, } static void -rpc_timeout_upcall_queue(void *data) +rpc_timeout_upcall_queue(struct work_struct *work) { LIST_HEAD(free_list); - struct rpc_inode *rpci = (struct rpc_inode *)data; + struct rpc_inode *rpci = + container_of(work, struct rpc_inode, queue_timeout.work); struct inode *inode = &rpci->vfs_inode; void (*destroy_msg)(struct rpc_pipe_msg *); @@ -837,7 +838,8 @@ init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) INIT_LIST_HEAD(&rpci->pipe); rpci->pipelen = 0; init_waitqueue_head(&rpci->waitq); - INIT_WORK(&rpci->queue_timeout, rpc_timeout_upcall_queue, rpci); + INIT_DELAYED_WORK(&rpci->queue_timeout, + rpc_timeout_upcall_queue); rpci->ops = NULL; } } diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f9fd66b1d48..18a33d32701 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -41,7 +41,7 @@ static mempool_t *rpc_buffer_mempool __read_mostly; static void __rpc_default_timer(struct rpc_task *task); static void rpciod_killall(void); -static void rpc_async_schedule(void *); +static void rpc_async_schedule(struct work_struct *); /* * RPC tasks sit here while waiting for conditions to improve. @@ -323,7 +323,7 @@ static void rpc_make_runnable(struct rpc_task *task) if (RPC_IS_ASYNC(task)) { int status; - INIT_WORK(&task->u.tk_work, rpc_async_schedule, (void *)task); + INIT_WORK(&task->u.tk_work, rpc_async_schedule); status = queue_work(task->tk_workqueue, &task->u.tk_work); if (status < 0) { printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status); @@ -729,9 +729,9 @@ rpc_execute(struct rpc_task *task) return __rpc_execute(task); } -static void rpc_async_schedule(void *arg) +static void rpc_async_schedule(struct work_struct *work) { - __rpc_execute((struct rpc_task *)arg); + __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); } /** diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index f8ca0a93454..7a3999f0a4a 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -477,9 +477,10 @@ int xprt_adjust_timeout(struct rpc_rqst *req) return status; } -static void xprt_autoclose(void *args) +static void xprt_autoclose(struct work_struct *work) { - struct rpc_xprt *xprt = (struct rpc_xprt *)args; + struct rpc_xprt *xprt = + container_of(work, struct rpc_xprt, task_cleanup); xprt_disconnect(xprt); xprt->ops->close(xprt); @@ -916,7 +917,7 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si INIT_LIST_HEAD(&xprt->free); INIT_LIST_HEAD(&xprt->recv); - INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt); + INIT_WORK(&xprt->task_cleanup, xprt_autoclose); init_timer(&xprt->timer); xprt->timer.function = xprt_init_autodisconnect; xprt->timer.data = (unsigned long) xprt; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 21438d7dc47..3bb232eb5d9 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -235,7 +235,7 @@ struct sock_xprt { /* * Connection of transports */ - struct work_struct connect_worker; + struct delayed_work connect_worker; unsigned short port; /* @@ -1175,13 +1175,14 @@ static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock) /** * xs_udp_connect_worker - set up a UDP socket - * @args: RPC transport to connect + * @work: RPC transport to connect * * Invoked by a work queue tasklet. */ -static void xs_udp_connect_worker(void *args) +static void xs_udp_connect_worker(struct work_struct *work) { - struct sock_xprt *transport = (struct sock_xprt *)args; + struct sock_xprt *transport = + container_of(work, struct sock_xprt, connect_worker.work); struct rpc_xprt *xprt = &transport->xprt; struct socket *sock = transport->sock; int err, status = -EIO; @@ -1260,13 +1261,14 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) /** * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint - * @args: RPC transport to connect + * @work: RPC transport to connect * * Invoked by a work queue tasklet. */ -static void xs_tcp_connect_worker(void *args) +static void xs_tcp_connect_worker(struct work_struct *work) { - struct sock_xprt *transport = (struct sock_xprt *)args; + struct sock_xprt *transport = + container_of(work, struct sock_xprt, connect_worker.work); struct rpc_xprt *xprt = &transport->xprt; struct socket *sock = transport->sock; int err, status = -EIO; @@ -1380,7 +1382,7 @@ static void xs_connect(struct rpc_task *task) xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO; } else { dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); - schedule_work(&transport->connect_worker); + schedule_delayed_work(&transport->connect_worker, 0); /* flush_scheduled_work can sleep... */ if (!RPC_IS_ASYNC(task)) @@ -1525,7 +1527,7 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_ /* XXX: header size can vary due to auth type, IPv6, etc. */ xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); - INIT_WORK(&transport->connect_worker, xs_udp_connect_worker, transport); + INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker); xprt->bind_timeout = XS_BIND_TO; xprt->connect_timeout = XS_UDP_CONN_TO; xprt->reestablish_timeout = XS_UDP_REEST_TO; @@ -1569,7 +1571,7 @@ struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_ xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; - INIT_WORK(&transport->connect_worker, xs_tcp_connect_worker, transport); + INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker); xprt->bind_timeout = XS_BIND_TO; xprt->connect_timeout = XS_TCP_CONN_TO; xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 64d3938f74c..f6c77bd36fd 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -392,7 +392,7 @@ static void xfrm_policy_gc_kill(struct xfrm_policy *policy) xfrm_pol_put(policy); } -static void xfrm_policy_gc_task(void *data) +static void xfrm_policy_gc_task(struct work_struct *work) { struct xfrm_policy *policy; struct hlist_node *entry, *tmp; @@ -580,7 +580,7 @@ static inline int xfrm_byidx_should_resize(int total) static DEFINE_MUTEX(hash_resize_mutex); -static void xfrm_hash_resize(void *__unused) +static void xfrm_hash_resize(struct work_struct *__unused) { int dir, total; @@ -597,7 +597,7 @@ static void xfrm_hash_resize(void *__unused) mutex_unlock(&hash_resize_mutex); } -static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL); +static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); /* Generate new index... KAME seems to generate them ordered by cost * of an absolute inpredictability of ordering of rules. This will not pass. */ @@ -2116,7 +2116,7 @@ static void __init xfrm_policy_init(void) panic("XFRM: failed to allocate bydst hash\n"); } - INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL); + INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); register_netdevice_notifier(&xfrm_dev_notifier); } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 864962bbda9..da54a64ccfa 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -115,7 +115,7 @@ static unsigned long xfrm_hash_new_size(void) static DEFINE_MUTEX(hash_resize_mutex); -static void xfrm_hash_resize(void *__unused) +static void xfrm_hash_resize(struct work_struct *__unused) { struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; unsigned long nsize, osize; @@ -168,7 +168,7 @@ out_unlock: mutex_unlock(&hash_resize_mutex); } -static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL); +static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); DECLARE_WAIT_QUEUE_HEAD(km_waitq); EXPORT_SYMBOL(km_waitq); @@ -207,7 +207,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) kfree(x); } -static void xfrm_state_gc_task(void *data) +static void xfrm_state_gc_task(struct work_struct *data) { struct xfrm_state *x; struct hlist_node *entry, *tmp; @@ -1568,6 +1568,6 @@ void __init xfrm_state_init(void) panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); - INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); + INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task); } diff --git a/security/keys/key.c b/security/keys/key.c index 80de8c3e9cc..70eacbe5abd 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -30,8 +30,8 @@ DEFINE_SPINLOCK(key_user_lock); static LIST_HEAD(key_types_list); static DECLARE_RWSEM(key_types_sem); -static void key_cleanup(void *data); -static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL); +static void key_cleanup(struct work_struct *work); +static DECLARE_WORK(key_cleanup_task, key_cleanup); /* we serialise key instantiation and link */ DECLARE_RWSEM(key_construction_sem); @@ -552,7 +552,7 @@ EXPORT_SYMBOL(key_negate_and_link); * do cleaning up in process context so that we don't have to disable * interrupts all over the place */ -static void key_cleanup(void *data) +static void key_cleanup(struct work_struct *work) { struct rb_node *_n; struct key *key; diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h index 3a61f311557..ee64f5de896 100644 --- a/sound/aoa/aoa-gpio.h +++ b/sound/aoa/aoa-gpio.h @@ -59,10 +59,10 @@ struct gpio_methods { }; struct gpio_notification { + struct delayed_work work; notify_func_t notify; void *data; void *gpio_private; - struct work_struct work; struct mutex mutex; }; diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c index 40eb47eccf9..2b03bc798bc 100644 --- a/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/sound/aoa/core/snd-aoa-gpio-feature.c @@ -195,9 +195,10 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) ftr_gpio_set_lineout(rt, (s>>2)&1); } -static void ftr_handle_notify(void *data) +static void ftr_handle_notify(struct work_struct *work) { - struct gpio_notification *notif = data; + struct gpio_notification *notif = + container_of(work, struct gpio_notification, work.work); mutex_lock(¬if->mutex); if (notif->notify) @@ -253,12 +254,9 @@ static void ftr_gpio_init(struct gpio_runtime *rt) ftr_gpio_all_amps_off(rt); rt->implementation_private = 0; - INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify, - &rt->headphone_notify); - INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify, - &rt->line_in_notify); - INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify, - &rt->line_out_notify); + INIT_DELAYED_WORK(&rt->headphone_notify.work, ftr_handle_notify); + INIT_DELAYED_WORK(&rt->line_in_notify.work, ftr_handle_notify); + INIT_DELAYED_WORK(&rt->line_out_notify.work, ftr_handle_notify); mutex_init(&rt->headphone_notify.mutex); mutex_init(&rt->line_in_notify.mutex); mutex_init(&rt->line_out_notify.mutex); @@ -287,7 +285,7 @@ static irqreturn_t ftr_handle_notify_irq(int xx, void *data) { struct gpio_notification *notif = data; - schedule_work(¬if->work); + schedule_delayed_work(¬if->work, 0); return IRQ_HANDLED; } diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c index 2836c321839..5ca2220eac7 100644 --- a/sound/aoa/core/snd-aoa-gpio-pmf.c +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c @@ -69,9 +69,10 @@ static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt) pmf_gpio_set_lineout(rt, (s>>2)&1); } -static void pmf_handle_notify(void *data) +static void pmf_handle_notify(struct work_struct *work) { - struct gpio_notification *notif = data; + struct gpio_notification *notif = + container_of(work, struct gpio_notification, work.work); mutex_lock(¬if->mutex); if (notif->notify) @@ -83,12 +84,9 @@ static void pmf_gpio_init(struct gpio_runtime *rt) { pmf_gpio_all_amps_off(rt); rt->implementation_private = 0; - INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, - &rt->headphone_notify); - INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, - &rt->line_in_notify); - INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, - &rt->line_out_notify); + INIT_DELAYED_WORK(&rt->headphone_notify.work, pmf_handle_notify); + INIT_DELAYED_WORK(&rt->line_in_notify.work, pmf_handle_notify); + INIT_DELAYED_WORK(&rt->line_out_notify.work, pmf_handle_notify); mutex_init(&rt->headphone_notify.mutex); mutex_init(&rt->line_in_notify.mutex); mutex_init(&rt->line_out_notify.mutex); @@ -129,7 +127,7 @@ static void pmf_handle_notify_irq(void *data) { struct gpio_notification *notif = data; - schedule_work(¬if->work); + schedule_delayed_work(¬if->work, 0); } static int pmf_set_notify(struct gpio_runtime *rt, diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 12ffffc9e81..d2f2c5078e6 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -35,7 +35,7 @@ MODULE_LICENSE("GPL"); #define AK4114_ADDR 0x00 /* fixed address */ -static void ak4114_stats(void *); +static void ak4114_stats(struct work_struct *work); static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val) { @@ -158,7 +158,7 @@ void snd_ak4114_reinit(struct ak4114 *chip) reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); /* bring up statistics / event queing */ chip->init = 0; - INIT_WORK(&chip->work, ak4114_stats, chip); + INIT_DELAYED_WORK(&chip->work, ak4114_stats); queue_delayed_work(chip->workqueue, &chip->work, HZ / 10); } @@ -561,9 +561,9 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) return res; } -static void ak4114_stats(void *data) +static void ak4114_stats(struct work_struct *work) { - struct ak4114 *chip = (struct ak4114 *)data; + struct ak4114 *chip = container_of(work, struct ak4114, work.work); if (chip->init) return; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 6577b232535..7abcb10b275 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1927,9 +1927,10 @@ static int snd_ac97_dev_disconnect(struct snd_device *device) static struct snd_ac97_build_ops null_build_ops; #ifdef CONFIG_SND_AC97_POWER_SAVE -static void do_update_power(void *data) +static void do_update_power(struct work_struct *work) { - update_power_regs(data); + update_power_regs( + container_of(work, struct snd_ac97, power_work.work)); } #endif @@ -1989,7 +1990,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, mutex_init(&ac97->page_mutex); #ifdef CONFIG_SND_AC97_POWER_SAVE ac97->power_workq = create_workqueue("ac97"); - INIT_WORK(&ac97->power_work, do_update_power, ac97); + INIT_DELAYED_WORK(&ac97->power_work, do_update_power); #endif #ifdef CONFIG_PCI diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9c3d7ac0806..71482c15a85 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -272,10 +272,11 @@ EXPORT_SYMBOL(snd_hda_queue_unsol_event); /* * process queueud unsolicited events */ -static void process_unsol_events(void *data) +static void process_unsol_events(struct work_struct *work) { - struct hda_bus *bus = data; - struct hda_bus_unsolicited *unsol = bus->unsol; + struct hda_bus_unsolicited *unsol = + container_of(work, struct hda_bus_unsolicited, work); + struct hda_bus *bus = unsol->bus; struct hda_codec *codec; unsigned int rp, caddr, res; @@ -314,7 +315,8 @@ static int init_unsol_queue(struct hda_bus *bus) kfree(unsol); return -ENOMEM; } - INIT_WORK(&unsol->work, process_unsol_events, bus); + INIT_WORK(&unsol->work, process_unsol_events); + unsol->bus = bus; bus->unsol = unsol; return 0; } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index f9416c36396..9ca1baf860b 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -206,6 +206,7 @@ struct hda_bus_unsolicited { /* workqueue */ struct workqueue_struct *workq; struct work_struct work; + struct hda_bus *bus; }; /* diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 2fbe1d183fc..8f074c7936e 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -942,10 +942,11 @@ static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int } static struct work_struct device_change; +static struct snd_pmac *device_change_chip; -static void device_change_handler(void *self) +static void device_change_handler(struct work_struct *work) { - struct snd_pmac *chip = self; + struct snd_pmac *chip = device_change_chip; struct pmac_tumbler *mix; int headphone, lineout; @@ -1417,7 +1418,8 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) chip->resume = tumbler_resume; #endif - INIT_WORK(&device_change, device_change_handler, (void *)chip); + INIT_WORK(&device_change, device_change_handler); + device_change_chip = chip; #ifdef PMAC_SUPPORT_AUTOMUTE if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) |