From 63fe08177f92ce21929df8af6361491b98ad12cd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Apr 2009 12:01:53 +1000 Subject: md: tiny md.h cleanups - update inclusion guard and make sure it covers the whole file - remove superflous #ifdef CONFIG_BLOCK - make sure all required headers are included so that new users aren't required to include others before Signed-off-by: Christoph Hellwig Signed-off-by: NeilBrown --- drivers/md/md.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.h b/drivers/md/md.h index e9b7f54c24d..8227ab909d4 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -12,10 +12,17 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _MD_K_H -#define _MD_K_H - -#ifdef CONFIG_BLOCK +#ifndef _MD_MD_H +#define _MD_MD_H + +#include +#include +#include +#include +#include +#include +#include +#include #define MaxSector (~(sector_t)0) @@ -408,10 +415,6 @@ static inline void safe_put_page(struct page *p) if (p) put_page(p); } -#endif /* CONFIG_BLOCK */ -#endif - - extern int register_md_personality(struct mdk_personality *p); extern int unregister_md_personality(struct mdk_personality *p); extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev), @@ -434,3 +437,5 @@ extern void md_new_event(mddev_t *mddev); extern int md_allow_write(mddev_t *mddev); extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev); extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors); + +#endif /* _MD_MD_H */ -- cgit v1.2.3 From 6d56e278444bc8323b1bcfcada126b8e4dbba0f4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 14 Apr 2009 12:01:57 +1000 Subject: md: allow setting newly added device to 'in_sync' via sysfs. When adding devices to an active array via sysfs, there is currently no way to mark a device as 'in-sync' which is useful when incrementally assembling an array. So add that option. Signed-off-by: NeilBrown --- drivers/md/md.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index ed5727c089a..298731b8e95 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2086,6 +2086,7 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len) * -writemostly - clears write_mostly * blocked - sets the Blocked flag * -blocked - clears the Blocked flag + * insync - sets Insync providing device isn't active */ int err = -EINVAL; if (cmd_match(buf, "faulty") && rdev->mddev->pers) { @@ -2117,6 +2118,9 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len) set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); md_wakeup_thread(rdev->mddev->thread); + err = 0; + } else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) { + set_bit(In_sync, &rdev->flags); err = 0; } if (!err && rdev->sysfs_state) @@ -2190,7 +2194,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) } else if (rdev->mddev->pers) { mdk_rdev_t *rdev2; /* Activating a spare .. or possibly reactivating - * if we every get bitmaps working here. + * if we ever get bitmaps working here. */ if (rdev->raid_disk != -1) -- cgit v1.2.3 From acb180b0e335ad88acfed6c8a33e39c05b95dc49 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 14 Apr 2009 16:28:34 +1000 Subject: md: improve usefulness and accuracy of sysfs file md/sync_completed. The sync_completed file reports how much of a resync (or recovery or reshape) has been completed. However due to the possibility of out-of-order completion of writes, it is not certain to be accurate. We have an internal value - mddev->curr_resync_completed - which is an accurate value (though it might not always be quite so uptodate). So: - make curr_resync_completed be uptodate a little more often, particularly when raid5 reshape updates status in the metadata - report curr_resync_completed in the sysfs file - allow poll/select to report all updates to md/sync_completed. This makes sync_completed completed usable by any external metadata handler that wants to record this status information in its metadata. Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 1 + drivers/md/md.c | 34 ++++++++++++++++++++++------------ drivers/md/raid5.c | 4 ++++ 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f8a9f7ab2cb..e4510c976b3 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1479,6 +1479,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) s += blocks; } bitmap->last_end_sync = jiffies; + sysfs_notify(&bitmap->mddev->kobj, NULL, "sync_completed"); } static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) diff --git a/drivers/md/md.c b/drivers/md/md.c index 298731b8e95..7af64f3846a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2017,6 +2017,8 @@ repeat: clear_bit(MD_CHANGE_PENDING, &mddev->flags); spin_unlock_irq(&mddev->write_lock); wake_up(&mddev->sb_wait); + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } @@ -3486,12 +3488,15 @@ sync_completed_show(mddev_t *mddev, char *page) { unsigned long max_sectors, resync; + if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + return sprintf(page, "none\n"); + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) max_sectors = mddev->resync_max_sectors; else max_sectors = mddev->dev_sectors; - resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active)); + resync = mddev->curr_resync_completed; return sprintf(page, "%lu / %lu\n", resync, max_sectors); } @@ -6338,18 +6343,12 @@ void md_do_sync(mddev_t *mddev) sector_t sectors; skipped = 0; - if (j >= mddev->resync_max) { - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); - wait_event(mddev->recovery_wait, - mddev->resync_max > j - || kthread_should_stop()); - } - if (kthread_should_stop()) - goto interrupted; - if (mddev->curr_resync > mddev->curr_resync_completed && - (mddev->curr_resync - mddev->curr_resync_completed) - > (max_sectors >> 4)) { + if ((mddev->curr_resync > mddev->curr_resync_completed && + (mddev->curr_resync - mddev->curr_resync_completed) + > (max_sectors >> 4)) || + j >= mddev->resync_max + ) { /* time to update curr_resync_completed */ blk_unplug(mddev->queue); wait_event(mddev->recovery_wait, @@ -6357,7 +6356,17 @@ void md_do_sync(mddev_t *mddev) mddev->curr_resync_completed = mddev->curr_resync; set_bit(MD_CHANGE_CLEAN, &mddev->flags); + sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } + + if (j >= mddev->resync_max) + wait_event(mddev->recovery_wait, + mddev->resync_max > j + || kthread_should_stop()); + + if (kthread_should_stop()) + goto interrupted; + sectors = mddev->pers->sync_request(mddev, j, &skipped, currspeed < speed_min(mddev)); if (sectors == 0) { @@ -6465,6 +6474,7 @@ void md_do_sync(mddev_t *mddev) skip: mddev->curr_resync = 0; + mddev->curr_resync_completed = 0; mddev->resync_min = 0; mddev->resync_max = MaxSector; sysfs_notify(&mddev->kobj, NULL, "sync_completed"); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 3bbc6d64704..76892ac7254 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3845,6 +3845,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped wait_event(conf->wait_for_overlap, atomic_read(&conf->reshape_stripes)==0); mddev->reshape_position = conf->reshape_progress; + mddev->curr_resync_completed = mddev->curr_resync; conf->reshape_checkpoint = jiffies; set_bit(MD_CHANGE_DEVS, &mddev->flags); md_wakeup_thread(mddev->thread); @@ -3854,6 +3855,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped conf->reshape_safe = mddev->reshape_position; spin_unlock_irq(&conf->device_lock); wake_up(&conf->wait_for_overlap); + sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } if (mddev->delta_disks < 0) { @@ -3943,6 +3945,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped wait_event(conf->wait_for_overlap, atomic_read(&conf->reshape_stripes) == 0); mddev->reshape_position = conf->reshape_progress; + mddev->curr_resync_completed = mddev->curr_resync; conf->reshape_checkpoint = jiffies; set_bit(MD_CHANGE_DEVS, &mddev->flags); md_wakeup_thread(mddev->thread); @@ -3953,6 +3956,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped conf->reshape_safe = mddev->reshape_position; spin_unlock_irq(&conf->device_lock); wake_up(&conf->wait_for_overlap); + sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } return reshape_sectors; } -- cgit v1.2.3 From c03f6a19699fce4389888a45db8245969311d868 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 17 Apr 2009 11:06:30 +1000 Subject: md: update sync_completed and reshape_position even more often. There are circumstances when a user-space process might need to "oversee" a resync/reshape process. For example when doing an in-place reshape of a raid5, it is prudent to take a backup of each section before reshaping it as this is the only way to provide safety against an unplanned shutdown (i.e. crash/power failure). The sync_max sysfs value can be used to stop the resync from advancing beyond a particular point. So user-space can: suspend IO to the first section and back it up set 'sync_max' to the end of the section wait for 'sync_completed' to reach that point resume IO on the first section and move on to the next section. However this process requires the kernel and user-space to run in lock-step which could introduce unnecessary delays. It would be better if a 'double buffered' approach could be used with userspace and kernel space working on different sections with the 'next' section always ready when the 'current' section is finished. One problem with implementing this is that sync_completed is only guaranteed to be updated when the sync process reaches sync_max. (it is updated on a time basis at other times, but it is hard to rely on that). This defeats some of the double buffering. With this patch, sync_completed (and reshape_position) get updated as the current position approaches sync_max, so there is room for userspace to advance sync_max early without losing updates. To be precise, sync_completed is updated when the current sync position reaches half way between the current value of sync_completed and the value of sync_max. This will usually be a good time for user space to update sync_max. If sync_max does not get updated, the updates to sync_completed (together with associated metadata updates) will occur at an exponentially increasing frequency which will get unreasonably fast (one update every page) immediately before the process hits sync_max and stops. So the update rate will be unreasonably fast only for an insignificant period of time. Signed-off-by: NeilBrown --- drivers/md/md.c | 3 ++- drivers/md/raid5.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 7af64f3846a..612343fdde9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6347,7 +6347,8 @@ void md_do_sync(mddev_t *mddev) if ((mddev->curr_resync > mddev->curr_resync_completed && (mddev->curr_resync - mddev->curr_resync_completed) > (max_sectors >> 4)) || - j >= mddev->resync_max + (j - mddev->curr_resync_completed)*2 + >= mddev->resync_max - mddev->curr_resync_completed ) { /* time to update curr_resync_completed */ blk_unplug(mddev->queue); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 76892ac7254..4616bc3a6e7 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3940,7 +3940,8 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped * then we need to write out the superblock. */ sector_nr += reshape_sectors; - if (sector_nr >= mddev->resync_max) { + if ((sector_nr - mddev->curr_resync_completed) * 2 + >= mddev->resync_max - mddev->curr_resync_completed) { /* Cannot proceed until we've updated the superblock... */ wait_event(conf->wait_for_overlap, atomic_read(&conf->reshape_stripes) == 0); -- cgit v1.2.3 From c018f1ee5cf81e58b93d9e93a2ee39cad13dc1ac Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 18 Apr 2009 17:42:19 +0200 Subject: hpt366: fix HPT370 DMA timeouts The big driver change in 2.4.19-rc1 introduced a regression for many HPT370[A] chips -- DMA stopped to work completely, only causing endless timeouts... The culprit has been identified (at last!): it turned to be the code resetting the DMA state machine before each transfer. Stop doing it now as this counter- measure has clearly caused more harm than good. This should fix the kernel.org bug #7703. Signed-off-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/hpt366.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index a0eb87f5913..cea1ac222a9 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -114,6 +114,8 @@ * the register setting lists into the table indexed by the clock selected * - set the correct hwif->ultra_mask for each individual chip * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards + * - stop resetting HPT370's state machine before each DMA transfer as that has + * caused more harm than good * Sergei Shtylyov, or */ @@ -133,7 +135,7 @@ #define DRV_NAME "hpt366" /* various tuning parameters */ -#define HPT_RESET_STATE_ENGINE +#undef HPT_RESET_STATE_ENGINE #undef HPT_DELAY_INTERRUPT static const char *quirk_drives[] = { -- cgit v1.2.3 From 59c8d04f5ee97ea46da854e9adbbaa45d988c39d Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 18 Apr 2009 17:42:19 +0200 Subject: hpt366: use ATA_DMA_* constants Use ATA_DMA_* constants instead of the bare numbers for the BMIDE register bits. Signed-off-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/hpt366.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index cea1ac222a9..0feb66c720e 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -3,7 +3,7 @@ * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc * Portions Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * Portions Copyright (C) 2005-2008 MontaVista Software, Inc. + * Portions Copyright (C) 2005-2009 MontaVista Software, Inc. * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his @@ -810,7 +810,7 @@ static void hpt370_irq_timeout(ide_drive_t *drive) /* get DMA command mode */ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); /* stop DMA */ - outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD); + outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD); hpt370_clear_engine(drive); } @@ -827,11 +827,11 @@ static int hpt370_dma_end(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - if (dma_stat & 0x01) { + if (dma_stat & ATA_DMA_ACTIVE) { /* wait a little */ udelay(20); dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - if (dma_stat & 0x01) + if (dma_stat & ATA_DMA_ACTIVE) hpt370_irq_timeout(drive); } return ide_dma_end(drive); @@ -853,7 +853,7 @@ static int hpt374_dma_test_irq(ide_drive_t *drive) dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); /* return 1 if INTR asserted */ - if (dma_stat & 4) + if (dma_stat & ATA_DMA_INTR) return 1; return 0; -- cgit v1.2.3 From d5f840bf74c09ca5a31e518c9d984999926b5f44 Mon Sep 17 00:00:00 2001 From: Jack Stone Date: Sat, 18 Apr 2009 17:42:19 +0200 Subject: ide: Remove void casts Remove uneeded void casts Signed-off-by: Jack Stone Cc: jeff@garzik.org Cc: kernel-janitors@vger.kernel.org Cc: Jack Stone Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 052b9bf1f8f..f76e4e6b408 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -1682,7 +1682,7 @@ static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, * The +2 is +1 for the stop command and +1 to allow for * aligning the start address to a multiple of 16 bytes. */ - pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( + pmif->dma_table_cpu = pci_alloc_consistent( dev, (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), &hwif->dmatable_dma); -- cgit v1.2.3 From f505d49ffd25ed062e76ffd17568d3937fcd338c Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sat, 18 Apr 2009 17:42:20 +0200 Subject: ide: fix barriers support Freeing non-slab objects is bad and results in an oops. Fix it. Reported-and-tested-by: Andrew Price Cc: Theodore Tso Cc: "Rafael J. Wysocki" Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 2ae02b8d7f8..35dc38d3b2c 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -102,11 +102,14 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) drive->dev_flags |= IDE_DFLAG_PARKED; } - if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE) - memcpy(rq->special, cmd, sizeof(*cmd)); + if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { + struct ide_cmd *orig_cmd = rq->special; - if (cmd->tf_flags & IDE_TFLAG_DYN) - kfree(cmd); + if (cmd->tf_flags & IDE_TFLAG_DYN) + kfree(orig_cmd); + else + memcpy(orig_cmd, cmd, sizeof(*cmd)); + } } /* obsolete, blk_rq_bytes() should be used instead */ -- cgit v1.2.3 From 15da90b516e9da92cc1d90001e640fd6707d0e27 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 18 Apr 2009 17:42:20 +0200 Subject: cs5536: define dma_sff_read_status() method The driver somehow got merged with the initializer for the dma_sff_read_status() method missing which caused kernel panic on bootup. This should fix the kernel.org bug #13026... Signed-off-by: Sergei Shtylyov Reported-by: Arnd Hannemann Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/cs5536.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c index 353a35bbba6..0332a95eefd 100644 --- a/drivers/ide/cs5536.c +++ b/drivers/ide/cs5536.c @@ -236,6 +236,7 @@ static const struct ide_dma_ops cs5536_dma_ops = { .dma_test_irq = ide_dma_test_irq, .dma_lost_irq = ide_dma_lost_irq, .dma_timer_expiry = ide_dma_sff_timer_expiry, + .dma_sff_read_status = ide_dma_sff_read_status, }; static const struct ide_port_info cs5536_info = { -- cgit v1.2.3 From 88df781afb788fa588dbf2e77f205214022a8893 Mon Sep 17 00:00:00 2001 From: Matias Zabaljauregui Date: Wed, 8 Apr 2009 17:58:39 -0300 Subject: lguest: fix crash on vmlinux images Typical message: 'lguest: unhandled trap 6 at 0x418726 (0x0)' vmlinux guests were broken by 4cd8b5e2a159f18a1507f1187b44a1acbfa6341b 'lguest: use KVM hypercalls', which rewrites guest text from kvm hypercalls to trap 31. The Launcher mmaps the kernel image. The Guest executes and immediately faults in the first text page (read-only). Then it hits a hypercall, and we rewrite that hypercall, causing a copy-on-write. But the Guest pagetables still refer to the old page: we fault again, but as Host we see the hypercall already rewritten, and pass the fault back to the Guest. The Guest hasn't set up an IDT yet, so we kill it. This doesn't happen with bzImages: they unpack themselves and so the text pages are already read-write. Signed-off-by: Rusty Russell Tested-by: Patrick McHardy --- drivers/lguest/x86/core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index a6b717644be..d6d7ac0982a 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -324,6 +324,11 @@ static void rewrite_hypercall(struct lg_cpu *cpu) u8 insn[3] = {0xcd, 0x1f, 0x90}; __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn)); + /* The above write might have caused a copy of that page to be made + * (if it was read-only). We need to make sure the Guest has + * up-to-date pagetables. As this doesn't happen often, we can just + * drop them all. */ + guest_pagetable_clear_all(cpu); } static bool is_hypercall(struct lg_cpu *cpu) -- cgit v1.2.3 From a489f0b555b753f9df8ddc24c7e74f657ef7ee7b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sun, 19 Apr 2009 23:14:00 -0600 Subject: lguest: fix guest crash on non-linear addresses in gdt pvops Fixes guest crash 'lguest: bad read address 0x4800000 len 256' The new per-cpu allocator ends up handing a non-linear address to write_gdt_entry. We do __pa() on it, and hand it to the host, which kills us. I've long wanted to make the hypercall "LOAD_GDT_ENTRY" to match the IDT code, but had no pressing reason until now. Signed-off-by: Rusty Russell Cc: lguest@ozlabs.org --- drivers/lguest/lg.h | 3 ++- drivers/lguest/segments.c | 13 +++++++------ drivers/lguest/x86/core.c | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index ac8a4a3741b..af92a176697 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -158,7 +158,8 @@ void free_interrupts(void); /* segments.c: */ void setup_default_gdt_entries(struct lguest_ro_state *state); void setup_guest_gdt(struct lg_cpu *cpu); -void load_guest_gdt(struct lg_cpu *cpu, unsigned long table, u32 num); +void load_guest_gdt_entry(struct lg_cpu *cpu, unsigned int i, + u32 low, u32 hi); void guest_load_tls(struct lg_cpu *cpu, unsigned long tls_array); void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt); void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt); diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index 4f15439b7f1..7ede64ffeef 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c @@ -144,18 +144,19 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt) gdt[i] = cpu->arch.gdt[i]; } -/*H:620 This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). - * We copy it from the Guest and tweak the entries. */ -void load_guest_gdt(struct lg_cpu *cpu, unsigned long table, u32 num) +/*H:620 This is where the Guest asks us to load a new GDT entry + * (LHCALL_LOAD_GDT_ENTRY). We tweak the entry and copy it in. */ +void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi) { /* We assume the Guest has the same number of GDT entries as the * Host, otherwise we'd have to dynamically allocate the Guest GDT. */ if (num > ARRAY_SIZE(cpu->arch.gdt)) kill_guest(cpu, "too many gdt entries %i", num); - /* We read the whole thing in, then fix it up. */ - __lgread(cpu, cpu->arch.gdt, table, num * sizeof(cpu->arch.gdt[0])); - fixup_gdt_table(cpu, 0, ARRAY_SIZE(cpu->arch.gdt)); + /* Set it up, then fix it. */ + cpu->arch.gdt[num].a = lo; + cpu->arch.gdt[num].b = hi; + fixup_gdt_table(cpu, num, num+1); /* Mark that the GDT changed so the core knows it has to copy it again, * even if the Guest is run on the same CPU. */ cpu->changed |= CHANGED_GDT; diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index d6d7ac0982a..1a83910f674 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -568,8 +568,8 @@ void __exit lguest_arch_host_fini(void) int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args) { switch (args->arg0) { - case LHCALL_LOAD_GDT: - load_guest_gdt(cpu, args->arg1, args->arg2); + case LHCALL_LOAD_GDT_ENTRY: + load_guest_gdt_entry(cpu, args->arg1, args->arg2, args->arg3); break; case LHCALL_LOAD_IDT_ENTRY: load_guest_idt_entry(cpu, args->arg1, args->arg2, args->arg3); -- cgit v1.2.3 From 84a139a985300901dfad99bd93c7345d180af860 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 16 Apr 2009 21:14:04 -0300 Subject: virtio: fix suspend when using virtio_balloon Break out of wait_event_interruptible() if freezing has been requested, in the vballoon thread. Without this change vballoon refuses to stop and the system can't suspend. Signed-off-by: Marcelo Tosatti Signed-off-by: Rusty Russell Cc: stable@kernel.org --- drivers/virtio/virtio_balloon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 59268266b79..9c76a061a04 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -190,7 +190,8 @@ static int balloon(void *_vballoon) try_to_freeze(); wait_event_interruptible(vb->config_change, (diff = towards_target(vb)) != 0 - || kthread_should_stop()); + || kthread_should_stop() + || freezing(current)); if (diff > 0) fill_balloon(vb, diff); else if (diff < 0) -- cgit v1.2.3 From c0b7988200a82290287c6f4cd49585007f73175a Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 18 Apr 2009 22:17:17 +0200 Subject: Revert "console ASCII glyph 1:1 mapping" This reverts commit 1c55f18717304100a5f624c923f7cb6511b4116d. Ingo Brueckl was assuming that reverting to 1:1 mapping for chars >= 128 was not useful, but it happens to be: due to the limitations of the Linux console, when a blind user wants to read BIG5 on it, he has no other way than loading a font without SFM and let the 1:1 mapping permit the screen reader to get the BIG5 encoding. Signed-off-by: Samuel Thibault Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 2c1d133819b..08151d4de48 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2274,7 +2274,7 @@ rescan_last_byte: continue; /* nothing to display */ } /* Glyph not found */ - if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) { + if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { /* In legacy mode use the glyph we get by a 1:1 mapping. This would make absolutely no sense with Unicode in mind, but do this for ASCII characters since a font may lack -- cgit v1.2.3 From 6a7c7eaf71b636f197d73b381a2ab729ebdcfb2e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 19 Apr 2009 20:08:42 +0200 Subject: PM/Suspend: Introduce two new platform callbacks to avoid breakage Commit 900af0d973856d6feb6fc088c2d0d3fde57707d3 (PM: Change suspend code ordering) changed the ordering of suspend code in such a way that the platform .prepare() callback is now executed after the device drivers' late suspend callbacks have run. Unfortunately, this turns out to break ARM platforms that need to talk via I2C to power control devices during the .prepare() callback. For this reason introduce two new platform suspend callbacks, .prepare_late() and .wake(), that will be called just prior to disabling non-boot CPUs and right after bringing them back on line, respectively, and use them instead of .prepare() and .finish() for ACPI suspend. Make the PM core execute the .prepare() and .finish() platform suspend callbacks where they were executed previously (that is, right after calling the regular suspend methods provided by device drivers and right before executing their regular resume methods, respectively). It is not necessary to make analogous changes to the hibernation code and data structures at the moment, because they are only used by ACPI platforms. Signed-off-by: Rafael J. Wysocki Reported-by: Russell King Acked-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 779e4e500df..d060e6fd7fd 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -300,9 +300,9 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state) static struct platform_suspend_ops acpi_suspend_ops = { .valid = acpi_suspend_state_valid, .begin = acpi_suspend_begin, - .prepare = acpi_pm_prepare, + .prepare_late = acpi_pm_prepare, .enter = acpi_suspend_enter, - .finish = acpi_pm_finish, + .wake = acpi_pm_finish, .end = acpi_pm_end, }; @@ -328,9 +328,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) static struct platform_suspend_ops acpi_suspend_ops_old = { .valid = acpi_suspend_state_valid, .begin = acpi_suspend_begin_old, - .prepare = acpi_pm_disable_gpes, + .prepare_late = acpi_pm_disable_gpes, .enter = acpi_suspend_enter, - .finish = acpi_pm_finish, + .wake = acpi_pm_finish, .end = acpi_pm_end, .recover = acpi_pm_finish, }; -- cgit v1.2.3 From d9c6f546469f33f9aa48ae5991c33da8cd535b37 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 16 Apr 2009 22:57:46 +0200 Subject: drm: count reaches -1 With a postfix decrement in the test count will reach -1 rather than 0, subsequent tests fail. Signed-off-by: Roel Kluin Signed-off-by: Dave Airlie --- drivers/gpu/drm/via/via_dma.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c index 7a339dba6a6..bfb92d28326 100644 --- a/drivers/gpu/drm/via/via_dma.c +++ b/drivers/gpu/drm/via/via_dma.c @@ -481,11 +481,13 @@ static int via_wait_idle(drm_via_private_t * dev_priv) { int count = 10000000; - while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--); + while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) + ; - while (count-- && (VIA_READ(VIA_REG_STATUS) & + while (count && (VIA_READ(VIA_REG_STATUS) & (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | - VIA_3D_ENG_BUSY))) ; + VIA_3D_ENG_BUSY))) + --count; return count; } @@ -705,7 +707,7 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file * switch (d_siz->func) { case VIA_CMDBUF_SPACE: while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) - && count--) { + && --count) { if (!d_siz->wait) { break; } @@ -717,7 +719,7 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file * break; case VIA_CMDBUF_LAG: while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) - && count--) { + && --count) { if (!d_siz->wait) { break; } -- cgit v1.2.3 From 77d26dc9b9805f322f5a1f6e559b18ad66205bd9 Mon Sep 17 00:00:00 2001 From: Ma Ling Date: Thu, 16 Apr 2009 17:51:25 +0800 Subject: drm: clean dirty memory after device release In current code we register/unregister connector object by drm_sysfs_connector_add/remove function. However under some cases, we need to dynamically register or unregister device multiple times, so we have to go through register -> unregister ->register routine. Because after device_unregister function our memory is dirty, we need to do clean operation in order to re-register the device, otherwise the system will crash. The patch intends to clean device after device release. Signed-off-by: Ma Ling Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_sysfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index bc0c6849360..022876ae34f 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -132,6 +132,7 @@ void drm_sysfs_destroy(void) */ static void drm_sysfs_device_release(struct device *dev) { + memset(dev, 0, sizeof(struct device)); return; } -- cgit v1.2.3 From 6b0084266c1d4917ad9259759a1e7bd623cb3888 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 16 Apr 2009 09:00:02 +0200 Subject: drm: set/clear is_master when master changed The variable is_master is being used to track the drm_file that is currently master, so its value needs to be updated accordingly when the master is changed. Signed-off-by: Jonas Bonn Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_stub.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index d009661781b..1b3e0ff57b4 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -159,6 +159,9 @@ void drm_master_put(struct drm_master **master) int drm_setmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + if (file_priv->is_master) + return 0; + if (file_priv->minor->master && file_priv->minor->master != file_priv->master) return -EINVAL; @@ -169,6 +172,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, file_priv->minor->master != file_priv->master) { mutex_lock(&dev->struct_mutex); file_priv->minor->master = drm_master_get(file_priv->master); + file_priv->is_master = 1; mutex_unlock(&dev->struct_mutex); } @@ -178,10 +182,12 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - if (!file_priv->master) + if (!file_priv->is_master) return -EINVAL; + mutex_lock(&dev->struct_mutex); drm_master_put(&file_priv->minor->master); + file_priv->is_master = 0; mutex_unlock(&dev->struct_mutex); return 0; } -- cgit v1.2.3 From 07f1c7a7f6736d9ec2eba57d209c5f48888d841e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 20 Apr 2009 09:32:50 +1000 Subject: drm: check for minor master before allowing drop master. When fast user switching a lot eventually we get to the point, where we were checking for the wrong thing in this function. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_stub.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 1b3e0ff57b4..ef878615c49 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -185,6 +185,9 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, if (!file_priv->is_master) return -EINVAL; + if (!file_priv->minor->master) + return -EINVAL; + mutex_lock(&dev->struct_mutex); drm_master_put(&file_priv->minor->master); file_priv->is_master = 0; -- cgit v1.2.3 From 59de2bebabc5027f93df999d59cc65df591c3e6e Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 20 Apr 2009 10:08:35 +1000 Subject: agp: zero pages before sending to userspace AGP pages might be mapped into userspace finally, so the pages should be set to zero before userspace can use it. Otherwise there is potential information leakage. Signed-off-by: Shaohua Li Signed-off-by: Dave Airlie --- drivers/char/agp/generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 10d6cbd7c05..2224b762b7f 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -1226,7 +1226,7 @@ int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *m int i, ret = -ENOMEM; for (i = 0; i < num_pages; i++) { - page = alloc_page(GFP_KERNEL | GFP_DMA32); + page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); /* agp_free_memory() needs gart address */ if (page == NULL) goto out; @@ -1257,7 +1257,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) { struct page * page; - page = alloc_page(GFP_KERNEL | GFP_DMA32); + page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); if (page == NULL) return NULL; -- cgit v1.2.3 From 1f59390339f263c0fe7908fbe54466dbf3a64b58 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 20 Apr 2009 11:50:24 +1000 Subject: md: support bitmaps on RAID10 arrays larger then 2 terabytes .. and other arrays with components larger than 2 terabytes. We use a "long" rather than a "sector_t" in part of the bitmap size calculations, which is sad. Reported-by: "Mario 'BitKoenig' Holbe" Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index e4510c976b3..1fb91edc7de 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1590,7 +1590,7 @@ void bitmap_destroy(mddev_t *mddev) int bitmap_create(mddev_t *mddev) { struct bitmap *bitmap; - unsigned long blocks = mddev->resync_max_sectors; + sector_t blocks = mddev->resync_max_sectors; unsigned long chunks; unsigned long pages; struct file *file = mddev->bitmap_file; @@ -1632,8 +1632,8 @@ int bitmap_create(mddev_t *mddev) bitmap->chunkshift = ffz(~bitmap->chunksize); /* now that chunksize and chunkshift are set, we can use these macros */ - chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) / - CHUNK_BLOCK_RATIO(bitmap); + chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) >> + CHUNK_BLOCK_SHIFT(bitmap); pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO; BUG_ON(!pages); -- cgit v1.2.3 From 8a577ffc75d9194fe8cdb7479236f2081c26ca1f Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 18 Apr 2009 15:05:45 -0700 Subject: driver: dont update dev_name via device_add path notice one system /proc/iomem some entries missed the name for pci_devices it turns that dev->dev.kobj name is changed after device_add. for pci code: via acpi_pci_root_driver.ops.add (aka acpi_pci_root_add) ==> pci_acpi_scan_root is used to scan pci bus/device, and at the same time we read the resource for pci_dev in the pci_read_bases, we have res->name = pci_name(pci_dev); pci_name is calling dev_name. later via acpi_pci_root_driver.ops.start (aka acpi_pci_root_start) ==> pci_bus_add_device to add all pci_dev in kobj tree. pci_bus_add_device will call device_add. actually in device_add /* first, register with generic layer. */ error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev_name(dev)); if (error) goto Error; will get one new name for that kobj, old name is freed. [Impact: fix corrupted names in /proc/iomem ] Signed-off-by: Yinghai Lu Signed-off-by: Linus Torvalds --- drivers/base/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index d230ff4b3ee..4aa527b8a91 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -891,7 +891,8 @@ int device_add(struct device *dev) set_dev_node(dev, dev_to_node(parent)); /* first, register with generic layer. */ - error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev_name(dev)); + /* we require the name to be set before, and pass NULL */ + error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); if (error) goto Error; -- cgit v1.2.3 From 7400516ab40d8fe55031dc8d614e2b365bd95f1c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 21 Apr 2009 21:47:22 +0200 Subject: go7007: Convert to the new i2c device binding model Move the go7007 driver away from the legacy i2c binding model, which is going away really soon now. The I2C addresses of the audio and video chips in s2250-board didn't look quite right, apparently they were left-aligned values when Linux wants right-aligned values, so I fixed them too. Signed-off-by: Jean Delvare Cc: Greg Kroah-Hartman --- drivers/staging/go7007/go7007-driver.c | 11 ++++- drivers/staging/go7007/go7007-i2c.c | 83 --------------------------------- drivers/staging/go7007/go7007-priv.h | 1 + drivers/staging/go7007/go7007-usb.c | 14 ++++-- drivers/staging/go7007/s2250-board.c | 71 ++++++++++++---------------- drivers/staging/go7007/wis-i2c.h | 9 ---- drivers/staging/go7007/wis-ov7640.c | 56 +++++++--------------- drivers/staging/go7007/wis-saa7113.c | 60 ++++++++---------------- drivers/staging/go7007/wis-saa7115.c | 60 ++++++++---------------- drivers/staging/go7007/wis-sony-tuner.c | 60 +++++++----------------- drivers/staging/go7007/wis-tw2804.c | 57 +++++++--------------- drivers/staging/go7007/wis-tw9903.c | 60 ++++++++---------------- drivers/staging/go7007/wis-uda1342.c | 52 ++++++--------------- 13 files changed, 176 insertions(+), 418 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c index f47c0ce2849..77b1e769ac9 100644 --- a/drivers/staging/go7007/go7007-driver.c +++ b/drivers/staging/go7007/go7007-driver.c @@ -191,8 +191,10 @@ int go7007_reset_encoder(struct go7007 *go) /* * Attempt to instantiate an I2C client by ID, probably loading a module. */ -static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr) +static int init_i2c_module(struct i2c_adapter *adapter, const char *type, + int id, int addr) { + struct i2c_board_info info; char *modname; switch (id) { @@ -226,7 +228,11 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr) } if (modname != NULL) request_module(modname); - if (wis_i2c_probe_device(adapter, id, addr) == 1) + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = addr; + strlcpy(info.type, type, I2C_NAME_SIZE); + if (!i2c_new_device(adapter, &info)) return 0; if (modname != NULL) printk(KERN_INFO @@ -266,6 +272,7 @@ int go7007_register_encoder(struct go7007 *go) if (go->i2c_adapter_online) { for (i = 0; i < go->board_info->num_i2c_devs; ++i) init_i2c_module(&go->i2c_adapter, + go->board_info->i2c_devs[i].type, go->board_info->i2c_devs[i].id, go->board_info->i2c_devs[i].addr); if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) diff --git a/drivers/staging/go7007/go7007-i2c.c b/drivers/staging/go7007/go7007-i2c.c index cd55b76eabc..c82867fdd28 100644 --- a/drivers/staging/go7007/go7007-i2c.c +++ b/drivers/staging/go7007/go7007-i2c.c @@ -31,87 +31,6 @@ #include "go7007-priv.h" #include "wis-i2c.h" -/************** Registration interface for I2C client drivers **************/ - -/* Since there's no way to auto-probe the I2C devices connected to the I2C - * bus on the go7007, we have this silly little registration system that - * client drivers can use to register their I2C driver ID and their - * detect_client function (the one that's normally passed to i2c_probe). - * - * When a new go7007 device is connected, we can look up in a board info - * table by the USB or PCI vendor/product/revision ID to determine - * which I2C client module to load. The client driver module will register - * itself here, and then we can call the registered detect_client function - * to force-load a new client at the address listed in the board info table. - * - * Really the I2C subsystem should have a way to force-load I2C client - * drivers when we have a priori knowledge of what's on the bus, especially - * since the existing I2C auto-probe mechanism is so hokey, but we'll use - * our own mechanism for the time being. */ - -struct wis_i2c_client_driver { - unsigned int id; - found_proc found_proc; - struct list_head list; -}; - -static LIST_HEAD(i2c_client_drivers); -static DECLARE_MUTEX(i2c_client_driver_list_lock); - -/* Client drivers register here by their I2C driver ID */ -int wis_i2c_add_driver(unsigned int id, found_proc found_proc) -{ - struct wis_i2c_client_driver *driver; - - driver = kmalloc(sizeof(struct wis_i2c_client_driver), GFP_KERNEL); - if (driver == NULL) - return -ENOMEM; - driver->id = id; - driver->found_proc = found_proc; - - down(&i2c_client_driver_list_lock); - list_add_tail(&driver->list, &i2c_client_drivers); - up(&i2c_client_driver_list_lock); - - return 0; -} -EXPORT_SYMBOL(wis_i2c_add_driver); - -void wis_i2c_del_driver(found_proc found_proc) -{ - struct wis_i2c_client_driver *driver, *next; - - down(&i2c_client_driver_list_lock); - list_for_each_entry_safe(driver, next, &i2c_client_drivers, list) - if (driver->found_proc == found_proc) { - list_del(&driver->list); - kfree(driver); - } - up(&i2c_client_driver_list_lock); -} -EXPORT_SYMBOL(wis_i2c_del_driver); - -/* The main go7007 driver calls this to instantiate a client by driver - * ID and bus address, which are both stored in the board info table */ -int wis_i2c_probe_device(struct i2c_adapter *adapter, - unsigned int id, int addr) -{ - struct wis_i2c_client_driver *driver; - int found = 0; - - if (addr < 0 || addr > 0x7f) - return -1; - down(&i2c_client_driver_list_lock); - list_for_each_entry(driver, &i2c_client_drivers, list) - if (driver->id == id) { - if (driver->found_proc(adapter, addr, 0) == 0) - found = 1; - break; - } - up(&i2c_client_driver_list_lock); - return found; -} - /********************* Driver for on-board I2C adapter *********************/ /* #define GO7007_I2C_DEBUG */ @@ -287,9 +206,7 @@ static struct i2c_algorithm go7007_algo = { static struct i2c_adapter go7007_adap_templ = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, .name = "WIS GO7007SB", - .id = I2C_ALGO_GO7007, .algo = &go7007_algo, }; diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h index 372f1f1c09b..178d18119fa 100644 --- a/drivers/staging/go7007/go7007-priv.h +++ b/drivers/staging/go7007/go7007-priv.h @@ -87,6 +87,7 @@ struct go7007_board_info { int audio_main_div; int num_i2c_devs; struct { + const char *type; int id; int addr; } i2c_devs[4]; diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c index 83eec920c7d..aa4a9e0b995 100644 --- a/drivers/staging/go7007/go7007-usb.c +++ b/drivers/staging/go7007/go7007-usb.c @@ -91,6 +91,7 @@ static struct go7007_usb_board board_matrix_ii = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "wis_saa7115", .id = I2C_DRIVERID_WIS_SAA7115, .addr = 0x20, }, @@ -127,6 +128,7 @@ static struct go7007_usb_board board_matrix_reload = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "wis_saa7113", .id = I2C_DRIVERID_WIS_SAA7113, .addr = 0x25, }, @@ -164,6 +166,7 @@ static struct go7007_usb_board board_star_trek = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "wis_saa7115", .id = I2C_DRIVERID_WIS_SAA7115, .addr = 0x20, }, @@ -209,14 +212,17 @@ static struct go7007_usb_board board_px_tv402u = { .num_i2c_devs = 3, .i2c_devs = { { + .type = "wis_saa7115", .id = I2C_DRIVERID_WIS_SAA7115, .addr = 0x20, }, { + .type = "wis_uda1342", .id = I2C_DRIVERID_WIS_UDA1342, .addr = 0x1a, }, { + .type = "wis_sony_tuner", .id = I2C_DRIVERID_WIS_SONY_TUNER, .addr = 0x60, }, @@ -264,6 +270,7 @@ static struct go7007_usb_board board_xmen = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "wis_ov7640", .id = I2C_DRIVERID_WIS_OV7640, .addr = 0x21, }, @@ -296,6 +303,7 @@ static struct go7007_usb_board board_matrix_revolution = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "wis_tw9903", .id = I2C_DRIVERID_WIS_TW9903, .addr = 0x44, }, @@ -385,6 +393,7 @@ static struct go7007_usb_board board_adlink_mpg24 = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "wis_twTW2804", .id = I2C_DRIVERID_WIS_TW2804, .addr = 0x00, /* yes, really */ }, @@ -415,8 +424,9 @@ static struct go7007_usb_board board_sensoray_2250 = { .num_i2c_devs = 1, .i2c_devs = { { + .type = "s2250_board", .id = I2C_DRIVERID_S2250, - .addr = 0x34, + .addr = 0x43, }, }, .num_inputs = 2, @@ -943,9 +953,7 @@ static struct i2c_algorithm go7007_usb_algo = { static struct i2c_adapter go7007_usb_adap_templ = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, .name = "WIS GO7007SB EZ-USB", - .id = I2C_ALGO_GO7007_USB, .algo = &go7007_usb_algo, }; diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index d333ea2cd77..1706fbf0684 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c @@ -28,7 +28,6 @@ extern int s2250loader_init(void); extern void s2250loader_cleanup(void); #define TLV320_ADDRESS 0x34 -#define S2250_VIDDEC 0x86 #define VPX322_ADDR_ANALOGCONTROL1 0x02 #define VPX322_ADDR_BRIGHTNESS0 0x0127 #define VPX322_ADDR_BRIGHTNESS1 0x0131 @@ -123,6 +122,7 @@ struct s2250 { int hue; int reg12b_val; int audio_input; + struct i2c_client *audio; }; /* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ @@ -452,16 +452,15 @@ static int s2250_command(struct i2c_client *client, { struct v4l2_audio *audio = arg; - client->addr = TLV320_ADDRESS; switch (audio->index) { case 0: - write_reg(client, 0x08, 0x02); /* Line In */ + write_reg(dec->audio, 0x08, 0x02); /* Line In */ break; case 1: - write_reg(client, 0x08, 0x04); /* Mic */ + write_reg(dec->audio, 0x08, 0x04); /* Mic */ break; case 2: - write_reg(client, 0x08, 0x05); /* Mic Boost */ + write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */ break; default: return -EINVAL; @@ -477,31 +476,23 @@ static int s2250_command(struct i2c_client *client, return 0; } -static struct i2c_driver s2250_driver; - -static struct i2c_client s2250_client_templ = { - .name = "Sensoray 2250", - .driver = &s2250_driver, -}; - -static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind) +static int s2250_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_client *audio; + struct i2c_adapter *adapter = client->adapter; struct s2250 *dec; u8 *data; struct go7007 *go = i2c_get_adapdata(adapter); struct go7007_usb *usb = go->hpi_context; - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) + audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1); + if (audio == NULL) return -ENOMEM; - memcpy(client, &s2250_client_templ, - sizeof(s2250_client_templ)); - client->adapter = adapter; dec = kmalloc(sizeof(struct s2250), GFP_KERNEL); if (dec == NULL) { - kfree(client); + i2c_unregister_device(audio); return -ENOMEM; } @@ -510,7 +501,7 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind) dec->contrast = 50; dec->saturation = 50; dec->hue = 0; - client->addr = TLV320_ADDRESS; + dec->audio = audio; i2c_set_clientdata(client, dec); printk(KERN_DEBUG @@ -518,28 +509,25 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind) adapter->name); /* initialize the audio */ - client->addr = TLV320_ADDRESS; - if (write_regs(client, aud_regs) < 0) { + if (write_regs(audio, aud_regs) < 0) { printk(KERN_ERR "s2250: error initializing audio\n"); - kfree(client); + i2c_unregister_device(audio); kfree(dec); return 0; } - client->addr = S2250_VIDDEC; - i2c_set_clientdata(client, dec); if (write_regs(client, vid_regs) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); - kfree(client); + i2c_unregister_device(audio); kfree(dec); return 0; } if (write_regs_fp(client, vid_regs_fp) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); - kfree(client); + i2c_unregister_device(audio); kfree(dec); return 0; } @@ -575,32 +563,33 @@ static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind) up(&usb->i2c_lock); } - i2c_attach_client(client); printk("s2250: initialized successfully\n"); return 0; } -static int s2250_detach(struct i2c_client *client) +static int s2250_remove(struct i2c_client *client) { struct s2250 *dec = i2c_get_clientdata(client); - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - kfree(client); + i2c_set_clientdata(client, NULL); + i2c_unregister_device(dec->audio); kfree(dec); return 0; } +static struct i2c_device_id s2250_id[] = { + { "s2250_board", 0 }, + { } +}; + static struct i2c_driver s2250_driver = { .driver = { .name = "Sensoray 2250 board driver", }, - .id = I2C_DRIVERID_S2250, - .detach_client = s2250_detach, + .probe = s2250_probe, + .remove = s2250_remove, .command = s2250_command, + .id_table = s2250_id, }; static int __init s2250_init(void) @@ -613,13 +602,13 @@ static int __init s2250_init(void) r = i2c_add_driver(&s2250_driver); if (r < 0) - return r; - return wis_i2c_add_driver(s2250_driver.id, s2250_detect); + s2250loader_cleanup(); + + return r; } static void __exit s2250_cleanup(void) { - wis_i2c_del_driver(s2250_detect); i2c_del_driver(&s2250_driver); s2250loader_cleanup(); diff --git a/drivers/staging/go7007/wis-i2c.h b/drivers/staging/go7007/wis-i2c.h index 431f41dd396..3c2b9be455d 100644 --- a/drivers/staging/go7007/wis-i2c.h +++ b/drivers/staging/go7007/wis-i2c.h @@ -24,21 +24,12 @@ #define I2C_DRIVERID_WIS_OV7640 0xf0f5 #define I2C_DRIVERID_WIS_TW2804 0xf0f6 #define I2C_DRIVERID_S2250 0xf0f7 -#define I2C_ALGO_GO7007 0xf00000 -#define I2C_ALGO_GO7007_USB 0xf10000 /* Flag to indicate that the client needs to be accessed with SCCB semantics */ /* We re-use the I2C_M_TEN value so the flag passes through the masks in the * core I2C code. Major kludge, but the I2C layer ain't exactly flexible. */ #define I2C_CLIENT_SCCB 0x10 -typedef int (*found_proc) (struct i2c_adapter *, int, int); -int wis_i2c_add_driver(unsigned int id, found_proc found_proc); -void wis_i2c_del_driver(found_proc found_proc); - -int wis_i2c_probe_device(struct i2c_adapter *adapter, - unsigned int id, int addr); - /* Definitions for new video decoder commands */ struct video_decoder_resolution { diff --git a/drivers/staging/go7007/wis-ov7640.c b/drivers/staging/go7007/wis-ov7640.c index 2f9efca0460..04d6d3a498a 100644 --- a/drivers/staging/go7007/wis-ov7640.c +++ b/drivers/staging/go7007/wis-ov7640.c @@ -50,76 +50,54 @@ static int write_regs(struct i2c_client *client, u8 *regs) return 0; } -static struct i2c_driver wis_ov7640_driver; - -static struct i2c_client wis_ov7640_client_templ = { - .name = "OV7640 (WIS)", - .driver = &wis_ov7640_driver, -}; - -static int wis_ov7640_detect(struct i2c_adapter *adapter, int addr, int kind) +static int wis_ov7640_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_ov7640_client_templ, - sizeof(wis_ov7640_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; + client->flags = I2C_CLIENT_SCCB; printk(KERN_DEBUG "wis-ov7640: initializing OV7640 at address %d on %s\n", - addr, adapter->name); + client->addr, adapter->name); if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-ov7640: error initializing OV7640\n"); - kfree(client); - return 0; + return -ENODEV; } - i2c_attach_client(client); return 0; } -static int wis_ov7640_detach(struct i2c_client *client) +static int wis_ov7640_remove(struct i2c_client *client) { - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - - kfree(client); return 0; } +static struct i2c_device_id wis_ov7640_id[] = { + { "wis_ov7640", 0 }, + { } +}; + static struct i2c_driver wis_ov7640_driver = { .driver = { .name = "WIS OV7640 I2C driver", }, - .id = I2C_DRIVERID_WIS_OV7640, - .detach_client = wis_ov7640_detach, + .probe = wis_ov7640_probe, + .remove = wis_ov7640_remove, + .id_table = wis_ov7640_id, }; static int __init wis_ov7640_init(void) { - int r; - - r = i2c_add_driver(&wis_ov7640_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_ov7640_driver.id, wis_ov7640_detect); + return i2c_add_driver(&wis_ov7640_driver); } static void __exit wis_ov7640_cleanup(void) { - wis_i2c_del_driver(wis_ov7640_detect); i2c_del_driver(&wis_ov7640_driver); } diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c index 11689723945..9ab893bd204 100644 --- a/drivers/staging/go7007/wis-saa7113.c +++ b/drivers/staging/go7007/wis-saa7113.c @@ -261,34 +261,19 @@ static int wis_saa7113_command(struct i2c_client *client, return 0; } -static struct i2c_driver wis_saa7113_driver; - -static struct i2c_client wis_saa7113_client_templ = { - .name = "SAA7113 (WIS)", - .driver = &wis_saa7113_driver, -}; - -static int wis_saa7113_detect(struct i2c_adapter *adapter, int addr, int kind) +static int wis_saa7113_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; struct wis_saa7113 *dec; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_saa7113_client_templ, - sizeof(wis_saa7113_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL); - if (dec == NULL) { - kfree(client); + if (dec == NULL) return -ENOMEM; - } + dec->norm = V4L2_STD_NTSC; dec->brightness = 128; dec->contrast = 71; @@ -298,56 +283,49 @@ static int wis_saa7113_detect(struct i2c_adapter *adapter, int addr, int kind) printk(KERN_DEBUG "wis-saa7113: initializing SAA7113 at address %d on %s\n", - addr, adapter->name); + client->addr, adapter->name); if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-saa7113: error initializing SAA7113\n"); - kfree(client); kfree(dec); - return 0; + return -ENODEV; } - i2c_attach_client(client); return 0; } -static int wis_saa7113_detach(struct i2c_client *client) +static int wis_saa7113_remove(struct i2c_client *client) { struct wis_saa7113 *dec = i2c_get_clientdata(client); - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - kfree(client); + i2c_set_clientdata(client, NULL); kfree(dec); return 0; } +static struct i2c_device_id wis_saa7113_id[] = { + { "wis_saa7113", 0 }, + { } +}; + static struct i2c_driver wis_saa7113_driver = { .driver = { .name = "WIS SAA7113 I2C driver", }, - .id = I2C_DRIVERID_WIS_SAA7113, - .detach_client = wis_saa7113_detach, + .probe = wis_saa7113_probe, + .remove = wis_saa7113_remove, .command = wis_saa7113_command, + .id_table = wis_saa7113_id, }; static int __init wis_saa7113_init(void) { - int r; - - r = i2c_add_driver(&wis_saa7113_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_saa7113_driver.id, wis_saa7113_detect); + return i2c_add_driver(&wis_saa7113_driver); } static void __exit wis_saa7113_cleanup(void) { - wis_i2c_del_driver(wis_saa7113_detect); i2c_del_driver(&wis_saa7113_driver); } diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c index 59417a7174d..8687ad2de76 100644 --- a/drivers/staging/go7007/wis-saa7115.c +++ b/drivers/staging/go7007/wis-saa7115.c @@ -394,34 +394,19 @@ static int wis_saa7115_command(struct i2c_client *client, return 0; } -static struct i2c_driver wis_saa7115_driver; - -static struct i2c_client wis_saa7115_client_templ = { - .name = "SAA7115 (WIS)", - .driver = &wis_saa7115_driver, -}; - -static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind) +static int wis_saa7115_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; struct wis_saa7115 *dec; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_saa7115_client_templ, - sizeof(wis_saa7115_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL); - if (dec == NULL) { - kfree(client); + if (dec == NULL) return -ENOMEM; - } + dec->norm = V4L2_STD_NTSC; dec->brightness = 128; dec->contrast = 64; @@ -431,56 +416,49 @@ static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind) printk(KERN_DEBUG "wis-saa7115: initializing SAA7115 at address %d on %s\n", - addr, adapter->name); + client->addr, adapter->name); if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-saa7115: error initializing SAA7115\n"); - kfree(client); kfree(dec); - return 0; + return -ENODEV; } - i2c_attach_client(client); return 0; } -static int wis_saa7115_detach(struct i2c_client *client) +static int wis_saa7115_remove(struct i2c_client *client) { struct wis_saa7115 *dec = i2c_get_clientdata(client); - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - kfree(client); + i2c_set_clientdata(client, NULL); kfree(dec); return 0; } +static struct i2c_device_id wis_saa7115_id[] = { + { "wis_saa7115", 0 }, + { } +}; + static struct i2c_driver wis_saa7115_driver = { .driver = { .name = "WIS SAA7115 I2C driver", }, - .id = I2C_DRIVERID_WIS_SAA7115, - .detach_client = wis_saa7115_detach, + .probe = wis_saa7115_probe, + .remove = wis_saa7115_remove, .command = wis_saa7115_command, + .id_table = wis_saa7115_id, }; static int __init wis_saa7115_init(void) { - int r; - - r = i2c_add_driver(&wis_saa7115_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_saa7115_driver.id, wis_saa7115_detect); + return i2c_add_driver(&wis_saa7115_driver); } static void __exit wis_saa7115_cleanup(void) { - wis_i2c_del_driver(wis_saa7115_detect); i2c_del_driver(&wis_saa7115_driver); } diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c index 0a7eeef7c00..c965c601ac9 100644 --- a/drivers/staging/go7007/wis-sony-tuner.c +++ b/drivers/staging/go7007/wis-sony-tuner.c @@ -653,35 +653,19 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -static struct i2c_driver wis_sony_tuner_driver; - -static struct i2c_client wis_sony_tuner_client_templ = { - .name = "Sony TV Tuner (WIS)", - .driver = &wis_sony_tuner_driver, -}; - -static int wis_sony_tuner_detect(struct i2c_adapter *adapter, - int addr, int kind) +static int wis_sony_tuner_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; struct wis_sony_tuner *t; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_sony_tuner_client_templ, - sizeof(wis_sony_tuner_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL); - if (t == NULL) { - kfree(client); + if (t == NULL) return -ENOMEM; - } + t->type = -1; t->freq = 0; t->mpxmode = 0; @@ -690,50 +674,42 @@ static int wis_sony_tuner_detect(struct i2c_adapter *adapter, printk(KERN_DEBUG "wis-sony-tuner: initializing tuner at address %d on %s\n", - addr, adapter->name); - - i2c_attach_client(client); + client->addr, adapter->name); return 0; } -static int wis_sony_tuner_detach(struct i2c_client *client) +static int wis_sony_tuner_remove(struct i2c_client *client) { struct wis_sony_tuner *t = i2c_get_clientdata(client); - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; + i2c_set_clientdata(client, NULL); kfree(t); - kfree(client); return 0; } +static struct i2c_device_id wis_sony_tuner_id[] = { + { "wis_sony_tuner", 0 }, + { } +}; + static struct i2c_driver wis_sony_tuner_driver = { .driver = { .name = "WIS Sony TV Tuner I2C driver", }, - .id = I2C_DRIVERID_WIS_SONY_TUNER, - .detach_client = wis_sony_tuner_detach, + .probe = wis_sony_tuner_probe, + .remove = wis_sony_tuner_remove, .command = tuner_command, + .id_table = wis_sony_tuner_id, }; static int __init wis_sony_tuner_init(void) { - int r; - - r = i2c_add_driver(&wis_sony_tuner_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_sony_tuner_driver.id, - wis_sony_tuner_detect); + return i2c_add_driver(&wis_sony_tuner_driver); } static void __exit wis_sony_tuner_cleanup(void) { - wis_i2c_del_driver(wis_sony_tuner_detect); i2c_del_driver(&wis_sony_tuner_driver); } diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c index 57b8f2b1caa..e15794a2a0a 100644 --- a/drivers/staging/go7007/wis-tw2804.c +++ b/drivers/staging/go7007/wis-tw2804.c @@ -291,34 +291,19 @@ static int wis_tw2804_command(struct i2c_client *client, return 0; } -static struct i2c_driver wis_tw2804_driver; - -static struct i2c_client wis_tw2804_client_templ = { - .name = "TW2804 (WIS)", - .driver = &wis_tw2804_driver, -}; - -static int wis_tw2804_detect(struct i2c_adapter *adapter, int addr, int kind) +static int wis_tw2804_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; struct wis_tw2804 *dec; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_tw2804_client_templ, - sizeof(wis_tw2804_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL); - if (dec == NULL) { - kfree(client); + if (dec == NULL) return -ENOMEM; - } + dec->channel = -1; dec->norm = V4L2_STD_NTSC; dec->brightness = 128; @@ -328,48 +313,42 @@ static int wis_tw2804_detect(struct i2c_adapter *adapter, int addr, int kind) i2c_set_clientdata(client, dec); printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n", - addr, adapter->name); + client->addr, adapter->name); - i2c_attach_client(client); return 0; } -static int wis_tw2804_detach(struct i2c_client *client) +static int wis_tw2804_remove(struct i2c_client *client) { struct wis_tw2804 *dec = i2c_get_clientdata(client); - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - kfree(client); + i2c_set_clientdata(client, NULL); kfree(dec); return 0; } +static struct i2c_device_id wis_tw2804_id[] = { + { "wis_tw2804", 0 }, + { } +}; + static struct i2c_driver wis_tw2804_driver = { .driver = { .name = "WIS TW2804 I2C driver", }, - .id = I2C_DRIVERID_WIS_TW2804, - .detach_client = wis_tw2804_detach, + .probe = wis_tw2804_probe, + .remove = wis_tw2804_remove, .command = wis_tw2804_command, + .id_table = wis_tw2804_id, }; static int __init wis_tw2804_init(void) { - int r; - - r = i2c_add_driver(&wis_tw2804_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_tw2804_driver.id, wis_tw2804_detect); + return i2c_add_driver(&wis_tw2804_driver); } static void __exit wis_tw2804_cleanup(void) { - wis_i2c_del_driver(wis_tw2804_detect); i2c_del_driver(&wis_tw2804_driver); } diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c index 40627b282cb..6c3427bb6f4 100644 --- a/drivers/staging/go7007/wis-tw9903.c +++ b/drivers/staging/go7007/wis-tw9903.c @@ -267,34 +267,19 @@ static int wis_tw9903_command(struct i2c_client *client, return 0; } -static struct i2c_driver wis_tw9903_driver; - -static struct i2c_client wis_tw9903_client_templ = { - .name = "TW9903 (WIS)", - .driver = &wis_tw9903_driver, -}; - -static int wis_tw9903_detect(struct i2c_adapter *adapter, int addr, int kind) +static int wis_tw9903_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; struct wis_tw9903 *dec; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_tw9903_client_templ, - sizeof(wis_tw9903_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; dec = kmalloc(sizeof(struct wis_tw9903), GFP_KERNEL); - if (dec == NULL) { - kfree(client); + if (dec == NULL) return -ENOMEM; - } + dec->norm = V4L2_STD_NTSC; dec->brightness = 0; dec->contrast = 0x60; @@ -303,55 +288,48 @@ static int wis_tw9903_detect(struct i2c_adapter *adapter, int addr, int kind) printk(KERN_DEBUG "wis-tw9903: initializing TW9903 at address %d on %s\n", - addr, adapter->name); + client->addr, adapter->name); if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-tw9903: error initializing TW9903\n"); - kfree(client); kfree(dec); - return 0; + return -ENODEV; } - i2c_attach_client(client); return 0; } -static int wis_tw9903_detach(struct i2c_client *client) +static int wis_tw9903_remove(struct i2c_client *client) { struct wis_tw9903 *dec = i2c_get_clientdata(client); - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - kfree(client); + i2c_set_clientdata(client, NULL); kfree(dec); return 0; } +static struct i2c_device_id wis_tw9903_id[] = { + { "wis_tw9903", 0 }, + { } +}; + static struct i2c_driver wis_tw9903_driver = { .driver = { .name = "WIS TW9903 I2C driver", }, - .id = I2C_DRIVERID_WIS_TW9903, - .detach_client = wis_tw9903_detach, + .probe = wis_tw9903_probe, + .remove = wis_tw9903_remove, .command = wis_tw9903_command, + .id_table = wis_tw9903_id, }; static int __init wis_tw9903_init(void) { - int r; - - r = i2c_add_driver(&wis_tw9903_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_tw9903_driver.id, wis_tw9903_detect); + return i2c_add_driver(&wis_tw9903_driver); } static void __exit wis_tw9903_cleanup(void) { - wis_i2c_del_driver(wis_tw9903_detect); i2c_del_driver(&wis_tw9903_driver); } diff --git a/drivers/staging/go7007/wis-uda1342.c b/drivers/staging/go7007/wis-uda1342.c index 555645c0cc1..739c7ae8913 100644 --- a/drivers/staging/go7007/wis-uda1342.c +++ b/drivers/staging/go7007/wis-uda1342.c @@ -59,73 +59,51 @@ static int wis_uda1342_command(struct i2c_client *client, return 0; } -static struct i2c_driver wis_uda1342_driver; - -static struct i2c_client wis_uda1342_client_templ = { - .name = "UDA1342 (WIS)", - .driver = &wis_uda1342_driver, -}; - -static int wis_uda1342_detect(struct i2c_adapter *adapter, int addr, int kind) +static int wis_uda1342_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) - return 0; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &wis_uda1342_client_templ, - sizeof(wis_uda1342_client_templ)); - client->adapter = adapter; - client->addr = addr; + return -ENODEV; printk(KERN_DEBUG "wis-uda1342: initializing UDA1342 at address %d on %s\n", - addr, adapter->name); + client->addr, adapter->name); write_reg(client, 0x00, 0x8000); /* reset registers */ write_reg(client, 0x00, 0x1241); /* select input 1 */ - i2c_attach_client(client); return 0; } -static int wis_uda1342_detach(struct i2c_client *client) +static int wis_uda1342_remove(struct i2c_client *client) { - int r; - - r = i2c_detach_client(client); - if (r < 0) - return r; - - kfree(client); return 0; } +static struct i2c_device_id wis_uda1342_id[] = { + { "wis_uda1342", 0 }, + { } +}; + static struct i2c_driver wis_uda1342_driver = { .driver = { .name = "WIS UDA1342 I2C driver", }, - .id = I2C_DRIVERID_WIS_UDA1342, - .detach_client = wis_uda1342_detach, + .probe = wis_uda1342_probe, + .remove = wis_uda1342_remove, .command = wis_uda1342_command, + .id_table = wis_uda1342_id, }; static int __init wis_uda1342_init(void) { - int r; - - r = i2c_add_driver(&wis_uda1342_driver); - if (r < 0) - return r; - return wis_i2c_add_driver(wis_uda1342_driver.id, wis_uda1342_detect); + return i2c_add_driver(&wis_uda1342_driver); } static void __exit wis_uda1342_cleanup(void) { - wis_i2c_del_driver(wis_uda1342_detect); i2c_del_driver(&wis_uda1342_driver); } -- cgit v1.2.3 From 44aa417910ec9cda6da42be914105e789273b507 Mon Sep 17 00:00:00 2001 From: Vlada Peric Date: Tue, 21 Apr 2009 12:23:59 -0700 Subject: asiliantfb: add missing return statement Commit 032220ba (asiliantfb: fix cmap memory leaks) changed the function init_asiliant from void to int, resulting in the following compile warning: drivers/video/asiliantfb.c: In function `init_asiliant': drivers/video/asiliantfb.c:536: warning: control reaches end of non-void function Fix the warning by returning 0. Signed-off-by: Vlada Peric Cc: Andres Salomon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/asiliantfb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 1a1f946d8fe..9fe90ce928f 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -533,6 +533,7 @@ static int __devinit init_asiliant(struct fb_info *p, unsigned long addr) writeb(0xff, mmio_base + 0x78c); chips_hw_init(p); + return 0; } static int __devinit -- cgit v1.2.3 From ff14ed5db6e7e5e5dc23712d3c877891d4d9a1a8 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Tue, 21 Apr 2009 12:23:59 -0700 Subject: pxafb: lcsr1 is unused without CONFIG_FB_PXA_OVERLAY Fixes the warning: drivers/video/pxafb.c: In function 'pxafb_handle_irq': drivers/video/pxafb.c:1442: warning: unused variable 'lcsr1' [akpm@linux-foundation.org: save an ifdef] Signed-off-by: Denis V. Lunev Cc: Eric Miao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pxafb.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 84f63205c46..0889d50c328 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1439,7 +1439,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) static irqreturn_t pxafb_handle_irq(int irq, void *dev_id) { struct pxafb_info *fbi = dev_id; - unsigned int lccr0, lcsr, lcsr1; + unsigned int lccr0, lcsr; lcsr = lcd_readl(fbi, LCSR); if (lcsr & LCSR_LDD) { @@ -1455,14 +1455,16 @@ static irqreturn_t pxafb_handle_irq(int irq, void *dev_id) lcd_writel(fbi, LCSR, lcsr); #ifdef CONFIG_FB_PXA_OVERLAY - lcsr1 = lcd_readl(fbi, LCSR1); - if (lcsr1 & LCSR1_BS(1)) - complete(&fbi->overlay[0].branch_done); + { + unsigned int lcsr1 = lcd_readl(fbi, LCSR1); + if (lcsr1 & LCSR1_BS(1)) + complete(&fbi->overlay[0].branch_done); - if (lcsr1 & LCSR1_BS(2)) - complete(&fbi->overlay[1].branch_done); + if (lcsr1 & LCSR1_BS(2)) + complete(&fbi->overlay[1].branch_done); - lcd_writel(fbi, LCSR1, lcsr1); + lcd_writel(fbi, LCSR1, lcsr1); + } #endif return IRQ_HANDLED; } -- cgit v1.2.3 From 8e19608e8b5c001e4a66ce482edc474f05fb7355 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 21 Apr 2009 12:24:00 -0700 Subject: clocksource: pass clocksource to read() callback Pass clocksource pointer to the read() callback for clocksources. This allows us to share the callback between multiple instances. [hugh@veritas.com: fix powerpc build of clocksource pass clocksource mods] [akpm@linux-foundation.org: cleanup] Signed-off-by: Magnus Damm Acked-by: John Stultz Cc: Thomas Gleixner Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hpet.c | 2 +- drivers/clocksource/acpi_pm.c | 12 ++++++------ drivers/clocksource/cyclone.c | 2 +- drivers/clocksource/scx200_hrt.c | 2 +- drivers/clocksource/tcb_clksrc.c | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 50dfa3bc71c..340ba4f9dc5 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -72,7 +72,7 @@ static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; #ifdef CONFIG_IA64 static void __iomem *hpet_mctr; -static cycle_t read_hpet(void) +static cycle_t read_hpet(struct clocksource *cs) { return (cycle_t)read_counter((void __iomem *)hpet_mctr); } diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index ee19b6e8fcb..40bd8c61c7d 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -57,7 +57,7 @@ u32 acpi_pm_read_verified(void) return v2; } -static cycle_t acpi_pm_read(void) +static cycle_t acpi_pm_read(struct clocksource *cs) { return (cycle_t)read_pmtmr(); } @@ -83,7 +83,7 @@ static int __init acpi_pm_good_setup(char *__str) } __setup("acpi_pm_good", acpi_pm_good_setup); -static cycle_t acpi_pm_read_slow(void) +static cycle_t acpi_pm_read_slow(struct clocksource *cs) { return (cycle_t)acpi_pm_read_verified(); } @@ -156,9 +156,9 @@ static int verify_pmtmr_rate(void) unsigned long count, delta; mach_prepare_counter(); - value1 = clocksource_acpi_pm.read(); + value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm); mach_countup(&count); - value2 = clocksource_acpi_pm.read(); + value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm); delta = (value2 - value1) & ACPI_PM_MASK; /* Check that the PMTMR delta is within 5% of what we expect */ @@ -195,9 +195,9 @@ static int __init init_acpi_pm_clocksource(void) /* "verify" this timing source: */ for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) { udelay(100 * j); - value1 = clocksource_acpi_pm.read(); + value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm); for (i = 0; i < ACPI_PM_READ_CHECKS; i++) { - value2 = clocksource_acpi_pm.read(); + value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm); if (value2 == value1) continue; if (value2 > value1) diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c index 8615059a872..64e528e8bfa 100644 --- a/drivers/clocksource/cyclone.c +++ b/drivers/clocksource/cyclone.c @@ -19,7 +19,7 @@ int use_cyclone = 0; static void __iomem *cyclone_ptr; -static cycle_t read_cyclone(void) +static cycle_t read_cyclone(struct clocksource *cs) { return (cycle_t)readl(cyclone_ptr); } diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c index b92da677aa5..27f4d9637b6 100644 --- a/drivers/clocksource/scx200_hrt.c +++ b/drivers/clocksource/scx200_hrt.c @@ -43,7 +43,7 @@ MODULE_PARM_DESC(ppm, "+-adjust to actual XO freq (ppm)"); /* The base timer frequency, * 27 if selected */ #define HRT_FREQ 1000000 -static cycle_t read_hrt(void) +static cycle_t read_hrt(struct clocksource *cs) { /* Read the timer value */ return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET); diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 254f1064d97..01b886e6882 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -39,7 +39,7 @@ static void __iomem *tcaddr; -static cycle_t tc_get_cycles(void) +static cycle_t tc_get_cycles(struct clocksource *cs) { unsigned long flags; u32 lower, upper; -- cgit v1.2.3 From 8b32b5d0dca2f5ab632e8bedcd57fe4c109c13fe Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 21 Apr 2009 12:24:02 -0700 Subject: ipmi: fix platform return check The wrong return value is being tested when allocating a platform device in the IPMI SI code. Check the right value. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e58ea4cd55c..2438fdf889b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2863,7 +2863,7 @@ static int try_smi_init(struct smi_info *new_smi) */ new_smi->pdev = platform_device_alloc("ipmi_si", new_smi->intf_num); - if (rv) { + if (!new_smi->pdev) { printk(KERN_ERR "ipmi_si_intf:" " Unable to allocate platform device\n"); -- cgit v1.2.3 From 40112ae7504745799e75ef418057f0d2cb745050 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 21 Apr 2009 12:24:03 -0700 Subject: ipmi: test for event buffer before using The IPMI driver would attempt to use the event buffer even if that didn't exist on the BMC. This patch modified the IPMI driver to check for the event buffer's existence before trying to use it. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 148 +++++++++++++++++++++++++++++++-------- 1 file changed, 119 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 2438fdf889b..259644646b8 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -82,12 +82,6 @@ #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a short timeout */ -/* Bit for BMC global enables. */ -#define IPMI_BMC_RCV_MSG_INTR 0x01 -#define IPMI_BMC_EVT_MSG_INTR 0x02 -#define IPMI_BMC_EVT_MSG_BUFF 0x04 -#define IPMI_BMC_SYS_LOG 0x08 - enum si_intf_state { SI_NORMAL, SI_GETTING_FLAGS, @@ -220,6 +214,9 @@ struct smi_info { OEM2_DATA_AVAIL) unsigned char msg_flags; + /* Does the BMC have an event buffer? */ + char has_event_buffer; + /* * If set to true, this will request events the next time the * state machine is idle. @@ -968,7 +965,8 @@ static void request_events(void *send_info) { struct smi_info *smi_info = send_info; - if (atomic_read(&smi_info->stop_operation)) + if (atomic_read(&smi_info->stop_operation) || + !smi_info->has_event_buffer) return; atomic_set(&smi_info->req_events, 1); @@ -2407,26 +2405,9 @@ static struct of_platform_driver ipmi_of_platform_driver = { }; #endif /* CONFIG_PPC_OF */ - -static int try_get_dev_id(struct smi_info *smi_info) +static int wait_for_msg_done(struct smi_info *smi_info) { - unsigned char msg[2]; - unsigned char *resp; - unsigned long resp_len; enum si_sm_result smi_result; - int rv = 0; - - resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); - if (!resp) - return -ENOMEM; - - /* - * Do a Get Device ID command, since it comes back with some - * useful info. - */ - msg[0] = IPMI_NETFN_APP_REQUEST << 2; - msg[1] = IPMI_GET_DEVICE_ID_CMD; - smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); smi_result = smi_info->handlers->event(smi_info->si_sm, 0); for (;;) { @@ -2441,16 +2422,39 @@ static int try_get_dev_id(struct smi_info *smi_info) } else break; } - if (smi_result == SI_SM_HOSED) { + if (smi_result == SI_SM_HOSED) /* * We couldn't get the state machine to run, so whatever's at * the port is probably not an IPMI SMI interface. */ - rv = -ENODEV; + return -ENODEV; + + return 0; +} + +static int try_get_dev_id(struct smi_info *smi_info) +{ + unsigned char msg[2]; + unsigned char *resp; + unsigned long resp_len; + int rv = 0; + + resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + /* + * Do a Get Device ID command, since it comes back with some + * useful info. + */ + msg[0] = IPMI_NETFN_APP_REQUEST << 2; + msg[1] = IPMI_GET_DEVICE_ID_CMD; + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); + + rv = wait_for_msg_done(smi_info); + if (rv) goto out; - } - /* Otherwise, we got some data. */ resp_len = smi_info->handlers->get_result(smi_info->si_sm, resp, IPMI_MAX_MSG_LENGTH); @@ -2462,6 +2466,88 @@ static int try_get_dev_id(struct smi_info *smi_info) return rv; } +static int try_enable_event_buffer(struct smi_info *smi_info) +{ + unsigned char msg[3]; + unsigned char *resp; + unsigned long resp_len; + int rv = 0; + + resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + msg[0] = IPMI_NETFN_APP_REQUEST << 2; + msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); + + rv = wait_for_msg_done(smi_info); + if (rv) { + printk(KERN_WARNING + "ipmi_si: Error getting response from get global," + " enables command, the event buffer is not" + " enabled.\n"); + goto out; + } + + resp_len = smi_info->handlers->get_result(smi_info->si_sm, + resp, IPMI_MAX_MSG_LENGTH); + + if (resp_len < 4 || + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || + resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || + resp[2] != 0) { + printk(KERN_WARNING + "ipmi_si: Invalid return from get global" + " enables command, cannot enable the event" + " buffer.\n"); + rv = -EINVAL; + goto out; + } + + if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) + /* buffer is already enabled, nothing to do. */ + goto out; + + msg[0] = IPMI_NETFN_APP_REQUEST << 2; + msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; + msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF; + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3); + + rv = wait_for_msg_done(smi_info); + if (rv) { + printk(KERN_WARNING + "ipmi_si: Error getting response from set global," + " enables command, the event buffer is not" + " enabled.\n"); + goto out; + } + + resp_len = smi_info->handlers->get_result(smi_info->si_sm, + resp, IPMI_MAX_MSG_LENGTH); + + if (resp_len < 3 || + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || + resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { + printk(KERN_WARNING + "ipmi_si: Invalid return from get global," + "enables command, not enable the event" + " buffer.\n"); + rv = -EINVAL; + goto out; + } + + if (resp[2] != 0) + /* + * An error when setting the event buffer bit means + * that the event buffer is not supported. + */ + rv = -ENOENT; + out: + kfree(resp); + return rv; +} + static int type_file_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -2847,6 +2933,10 @@ static int try_smi_init(struct smi_info *new_smi) new_smi->intf_num = smi_num; smi_num++; + rv = try_enable_event_buffer(new_smi); + if (rv == 0) + new_smi->has_event_buffer = 1; + /* * Start clearing the flags before we enable interrupts or the * timer to avoid racing with the timer. -- cgit v1.2.3 From 25176ed670121e1e0aae5c8161713c332b786538 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 21 Apr 2009 12:24:04 -0700 Subject: ipmi: fix statistics counting issues Bela Lubkin noticed that the statistics for send IPMB and LAN commands in the IPMI driver could be incremented even if an error occurred. Move the increments to the proper place to avoid this. Also add some statistics for retransmissions that failed, and some little helper functions to neaten up the code a little. Signed-off-by: Corey Minyard Cc: Bela Lubkin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 73 ++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e93fc8d22fb..83c7477ba80 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -285,6 +285,11 @@ enum ipmi_stat_indexes { /* Events that were received with the proper format. */ IPMI_STAT_events, + /* Retransmissions on IPMB that failed. */ + IPMI_STAT_dropped_rexmit_ipmb_commands, + + /* Retransmissions on LAN that failed. */ + IPMI_STAT_dropped_rexmit_lan_commands, /* This *must* remain last, add new values above this. */ IPMI_NUM_STATS @@ -445,6 +450,20 @@ static DEFINE_MUTEX(smi_watchers_mutex); #define ipmi_get_stat(intf, stat) \ ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) +static int is_lan_addr(struct ipmi_addr *addr) +{ + return addr->addr_type == IPMI_LAN_ADDR_TYPE; +} + +static int is_ipmb_addr(struct ipmi_addr *addr) +{ + return addr->addr_type == IPMI_IPMB_ADDR_TYPE; +} + +static int is_ipmb_bcast_addr(struct ipmi_addr *addr) +{ + return addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE; +} static void free_recv_msg_list(struct list_head *q) { @@ -601,8 +620,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) return (smi_addr1->lun == smi_addr2->lun); } - if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE) - || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { + if (is_ipmb_addr(addr1) || is_ipmb_bcast_addr(addr1)) { struct ipmi_ipmb_addr *ipmb_addr1 = (struct ipmi_ipmb_addr *) addr1; struct ipmi_ipmb_addr *ipmb_addr2 @@ -612,7 +630,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) && (ipmb_addr1->lun == ipmb_addr2->lun)); } - if (addr1->addr_type == IPMI_LAN_ADDR_TYPE) { + if (is_lan_addr(addr1)) { struct ipmi_lan_addr *lan_addr1 = (struct ipmi_lan_addr *) addr1; struct ipmi_lan_addr *lan_addr2 @@ -644,14 +662,13 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len) || (addr->channel < 0)) return -EINVAL; - if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) - || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { + if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) { if (len < sizeof(struct ipmi_ipmb_addr)) return -EINVAL; return 0; } - if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { + if (is_lan_addr(addr)) { if (len < sizeof(struct ipmi_lan_addr)) return -EINVAL; return 0; @@ -1503,8 +1520,7 @@ static int i_ipmi_request(ipmi_user_t user, memcpy(&(smi_msg->data[2]), msg->data, msg->data_len); smi_msg->data_size = msg->data_len + 2; ipmi_inc_stat(intf, sent_local_commands); - } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE) - || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) { + } else if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) { struct ipmi_ipmb_addr *ipmb_addr; unsigned char ipmb_seq; long seqid; @@ -1583,8 +1599,6 @@ static int i_ipmi_request(ipmi_user_t user, spin_lock_irqsave(&(intf->seq_lock), flags); - ipmi_inc_stat(intf, sent_ipmb_commands); - /* * Create a sequence number with a 1 second * timeout and 4 retries. @@ -1606,6 +1620,8 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } + ipmi_inc_stat(intf, sent_ipmb_commands); + /* * Store the sequence number in the message, * so that when the send message response @@ -1635,7 +1651,7 @@ static int i_ipmi_request(ipmi_user_t user, */ spin_unlock_irqrestore(&(intf->seq_lock), flags); } - } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { + } else if (is_lan_addr(addr)) { struct ipmi_lan_addr *lan_addr; unsigned char ipmb_seq; long seqid; @@ -1696,8 +1712,6 @@ static int i_ipmi_request(ipmi_user_t user, spin_lock_irqsave(&(intf->seq_lock), flags); - ipmi_inc_stat(intf, sent_lan_commands); - /* * Create a sequence number with a 1 second * timeout and 4 retries. @@ -1719,6 +1733,8 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } + ipmi_inc_stat(intf, sent_lan_commands); + /* * Store the sequence number in the message, * so that when the send message response @@ -1937,6 +1953,10 @@ static int stat_file_read_proc(char *page, char **start, off_t off, ipmi_get_stat(intf, invalid_events)); out += sprintf(out, "events: %u\n", ipmi_get_stat(intf, events)); + out += sprintf(out, "failed rexmit LAN msgs: %u\n", + ipmi_get_stat(intf, dropped_rexmit_lan_commands)); + out += sprintf(out, "failed rexmit IPMB msgs: %u\n", + ipmi_get_stat(intf, dropped_rexmit_ipmb_commands)); return (out - ((char *) page)); } @@ -3730,7 +3750,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, list_add_tail(&msg->link, timeouts); if (ent->broadcast) ipmi_inc_stat(intf, timed_out_ipmb_broadcasts); - else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + else if (is_lan_addr(&ent->recv_msg->addr)) ipmi_inc_stat(intf, timed_out_lan_commands); else ipmi_inc_stat(intf, timed_out_ipmb_commands); @@ -3744,15 +3764,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, */ ent->timeout = MAX_MSG_TIMEOUT; ent->retries_left--; - if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) - ipmi_inc_stat(intf, retransmitted_lan_commands); - else - ipmi_inc_stat(intf, retransmitted_ipmb_commands); - smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, ent->seqid); - if (!smi_msg) + if (!smi_msg) { + if (is_lan_addr(&ent->recv_msg->addr)) + ipmi_inc_stat(intf, + dropped_rexmit_lan_commands); + else + ipmi_inc_stat(intf, + dropped_rexmit_ipmb_commands); return; + } spin_unlock_irqrestore(&intf->seq_lock, *flags); @@ -3764,10 +3786,17 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, * resent. */ handlers = intf->handlers; - if (handlers) + if (handlers) { + if (is_lan_addr(&ent->recv_msg->addr)) + ipmi_inc_stat(intf, + retransmitted_lan_commands); + else + ipmi_inc_stat(intf, + retransmitted_ipmb_commands); + intf->handlers->sender(intf->send_info, smi_msg, 0); - else + } else ipmi_free_smi_msg(smi_msg); spin_lock_irqsave(&intf->seq_lock, *flags); -- cgit v1.2.3 From 4dec302ff71ebf48f5784a2d2fc5e3745e6d4d52 Mon Sep 17 00:00:00 2001 From: dann frazier Date: Tue, 21 Apr 2009 12:24:05 -0700 Subject: ipmi: add oem message handling Enable userspace to receive messages that a BMC transmits using an OEM medium. This is used by the HP iLO2. Based on code originally written by Patrick Schoeller. Signed-off-by: dann frazier Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 138 ++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 83c7477ba80..aa83a0865ec 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -3284,6 +3284,114 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, return rv; } +/* + * This routine will handle "Get Message" command responses with + * channels that use an OEM Medium. The message format belongs to + * the OEM. See IPMI 2.0 specification, Chapter 6 and + * Chapter 22, sections 22.6 and 22.24 for more details. + */ +static int handle_oem_get_msg_cmd(ipmi_smi_t intf, + struct ipmi_smi_msg *msg) +{ + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + unsigned char chan; + ipmi_user_t user = NULL; + struct ipmi_system_interface_addr *smi_addr; + struct ipmi_recv_msg *recv_msg; + + /* + * We expect the OEM SW to perform error checking + * so we just do some basic sanity checks + */ + if (msg->rsp_size < 4) { + /* Message not big enough, just ignore it. */ + ipmi_inc_stat(intf, invalid_commands); + return 0; + } + + if (msg->rsp[2] != 0) { + /* An error getting the response, just ignore it. */ + return 0; + } + + /* + * This is an OEM Message so the OEM needs to know how + * handle the message. We do no interpretation. + */ + netfn = msg->rsp[0] >> 2; + cmd = msg->rsp[1]; + chan = msg->rsp[3] & 0xf; + + rcu_read_lock(); + rcvr = find_cmd_rcvr(intf, netfn, cmd, chan); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + rcu_read_unlock(); + + if (user == NULL) { + /* We didn't find a user, just give up. */ + ipmi_inc_stat(intf, unhandled_commands); + + /* + * Don't do anything with these messages, just allow + * them to be freed. + */ + + rv = 0; + } else { + /* Deliver the message to the user. */ + ipmi_inc_stat(intf, handled_commands); + + recv_msg = ipmi_alloc_recv_msg(); + if (!recv_msg) { + /* + * We couldn't allocate memory for the + * message, so requeue it for handling + * later. + */ + rv = 1; + kref_put(&user->refcount, free_user); + } else { + /* + * OEM Messages are expected to be delivered via + * the system interface to SMS software. We might + * need to visit this again depending on OEM + * requirements + */ + smi_addr = ((struct ipmi_system_interface_addr *) + &(recv_msg->addr)); + smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + smi_addr->channel = IPMI_BMC_CHANNEL; + smi_addr->lun = msg->rsp[0] & 3; + + recv_msg->user = user; + recv_msg->user_msg_data = NULL; + recv_msg->recv_type = IPMI_OEM_RECV_TYPE; + recv_msg->msg.netfn = msg->rsp[0] >> 2; + recv_msg->msg.cmd = msg->rsp[1]; + recv_msg->msg.data = recv_msg->msg_data; + + /* + * The message starts at byte 4 which follows the + * the Channel Byte in the "GET MESSAGE" command + */ + recv_msg->msg.data_len = msg->rsp_size - 4; + memcpy(recv_msg->msg_data, + &(msg->rsp[4]), + msg->rsp_size - 4); + deliver_response(recv_msg); + } + } + + return rv; +} + static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, struct ipmi_smi_msg *msg) { @@ -3539,6 +3647,17 @@ static int handle_new_recv_msg(ipmi_smi_t intf, goto out; } + /* + ** We need to make sure the channels have been initialized. + ** The channel_handler routine will set the "curr_channel" + ** equal to or greater than IPMI_MAX_CHANNELS when all the + ** channels for this interface have been initialized. + */ + if (intf->curr_channel < IPMI_MAX_CHANNELS) { + requeue = 1; /* Just put the message back for now */ + goto out; + } + switch (intf->channels[chan].medium) { case IPMI_CHANNEL_MEDIUM_IPMB: if (msg->rsp[4] & 0x04) { @@ -3574,11 +3693,20 @@ static int handle_new_recv_msg(ipmi_smi_t intf, break; default: - /* - * We don't handle the channel type, so just - * free the message. - */ - requeue = 0; + /* Check for OEM Channels. Clients had better + register for these commands. */ + if ((intf->channels[chan].medium + >= IPMI_CHANNEL_MEDIUM_OEM_MIN) + && (intf->channels[chan].medium + <= IPMI_CHANNEL_MEDIUM_OEM_MAX)) { + requeue = handle_oem_get_msg_cmd(intf, msg); + } else { + /* + * We don't handle the channel type, so just + * free the message. + */ + requeue = 0; + } } } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) -- cgit v1.2.3 From aa0b8f3687f06ac0e5a2b24547fdf431e923c475 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 21 Apr 2009 12:24:42 -0700 Subject: drivers/input/serio/hp_sdc.c: fix crash when removing hp_sdc module On parisc machines, which don't have HIL, removing the hp_sdc module panics the kernel. Fix this by returning early in hp_sdc_exit() if no HP SDC controller was found. Add functionality to probe for the hp_sdc_mlc kernel module (which takes care of the upper layer HIL functionality on parisc) after two seconds. This is needed to get all the other HIL drivers (keyboard / mouse/ ..) drivers automatically loaded by udev later as well. Signed-off-by: Helge Deller Cc: Geert Uytterhoeven Cc: Frans Pop Cc: Kyle McMartin Cc: Grant Grundler Acked-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/serio/hp_sdc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index bfe49243f38..1c9410d1822 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -819,6 +819,7 @@ static const struct parisc_device_id hp_sdc_tbl[] = { MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); static int __init hp_sdc_init_hppa(struct parisc_device *d); +static struct delayed_work moduleloader_work; static struct parisc_driver hp_sdc_driver = { .name = "hp_sdc", @@ -930,8 +931,15 @@ static int __init hp_sdc_init(void) #if defined(__hppa__) +static void request_module_delayed(struct work_struct *work) +{ + request_module("hp_sdc_mlc"); +} + static int __init hp_sdc_init_hppa(struct parisc_device *d) { + int ret; + if (!d) return 1; if (hp_sdc.dev != NULL) @@ -944,13 +952,26 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) hp_sdc.data_io = d->hpa.start + 0x800; hp_sdc.status_io = d->hpa.start + 0x801; - return hp_sdc_init(); + INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); + + ret = hp_sdc_init(); + /* after sucessfull initialization give SDC some time to settle + * and then load the hp_sdc_mlc upper layer driver */ + if (!ret) + schedule_delayed_work(&moduleloader_work, + msecs_to_jiffies(2000)); + + return ret; } #endif /* __hppa__ */ static void hp_sdc_exit(void) { + /* do nothing if we don't have a SDC */ + if (!hp_sdc.dev) + return; + write_lock_irq(&hp_sdc.lock); /* Turn off all maskable "sub-function" irq's. */ @@ -969,6 +990,7 @@ static void hp_sdc_exit(void) tasklet_kill(&hp_sdc.task); #if defined(__hppa__) + cancel_delayed_work_sync(&moduleloader_work); if (unregister_parisc_driver(&hp_sdc_driver)) printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); #endif -- cgit v1.2.3 From 148da331200a0df8195e10eb8a38fd77bd7003af Mon Sep 17 00:00:00 2001 From: Daniel Ribeiro Date: Tue, 21 Apr 2009 12:24:43 -0700 Subject: pxa2xx_spi: restore DRCMR on resume If DMA is enabled, any spi_sync call after suspend/resume would block forever, because DRCMR is lost on suspend. This patch restores DRCMR to the same values set by probe. Signed-off-by: Daniel Ribeiro Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index c76feea5fe2..1a00b415bcc 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1700,6 +1700,13 @@ static int pxa2xx_spi_resume(struct platform_device *pdev) struct ssp_device *ssp = drv_data->ssp; int status = 0; + if (drv_data->rx_channel != -1) + DRCMR(drv_data->ssp->drcmr_rx) = + DRCMR_MAPVLD | drv_data->rx_channel; + if (drv_data->tx_channel != -1) + DRCMR(drv_data->ssp->drcmr_tx) = + DRCMR_MAPVLD | drv_data->tx_channel; + /* Enable the SSP clock */ clk_enable(ssp->clk); -- cgit v1.2.3 From 306c68aaa7c62010428196d309fda30b6bf57710 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 21 Apr 2009 12:24:46 -0700 Subject: spi: pxa2xx: limit reaches -1 On line 944 the return value of flush() is considered as a boolean, but limit reaches -1 upon timeout which evaluates to true. On 540, 594, 720 the same occurs for wait_ssp_rx_stall() On 536 the same occurs for wait_dma_channel_stop() Signed-off-by: Roel Kluin Acked-by: Eric Miao Cc: David Brownell Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 1a00b415bcc..885194a0741 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -213,7 +213,7 @@ static int flush(struct driver_data *drv_data) while (read_SSSR(reg) & SSSR_RNE) { read_SSDR(reg); } - } while ((read_SSSR(reg) & SSSR_BSY) && limit--); + } while ((read_SSSR(reg) & SSSR_BSY) && --limit); write_SSSR(SSSR_ROR, reg); return limit; @@ -484,7 +484,7 @@ static int wait_ssp_rx_stall(void const __iomem *ioaddr) { unsigned long limit = loops_per_jiffy << 1; - while ((read_SSSR(ioaddr) & SSSR_BSY) && limit--) + while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit) cpu_relax(); return limit; @@ -494,7 +494,7 @@ static int wait_dma_channel_stop(int channel) { unsigned long limit = loops_per_jiffy << 1; - while (!(DCSR(channel) & DCSR_STOPSTATE) && limit--) + while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit) cpu_relax(); return limit; -- cgit v1.2.3 From 6d029b645175ae71fdeedea84b246ecb1362d003 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Tue, 21 Apr 2009 12:24:49 -0700 Subject: rtc-cmos: fix printk output With no IRQ available/defined, RTC-CMOS driver prints something like: rtc0: alarms up to one no, y3k, 114 bytes nvram ^^^^ I guess the following is a bit easier to understand: rtc0: no alarms, y3k, 114 bytes nvram Signed-off-by: Krzysztof Halasa Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-cmos.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b6d35f50e40..23e10b6263d 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -797,17 +797,15 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) goto cleanup2; } - pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n", - dev_name(&cmos_rtc.rtc->dev), - is_valid_irq(rtc_irq) - ? (cmos_rtc.mon_alrm - ? "year" - : (cmos_rtc.day_alrm - ? "month" : "day")) - : "no", - cmos_rtc.century ? ", y3k" : "", - nvram.size, - is_hpet_enabled() ? ", hpet irqs" : ""); + pr_info("%s: %s%s, %zd bytes nvram%s\n", + dev_name(&cmos_rtc.rtc->dev), + !is_valid_irq(rtc_irq) ? "no alarms" : + cmos_rtc.mon_alrm ? "alarms up to one year" : + cmos_rtc.day_alrm ? "alarms up to one month" : + "alarms up to one day", + cmos_rtc.century ? ", y3k" : "", + nvram.size, + is_hpet_enabled() ? ", hpet irqs" : ""); return 0; -- cgit v1.2.3 From e873cff0fada2b0532ca5104d5b5f5b02aa442b2 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 21 Apr 2009 12:24:53 -0700 Subject: sgi-xp/sgi-gru: allow modules to load on non-uv systems For an upcoming distro release, we need to have the xp kernel module loadable even when not on UV equipment. The xpc module will not load. This will allow one set of modules dependent upon xp to work on either UV or non-UV equipment. Signed-off-by: Robin Holt Signed-off-by: Jack Steiner Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-gru/grufile.c | 2 +- drivers/misc/sgi-xp/xp_main.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index 3e6e42d2f01..bbefe77c67a 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c @@ -375,7 +375,7 @@ static int __init gru_init(void) void *gru_start_vaddr; if (!is_uv_system()) - return -ENODEV; + return 0; #if defined CONFIG_IA64 gru_start_paddr = 0xd000000000UL; /* ZZZZZZZZZZZZZZZZZZZ fixme */ diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c index 16f8dcab2da..7896849b16d 100644 --- a/drivers/misc/sgi-xp/xp_main.c +++ b/drivers/misc/sgi-xp/xp_main.c @@ -248,19 +248,19 @@ xp_init(void) enum xp_retval ret; int ch_number; + /* initialize the connection registration mutex */ + for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) + mutex_init(&xpc_registrations[ch_number].mutex); + if (is_shub()) ret = xp_init_sn2(); else if (is_uv()) ret = xp_init_uv(); else - ret = xpUnsupported; + ret = 0; if (ret != xpSuccess) - return -ENODEV; - - /* initialize the connection registration mutex */ - for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) - mutex_init(&xpc_registrations[ch_number].mutex); + return ret; return 0; } -- cgit v1.2.3 From b298cecb3deddf76d60022473a57f1cb776cbdcd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 21 Apr 2009 12:24:54 -0700 Subject: scsi: mpt: suppress debugobjects warning Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13133 ODEBUG: object is on stack, but not annotated ------------[ cut here ]------------ WARNING: at lib/debugobjects.c:253 __debug_object_init+0x1f3/0x276() Hardware name: VMware Virtual Platform Modules linked in: mptspi(+) mptscsih mptbase scsi_transport_spi ext3 jbd mbcache Pid: 540, comm: insmod Not tainted 2.6.28-mm1 #2 Call Trace: [] warn_slowpath+0x74/0x8a [] ? start_critical_timing+0x96/0xb7 [] ? _spin_unlock_irqrestore+0x2f/0x3c [] ? trace_hardirqs_off_caller+0x18/0xaf [] ? trace_hardirqs_off+0xb/0xd [] ? _spin_unlock_irqrestore+0x2f/0x3c [] ? release_console_sem+0x1a5/0x1ad [] __debug_object_init+0x1f3/0x276 [] debug_object_init+0x13/0x17 [] init_timer+0x10/0x1a [] mpt_config+0x1c1/0x2b7 [mptbase] [] ? kmalloc+0x8/0xa [mptbase] [] ? kmalloc+0x8/0xa [mptbase] [] mpt_do_ioc_recovery+0x950/0x1212 [mptbase] [] ? __lock_acquire+0xa69/0xacc [] ? _spin_unlock_irqrestore+0x36/0x3c [] ? _spin_unlock_irq+0x22/0x26 [] ? string+0x2b/0x76 [] ? vsnprintf+0x338/0x7b3 [] ? __lock_acquire+0xa69/0xacc [] ? _spin_unlock_irqrestore+0x2f/0x3c [] ? __lock_acquire+0xa69/0xacc [] ? debug_check_no_locks_freed+0xeb/0x105 [] ? _spin_unlock_irqrestore+0x36/0x3c [] ? debug_check_no_locks_freed+0x2a/0x105 [] ? lock_release_holdtime+0x43/0x48 [] ? up_read+0x16/0x29 [] ? pci_get_slot+0x66/0x72 [] mpt_attach+0x881/0x9b1 [mptbase] [] mptspi_probe+0x11/0x354 [mptspi] Noticing that every caller of mpt_config has its CONFIGPARMS struct declared on the stack and thus the &pCfg->timer is always on the stack I changed init_timer() to init_timer_on_stack() and it seems to have shut up..... Cc: "Moore, Eric Dean" Cc: James Bottomley Cc: Thomas Gleixner Acked-by: "Desai, Kashyap" Cc: [2.6.29.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/fusion/mptbase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index d0d126c6935..5d496a99e03 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -5934,7 +5934,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* Initalize the timer */ - init_timer(&pCfg->timer); + init_timer_on_stack(&pCfg->timer); pCfg->timer.data = (unsigned long) ioc; pCfg->timer.function = mpt_timer_expired; pCfg->wait_done = 0; -- cgit v1.2.3 From 55e5750b3e979bac853c0809ad0ef75b7cebd18c Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 21 Apr 2009 12:24:56 -0700 Subject: edac: ppc mpc85xx fix mc err detect Error found by Jeff Haran. The error detect register is 0s when no errors are detected. The check code is incorrect, so reverse check sense. Reported-by: Jeff Haran Signed-off-by: Dave Jiang Signed-off-by: Doug Thompson Cc: Benjamin Herrenschmidt Acked-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/mpc85xx_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 4637a4a757d..7c8c2d72916 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -674,7 +674,7 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) int row_index; err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); - if (err_detect) + if (!err_detect) return; mpc85xx_mc_printk(mci, KERN_ERR, "Err Detect Register: %#8.8x\n", -- cgit v1.2.3 From daba0280fdebce0761088cf541d6e6dd7c232850 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 21 Apr 2009 12:24:58 -0700 Subject: bfin_5xx: misplaced parentheses `!' has a higher precedence than `&', parentheses are misplaced. Signed-off-by: Roel Kluin Cc: Alan Cox Acked-by: Sonic Zhang Cc: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/bfin_5xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 18ba812a4f8..d86123e0339 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -166,7 +166,7 @@ static void bfin_serial_start_tx(struct uart_port *port) struct tty_struct *tty = uart->port.info->port.tty; #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS - if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) { + if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { uart->scts = 0; uart_handle_cts_change(&uart->port, uart->scts); } @@ -368,7 +368,7 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) struct bfin_serial_port *uart = dev_id; #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS - if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) { + if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { uart->scts = 0; uart_handle_cts_change(&uart->port, uart->scts); } @@ -504,7 +504,7 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) struct circ_buf *xmit = &uart->port.info->xmit; #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS - if (uart->scts && (!bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) { + if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) { uart->scts = 0; uart_handle_cts_change(&uart->port, uart->scts); } -- cgit v1.2.3