diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist index bfbb271..bd23dc0 100644 --- a/Documentation/SubmitChecklist +++ b/Documentation/SubmitChecklist @@ -76,3 +76,7 @@ kernel patches. 22: Newly-added code has been compiled with `gcc -W'. This will generate lots of noise, but is good for finding bugs like "warning: comparison between signed and unsigned". + +23: Tested after it has been merged into the -mm patchset to make sure + that it still works with all of the other queued patches and various + changes in the VM, VFS, and other subsystems. diff --git a/Documentation/cpu-load.txt b/Documentation/cpu-load.txt new file mode 100644 index 0000000..287224e --- /dev/null +++ b/Documentation/cpu-load.txt @@ -0,0 +1,113 @@ +CPU load +-------- + +Linux exports various bits of information via `/proc/stat' and +`/proc/uptime' that userland tools, such as top(1), use to calculate +the average time system spent in a particular state, for example: + + $ iostat + Linux 2.6.18.3-exp (linmac) 02/20/2007 + + avg-cpu: %user %nice %system %iowait %steal %idle + 10.01 0.00 2.92 5.44 0.00 81.63 + + ... + +Here the system thinks that over the default sampling period the +system spent 10.01% of the time doing work in user space, 2.92% in the +kernel, and was overall 81.63% of the time idle. + +In most cases the `/proc/stat' information reflects the reality quite +closely, however due to the nature of how/when the kernel collects +this data sometimes it can not be trusted at all. + +So how is this information collected? Whenever timer interrupt is +signalled the kernel looks what kind of task was running at this +moment and increments the counter that corresponds to this tasks +kind/state. The problem with this is that the system could have +switched between various states multiple times between two timer +interrupts yet the counter is incremented only for the last state. + + +Example +------- + +If we imagine the system with one task that periodically burns cycles +in the following manner: + + time line between two timer interrupts +|--------------------------------------| + ^ ^ + |_ something begins working | + |_ something goes to sleep + (only to be awaken quite soon) + +In the above situation the system will be 0% loaded according to the +`/proc/stat' (since the timer interrupt will always happen when the +system is executing the idle handler), but in reality the load is +closer to 99%. + +One can imagine many more situations where this behavior of the kernel +will lead to quite erratic information inside `/proc/stat'. + + +/* gcc -o hog smallhog.c */ +#include +#include +#include +#include +#define HIST 10 + +static volatile sig_atomic_t stop; + +static void sighandler (int signr) +{ + (void) signr; + stop = 1; +} +static unsigned long hog (unsigned long niters) +{ + stop = 0; + while (!stop && --niters); + return niters; +} +int main (void) +{ + int i; + struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 }, + .it_value = { .tv_sec = 0, .tv_usec = 1 } }; + sigset_t set; + unsigned long v[HIST]; + double tmp = 0.0; + unsigned long n; + signal (SIGALRM, &sighandler); + setitimer (ITIMER_REAL, &it, NULL); + + hog (ULONG_MAX); + for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX); + for (i = 0; i < HIST; ++i) tmp += v[i]; + tmp /= HIST; + n = tmp - (tmp / 3.0); + + sigemptyset (&set); + sigaddset (&set, SIGALRM); + + for (;;) { + hog (n); + sigwait (&set, &i); + } + return 0; +} + + +References +---------- + +http://lkml.org/lkml/2007/2/12/6 +Documentation/filesystems/proc.txt (1.8) + + +Thanks +------ + +Con Kolivas, Pavel Machek diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index a0f6842..d3aae1f 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -147,6 +147,11 @@ tcp_available_congestion_control - STRING More congestion control algorithms may be available as modules, but not loaded. +tcp_base_mss - INTEGER + The initial value of search_low to be used by Packetization Layer + Path MTU Discovery (MTU probing). If MTU probing is enabled, + this is the inital MSS used by the connection. + tcp_congestion_control - STRING Set the congestion control algorithm to be used for new connections. The algorithm "reno" is always available, but @@ -243,6 +248,27 @@ tcp_mem - vector of 3 INTEGERs: min, pressure, max Defaults are calculated at boot time from amount of available memory. +tcp_moderate_rcvbuf - BOOLEAN + If set, TCP performs receive buffer autotuning, attempting to + automatically size the buffer (no greater than tcp_rmem[2]) to + match the size required by the path for full throughput. Enabled by + default. + +tcp_mtu_probing - INTEGER + Controls TCP Packetization-Layer Path MTU Discovery. Takes three + values: + 0 - Disabled + 1 - Disabled by default, enabled when an ICMP black hole detected + 2 - Always enabled, use initial MSS of tcp_base_mss. + +tcp_no_metrics_save - BOOLEAN + By default, TCP saves various connection metrics in the route cache + when the connection closes, so that connections established in the + near future can use these to set initial conditions. Usually, this + increases overall performance, but may sometimes cause performance + degredation. If set, TCP will not cache metrics on closing + connections. + tcp_orphan_retries - INTEGER How may times to retry before killing TCP connection, closed by our side. Default value 7 corresponds to ~50sec-16min diff --git a/MAINTAINERS b/MAINTAINERS index 35e0a64..1dfba85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1345,7 +1345,7 @@ S: Supported FRAMEBUFFER LAYER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) W: http://linux-fbdev.sourceforge.net/ S: Maintained @@ -1492,6 +1492,7 @@ HID CORE LAYER P: Jiri Kosina M: jkosina@suse.cz L: linux-input@atrey.karlin.mff.cuni.cz +T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS @@ -1756,7 +1757,7 @@ S: Maintained INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained @@ -2471,7 +2472,7 @@ S: Maintained NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained @@ -2855,7 +2856,7 @@ S: Orphan S3 SAVAGE FRAMEBUFFER DRIVER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained @@ -3423,6 +3424,7 @@ USB HID/HIDBP DRIVERS P: Jiri Kosina M: jkosina@suse.cz L: linux-usb-devel@lists.sourceforge.net +T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained USB HUB DRIVER diff --git a/Makefile b/Makefile index 66ee8b8..dee9938 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 21 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc2-git2 NAME = Homicidal Dwarf Hamster # *DOCUMENTATION* diff --git a/arch/arm26/kernel/entry.S b/arch/arm26/kernel/entry.S index 6d910ea..91496cc 100644 --- a/arch/arm26/kernel/entry.S +++ b/arch/arm26/kernel/entry.S @@ -245,11 +245,6 @@ ENTRY(vector_swi) zero_fp get_scno -#ifdef CONFIG_ALIGNMENT_TRAP - ldr ip, __cr_alignment - ldr ip, [ip] - mcr p15, 0, ip, c1, c0 @ update control register -#endif enable_irqs ip str r4, [sp, #-S_OFF]! @ push fifth arg @@ -299,11 +294,6 @@ __sys_trace_return: b ret_slow_syscall .align 5 -#ifdef CONFIG_ALIGNMENT_TRAP - .type __cr_alignment, #object -__cr_alignment: - .word cr_alignment -#endif .type sys_call_table, #object ENTRY(sys_call_table) diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c index 426b098..70d3bf0 100644 --- a/arch/cris/arch-v32/drivers/pci/dma.c +++ b/arch/cris/arch-v32/drivers/pci/dma.c @@ -111,7 +111,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, return DMA_MEMORY_IO; free1_out: - kfree(dev->dma_mem->bitmap); + kfree(dev->dma_mem); out: return 0; } diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index 3f3a0ed..4103c2c 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -126,8 +126,7 @@ void __init paging_init(void) /* distribute the allocatable pages across the various zones and pass them to the allocator */ - zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; - zones_size[ZONE_NORMAL] = 0; + zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; #ifdef CONFIG_HIGHMEM zones_size[ZONE_HIGHMEM] = num_physpages - num_mappedpages; #endif diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 6fec4da..e4408ff 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1354,7 +1354,6 @@ static void __init setup_IO_APIC_irqs(void) } spin_lock_irqsave(&ioapic_lock, flags); __ioapic_write_entry(apic, pin, entry); - irq_desc[irq].affinity = TARGET_CPUS; spin_unlock_irqrestore(&ioapic_lock, flags); } } @@ -2875,7 +2874,6 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a spin_lock_irqsave(&ioapic_lock, flags); __ioapic_write_entry(ioapic, pin, entry); - irq_desc[irq].affinity = TARGET_CPUS; spin_unlock_irqrestore(&ioapic_lock, flags); return 0; diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c index 41af692..3ebcea0 100644 --- a/arch/i386/kernel/pci-dma.c +++ b/arch/i386/kernel/pci-dma.c @@ -110,7 +110,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, return DMA_MEMORY_IO; free1_out: - kfree(dev->dma_mem->bitmap); + kfree(dev->dma_mem); out: if (mem_base) iounmap(mem_base); diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index d270a1e..1a481a6 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -1,9 +1,24 @@ menu "PS3 Platform Options" depends on PPC_PS3 +config PS3_ADVANCED + depends on PPC_PS3 + bool "PS3 Advanced configuration options" + help + This gives you access to some advanced options for the PS3. The + defaults should be fine for most users, but these options may make + it possible to better control the kernel configuration if you know + what you are doing. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about these options. + + Most users should say N to this question. + config PS3_HTAB_SIZE depends on PPC_PS3 - int "PS3 Platform pagetable size" + int "PS3 Platform pagetable size" if PS3_ADVANCED range 18 20 default 20 help @@ -42,7 +57,7 @@ config PS3_USE_LPAR_ADDR config PS3_VUART depends on PPC_PS3 - bool "PS3 Virtual UART support" + bool "PS3 Virtual UART support" if PS3_ADVANCED default y help Include support for the PS3 Virtual UART. @@ -52,9 +67,8 @@ config PS3_VUART general, all users will say Y. config PS3_PS3AV - tristate "PS3 AV settings driver" - depends on PPC_PS3 - select PS3_VUART + tristate "PS3 AV settings driver" if PS3_ADVANCED + depends on PS3_VUART default y help Include support for the PS3 AV Settings driver. @@ -63,8 +77,8 @@ config PS3_PS3AV general, all users will say Y or M. config PS3_SYS_MANAGER - bool "PS3 System Manager driver" - select PS3_VUART + bool "PS3 System Manager driver" if PS3_ADVANCED + depends on PS3_VUART default y help Include support for the PS3 System Manager. diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 59eef40..860b8b6 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21-rc1 -# Mon Feb 26 10:45:21 2007 +# Linux kernel version: 2.6.21-rc2 +# Wed Feb 28 09:50:51 2007 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -1219,6 +1219,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index e03e40c..a5b079d 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -146,6 +146,25 @@ config LEGACY_PTYS security. This option enables these legacy devices; on most systems, it is safe to say N. +config RAW_DRIVER + tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" + help + The raw driver permits block devices to be bound to /dev/raw/rawN. + Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. + See the raw(8) manpage for more details. + + The raw driver is deprecated and will be removed soon. + Applications should simply open the device (eg /dev/hda1) + with the O_DIRECT flag. + +config MAX_RAW_DEVS + int "Maximum number of RAW devices to support (1-8192)" + depends on RAW_DRIVER + default "256" + help + The maximum number of RAW devices that are supported. + Default is 256. Increase this number in case you need lots of + raw devices. config LEGACY_PTY_COUNT int "Maximum number of legacy PTY in use" diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 3a8d7e3..608784d 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -39,6 +39,9 @@ __init void scan_elf_aux( char **envp) switch ( auxv->a_type ) { case AT_SYSINFO: __kernel_vsyscall = auxv->a_un.a_val; + /* See if the page is under TASK_SIZE */ + if (__kernel_vsyscall < (unsigned long) envp) + __kernel_vsyscall = 0; break; case AT_SYSINFO_EHDR: vsyscall_ehdr = auxv->a_un.a_val; diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index b2e1fd8..3fc43b3 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -334,8 +334,11 @@ void maybe_sigio_broken(int fd, int read) sigio_lock(); err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); - if(err) + if(err){ + printk("maybe_sigio_broken - failed to add pollfd for " + "descriptor %d\n", fd); goto out; + } all_sigio_fds.poll[all_sigio_fds.used++] = ((struct pollfd) { .fd = fd, diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 5db7737..4a8b420 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -7,6 +7,7 @@ #include "linux/slab.h" #include "linux/types.h" #include "linux/errno.h" +#include "linux/spinlock.h" #include "asm/uaccess.h" #include "asm/smp.h" #include "asm/ldt.h" @@ -386,23 +387,33 @@ static long do_modify_ldt_skas(int func, void __user *ptr, return ret; } -short dummy_list[9] = {0, -1}; -short * host_ldt_entries = NULL; +static DEFINE_SPINLOCK(host_ldt_lock); +static short dummy_list[9] = {0, -1}; +static short * host_ldt_entries = NULL; -void ldt_get_host_info(void) +static void ldt_get_host_info(void) { long ret; - struct ldt_entry * ldt; + struct ldt_entry * ldt, *tmp; int i, size, k, order; + spin_lock(&host_ldt_lock); + + if(host_ldt_entries != NULL){ + spin_unlock(&host_ldt_lock); + return; + } host_ldt_entries = dummy_list+1; + spin_unlock(&host_ldt_lock); + for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); ldt = (struct ldt_entry *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); if(ldt == NULL) { - printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n"); + printk("ldt_get_host_info: couldn't allocate buffer for host " + "ldt\n"); return; } @@ -426,11 +437,13 @@ void ldt_get_host_info(void) host_ldt_entries = dummy_list; else { size = (size + 1) * sizeof(dummy_list[0]); - host_ldt_entries = kmalloc(size, GFP_KERNEL); - if(host_ldt_entries == NULL) { - printk("ldt_get_host_info: couldn't allocate host ldt list\n"); + tmp = kmalloc(size, GFP_KERNEL); + if(tmp == NULL) { + printk("ldt_get_host_info: couldn't allocate host ldt " + "list\n"); goto out_free; } + host_ldt_entries = tmp; } for(i=0, k=0; iid, 1, &desc, @@ -560,6 +572,6 @@ void free_ldt(struct mmu_context_skas * mm) int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { - return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, - ptr, bytecount)); + return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, + ptr, bytecount); } diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 48593f6..0a91368 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -830,10 +830,6 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, disable_8259A_irq(irq); ioapic_write_entry(apic, pin, entry); - - spin_lock_irqsave(&ioapic_lock, flags); - irq_desc[irq].affinity = TARGET_CPUS; - spin_unlock_irqrestore(&ioapic_lock, flags); } static void __init setup_IO_APIC_irqs(void) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index e942ffe..7c49e10 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -149,6 +149,7 @@ config ACPI_DOCK config ACPI_BAY tristate "Removable Drive Bay (EXPERIMENTAL)" depends on EXPERIMENTAL + depends on ACPI_DOCK help This driver adds support for ACPI controlled removable drive bays such as the IBM ultrabay or the Dell Module Bay. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 6d93240..1539734 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -200,6 +200,7 @@ struct ahci_port_priv { /* for NCQ spurious interrupt analysis */ unsigned int ncq_saw_d2h:1; unsigned int ncq_saw_dmas:1; + unsigned int ncq_saw_sdb:1; }; static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -384,12 +385,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */ - /* JMicron */ - { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ - { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */ - { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */ - { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */ - { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */ + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ @@ -1160,23 +1158,31 @@ static void ahci_host_intr(struct ata_port *ap) } if (status & PORT_IRQ_SDB_FIS) { - /* SDB FIS containing spurious completions might be - * dangerous, whine and fail commands with HSM - * violation. EH will turn off NCQ after several such - * failures. - */ const __le32 *f = pp->rx_fis + RX_FIS_SDB; - ata_ehi_push_desc(ehi, "spurious completion during NCQ " - "issue=0x%x SAct=0x%x FIS=%08x:%08x", - readl(port_mmio + PORT_CMD_ISSUE), - readl(port_mmio + PORT_SCR_ACT), - le32_to_cpu(f[0]), le32_to_cpu(f[1])); - - ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_SOFTRESET; - ata_port_freeze(ap); - + if (le32_to_cpu(f[1])) { + /* SDB FIS containing spurious completions + * might be dangerous, whine and fail commands + * with HSM violation. EH will turn off NCQ + * after several such failures. + */ + ata_ehi_push_desc(ehi, + "spurious completions during NCQ " + "issue=0x%x SAct=0x%x FIS=%08x:%08x", + readl(port_mmio + PORT_CMD_ISSUE), + readl(port_mmio + PORT_SCR_ACT), + le32_to_cpu(f[0]), le32_to_cpu(f[1])); + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); + } else { + if (!pp->ncq_saw_sdb) + ata_port_printk(ap, KERN_INFO, + "spurious SDB FIS %08x:%08x during NCQ, " + "this message won't be printed again\n", + le32_to_cpu(f[0]), le32_to_cpu(f[1])); + pp->ncq_saw_sdb = 1; + } known_irq = 1; } @@ -1665,13 +1671,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - if (pdev->vendor == PCI_VENDOR_ID_JMICRON) { - /* Function 1 is the PATA controller except on the 368, where - we are not AHCI anyway */ - if (PCI_FUNC(pdev->devfn)) - return -ENODEV; - } - rc = pcim_enable_device(pdev); if (rc) return rc; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c8d44a7..ac3d120 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3346,6 +3346,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices where NCQ should be avoided */ /* NCQ is slow */ { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, + /* http://thread.gmane.org/gmane.linux.ide/14907 */ + { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, /* Devices with NCQ limits */ @@ -5680,6 +5682,8 @@ static void ata_host_release(struct device *gendev, void *res) if (host->ops->host_stop) host->ops->host_stop(host); + + dev_set_drvdata(gendev, NULL); } /** @@ -5902,7 +5906,6 @@ int ata_device_add(const struct ata_probe_ent *ent) err_out: devres_release_group(dev, ata_device_add); - dev_set_drvdata(dev, NULL); VPRINTK("EXIT, returning %d\n", rc); return 0; } diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index c1334c6..8ff2d58 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -306,7 +306,6 @@ static void __devexit cs5520_remove_one(struct pci_dev *pdev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); - dev_set_drvdata(dev, NULL); } /** diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index d5f2e85..1a61cc8 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -128,7 +128,6 @@ static void isapnp_remove_one(struct pnp_dev *idev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); - dev_set_drvdata(dev, NULL); } static struct pnp_device_id isapnp_devices[] = { diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 7a635dd..47d0f94 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -202,49 +202,20 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i }; struct ata_port_info *port_info[2] = { &info, &info }; - u32 reg; - - /* PATA controller is fn 1, AHCI is fn 0 */ - if (id->driver_data != 368 && PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - /* The 365/66 have two PATA channels, redirect the second */ - if (id->driver_data == 365 || id->driver_data == 366) { - pci_read_config_dword(pdev, 0x80, ®); - reg |= (1 << 24); /* IDE1 to PATA IDE secondary */ - pci_write_config_dword(pdev, 0x80, reg); - } - return ata_pci_init_one(pdev, port_info, 2); } -static int jmicron_reinit_one(struct pci_dev *pdev) -{ - u32 reg; - - switch(pdev->device) { - case PCI_DEVICE_ID_JMICRON_JMB368: - break; - case PCI_DEVICE_ID_JMICRON_JMB365: - case PCI_DEVICE_ID_JMICRON_JMB366: - /* Restore mapping or disks swap and boy does it get ugly */ - pci_read_config_dword(pdev, 0x80, ®); - reg |= (1 << 24); /* IDE1 to PATA IDE secondary */ - pci_write_config_dword(pdev, 0x80, reg); - /* Fall through */ - default: - /* Make sure AHCI is turned back on */ - pci_write_config_byte(pdev, 0x41, 0xa1); - } - return ata_pci_device_resume(pdev); -} - static const struct pci_device_id jmicron_pci_tbl[] = { - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 365}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 366}, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 368}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 361 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 363 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 365 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 366 }, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 368 }, { } /* terminate list */ }; @@ -255,7 +226,7 @@ static struct pci_driver jmicron_pci_driver = { .probe = jmicron_init_one, .remove = ata_pci_remove_one, .suspend = ata_pci_device_suspend, - .resume = jmicron_reinit_one, + .resume = ata_pci_device_resume, }; static int __init jmicron_init(void) diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 02ea95f..4b82a54 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -228,7 +228,6 @@ static int __devexit pata_platform_remove(struct platform_device *pdev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); - dev_set_drvdata(dev, NULL); return 0; } diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 5d083f4..b1bab82 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -647,7 +647,6 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, struct sil24_sge *sge) { struct scatterlist *sg; - unsigned int idx = 0; ata_for_each_sg(sg, qc) { sge->addr = cpu_to_le64(sg_dma_address(sg)); @@ -656,9 +655,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, sge->flags = cpu_to_le32(SGE_TRM); else sge->flags = 0; - sge++; - idx++; } } diff --git a/drivers/block/umem.c b/drivers/block/umem.c index dff3766..5872036 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -1179,8 +1179,10 @@ static int __init mm_init(void) return -ENOMEM; err = major_nr = register_blkdev(0, "umem"); - if (err < 0) + if (err < 0) { + pci_unregister_driver(&mm_pci_driver); return -EIO; + } for (i = 0; i < num_cards; i++) { mm_gendisk[i] = alloc_disk(1 << MM_SHIFT); @@ -1207,6 +1209,7 @@ static int __init mm_init(void) return 0; out: + pci_unregister_driver(&mm_pci_driver); unregister_blkdev(major_nr, "umem"); while (i--) put_disk(mm_gendisk[i]); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f24c26d..e453268 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1901,6 +1901,20 @@ static int init_dev(struct tty_driver *driver, int idx, /* check whether we're reopening an existing tty */ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { tty = devpts_get_tty(idx); + /* + * If we don't have a tty here on a slave open, it's because + * the master already started the close process and there's + * no relation between devpts file and tty anymore. + */ + if (!tty && driver->subtype == PTY_TYPE_SLAVE) { + retval = -EIO; + goto end_init; + } + /* + * It's safe from now on because init_dev() is called with + * tty_mutex held and release_dev() won't change tty->count + * or tty->flags without having to grab tty_mutex + */ if (tty && driver->subtype == PTY_TYPE_MASTER) tty = tty->link; } else { diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7452399..f4ee1af 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -667,7 +667,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (item.format != HID_ITEM_FORMAT_SHORT) { dbg("unexpected long global item"); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -676,7 +675,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (dispatch_type[item.type](parser, &item)) { dbg("item %u %u %u %u parsing failed\n", item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -685,14 +683,12 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (start == end) { if (parser->collection_stack_ptr) { dbg("unbalanced collection at end of report description"); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; } if (parser->local.delimiter_depth) { dbg("unbalanced delimiter at end of report description"); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -703,7 +699,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) } dbg("item fetching failed at offset %d\n", (int)(end - start)); - kfree(device->collection); hid_free_device(device); kfree(parser); return NULL; @@ -880,7 +875,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data) /* make sure the unused bits in the last byte are zeros */ if (count > 0 && size > 0) - data[(count*size-1)/8] = 0; + data[(offset+count*size-1)/8] = 0; for (n = 0; n < count; n++) { if (field->logical_minimum < 0) /* signed values */ diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 89241be..83c4126 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -29,6 +29,7 @@ */ #include +#include struct hid_usage_entry { unsigned page; diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 25d180a..c843402 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -2,7 +2,7 @@ * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik - * Copyright (c) 2006 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina * * HID to Linux Input mapping */ @@ -71,7 +71,6 @@ static const struct { #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) -#define map_rel_clear(c) do { map_rel(c); clear_bit(c, bit); } while (0) #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) #ifdef CONFIG_USB_HIDINPUT_POWERBOOK @@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } } - map_key_clear(code); + map_key(code); break; @@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: if (field->flags & HID_MAIN_ITEM_RELATIVE) - map_rel_clear(usage->hid & 0xf); + map_rel(usage->hid & 0xf); else - map_abs_clear(usage->hid & 0xf); + map_abs(usage->hid & 0xf); break; case HID_GD_HATSWITCH: @@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x22f: map_key_clear(KEY_ZOOMRESET); break; case 0x233: map_key_clear(KEY_SCROLLUP); break; case 0x234: map_key_clear(KEY_SCROLLDOWN); break; - case 0x238: map_rel_clear(REL_HWHEEL); break; + case 0x238: map_rel(REL_HWHEEL); break; case 0x25f: map_key_clear(KEY_CANCEL); break; case 0x279: map_key_clear(KEY_REDO); break; @@ -532,6 +531,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x302: map_key_clear(KEY_PROG2); break; case 0x303: map_key_clear(KEY_PROG3); break; + /* Reported on Logitech S510 wireless keyboard */ + case 0x101f: map_key_clear(KEY_ZOOMIN); break; + case 0x1020: map_key_clear(KEY_ZOOMOUT); break; + case 0x1021: map_key_clear(KEY_ZOOMRESET); break; + /* this one is marked as 'Rotate' */ + case 0x1028: map_key_clear(KEY_ANGLE); break; + case 0x1029: map_key_clear(KEY_SHUFFLE); break; + case 0x1041: map_key_clear(KEY_BATTERY); break; + case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; + case 0x1043: map_key_clear(KEY_SPREADSHEET); break; + case 0x1044: map_key_clear(KEY_PRESENTATION); break; + case 0x1045: map_key_clear(KEY_UNDO); break; + case 0x1046: map_key_clear(KEY_REDO); break; + case 0x1047: map_key_clear(KEY_PRINT); break; + case 0x1048: map_key_clear(KEY_SAVE); break; + case 0x1049: map_key_clear(KEY_PROG1); break; + case 0x104a: map_key_clear(KEY_PROG2); break; + case 0x104b: map_key_clear(KEY_PROG3); break; + case 0x104c: map_key_clear(KEY_PROG4); break; + default: goto ignore; } break; @@ -647,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(usage->type, input->evbit); + if (device->quirks & HID_QUIRK_DUPLICATE_USAGES && + (usage->type == EV_KEY || + usage->type == EV_REL || + usage->type == EV_ABS)) + clear_bit(usage->code, bit); + while (usage->code <= max && test_and_set_bit(usage->code, bit)) usage->code = find_next_zero_bit(bit, max + 1, usage->code); diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index 8b6c9a4..c921d6c 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -2,13 +2,25 @@ # Config.in for the CAPI subsystem # config ISDN_DRV_AVMB1_VERBOSE_REASON - bool "Verbose reason code reporting (kernel size +=7K)" + bool "Verbose reason code reporting" depends on ISDN_CAPI + default y help - If you say Y here, the AVM B1 driver will give verbose reasons for + If you say Y here, the CAPI drivers will give verbose reasons for disconnecting. This will increase the size of the kernel by 7 KB. If unsure, say Y. +config CAPI_TRACE + bool "CAPI trace support" + depends on ISDN_CAPI + default y + help + If you say Y here, the kernelcapi driver can make verbose traces + of CAPI messages. This feature can be enabled/disabled via IOCTL for + every controler (default disabled). + This will increase the size of the kernelcapi module by 20 KB. + If unsure, say Y. + config ISDN_CAPI_MIDDLEWARE bool "CAPI2.0 Middleware support (EXPERIMENTAL)" depends on ISDN_CAPI && EXPERIMENTAL diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 2a49cea..23b6f7b 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -990,6 +990,7 @@ static void handle_plci(_cmsg * cmsg) capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); capidrv_plci *plcip; isdn_ctrl cmd; + _cdebbuf *cdb; if (!card) { printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", @@ -1122,8 +1123,15 @@ static void handle_plci(_cmsg * cmsg) break; } } - printk(KERN_ERR "capidrv-%d: %s\n", - card->contrnr, capi_cmsg2str(cmsg)); + cdb = capi_cmsg2str(cmsg); + if (cdb) { + printk(KERN_WARNING "capidrv-%d: %s\n", + card->contrnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n", + card->contrnr, cmsg->InfoNumber); + break; case CAPI_CONNECT_ACTIVE_CONF: /* plci */ @@ -1371,10 +1379,18 @@ static _cmsg s_cmsg; static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 3) - printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", - ap->applid, capi_cmsg2str(&s_cmsg)); - + if (debugmode > 3) { + _cdebbuf *cdb = capi_cmsg2str(&s_cmsg); + + if (cdb) { + printk(KERN_DEBUG "%s: applid=%d %s\n", __FUNCTION__, + ap->applid, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "%s: applid=%d %s not traced\n", + __FUNCTION__, ap->applid, + capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand)); + } if (s_cmsg.Command == CAPI_DATA_B3 && s_cmsg.Subcommand == CAPI_IND) { handle_data(&s_cmsg, skb); diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index c1b2155..ad1e270 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd) /*-------------------------------------------------------*/ + +#ifdef CONFIG_CAPI_TRACE + /*-------------------------------------------------------*/ static char *pnames[] = @@ -703,44 +706,77 @@ static char *pnames[] = }; -static char buf[8192]; -static char *p = NULL; #include /*-------------------------------------------------------*/ -static void bufprint(char *fmt,...) +static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...) { va_list f; + size_t n,r; + + if (!cdb) + return NULL; va_start(f, fmt); - vsprintf(p, fmt, f); + r = cdb->size - cdb->pos; + n = vsnprintf(cdb->p, r, fmt, f); va_end(f); - p += strlen(p); + if (n >= r) { + /* truncated, need bigger buffer */ + size_t ns = 2 * cdb->size; + u_char *nb; + + while ((ns - cdb->pos) <= n) + ns *= 2; + nb = kmalloc(ns, GFP_ATOMIC); + if (!nb) { + cdebbuf_free(cdb); + return NULL; + } + memcpy(nb, cdb->buf, cdb->pos); + kfree(cdb->buf); + nb[cdb->pos] = 0; + cdb->buf = nb; + cdb->p = cdb->buf + cdb->pos; + cdb->size = ns; + va_start(f, fmt); + r = cdb->size - cdb->pos; + n = vsnprintf(cdb->p, r, fmt, f); + va_end(f); + } + cdb->p += n; + cdb->pos += n; + return cdb; } -static void printstructlen(u8 * m, unsigned len) +static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len) { unsigned hex = 0; + + if (!cdb) + return NULL; for (; len; len--, m++) if (isalnum(*m) || *m == ' ') { if (hex) - bufprint(">"); - bufprint("%c", *m); + cdb = bufprint(cdb, ">"); + cdb = bufprint(cdb, "%c", *m); hex = 0; } else { if (!hex) - bufprint("<%02x", *m); + cdb = bufprint(cdb, "<%02x", *m); else - bufprint(" %02x", *m); + cdb = bufprint(cdb, " %02x", *m); hex = 1; } if (hex) - bufprint(">"); + cdb = bufprint(cdb, ">"); + return cdb; } -static void printstruct(u8 * m) +static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m) { unsigned len; + if (m[0] != 0xff) { len = m[0]; m += 1; @@ -748,42 +784,45 @@ static void printstruct(u8 * m) len = ((u16 *) (m + 1))[0]; m += 3; } - printstructlen(m, len); + cdb = printstructlen(cdb, m, len); + return cdb; } /*-------------------------------------------------------*/ #define NAME (pnames[cmsg->par[cmsg->p]]) -static void protocol_message_2_pars(_cmsg * cmsg, int level) +static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level) { for (; TYP != _CEND; cmsg->p++) { int slen = 29 + 3 - level; int i; - bufprint(" "); + if (!cdb) + return NULL; + cdb = bufprint(cdb, " "); for (i = 0; i < level - 1; i++) - bufprint(" "); + cdb = bufprint(cdb, " "); switch (TYP) { case _CBYTE: - bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); cmsg->l++; break; case _CWORD: - bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); cmsg->l += 2; break; case _CDWORD: - bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); cmsg->l += 4; break; case _CSTRUCT: - bufprint("%-*s = ", slen, NAME); + cdb = bufprint(cdb, "%-*s = ", slen, NAME); if (cmsg->m[cmsg->l] == '\0') - bufprint("default"); + cdb = bufprint(cdb, "default"); else - printstruct(cmsg->m + cmsg->l); - bufprint("\n"); + cdb = printstruct(cdb, cmsg->m + cmsg->l); + cdb = bufprint(cdb, "\n"); if (cmsg->m[cmsg->l] != 0xff) cmsg->l += 1 + cmsg->m[cmsg->l]; else @@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level) case _CMSTRUCT: /*----- Metastruktur 0 -----*/ if (cmsg->m[cmsg->l] == '\0') { - bufprint("%-*s = default\n", slen, NAME); + cdb = bufprint(cdb, "%-*s = default\n", slen, NAME); cmsg->l++; jumpcstruct(cmsg); } else { char *name = NAME; unsigned _l = cmsg->l; - bufprint("%-*s\n", slen, name); + cdb = bufprint(cdb, "%-*s\n", slen, name); cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; cmsg->p++; - protocol_message_2_pars(cmsg, level + 1); + cdb = protocol_message_2_pars(cdb, cmsg, level + 1); } break; } } + return cdb; } /*-------------------------------------------------------*/ -char *capi_message2str(u8 * msg) + +static _cdebbuf *g_debbuf; +static u_long g_debbuf_lock; +static _cmsg *g_cmsg; + +_cdebbuf *cdebbuf_alloc(void) { + _cdebbuf *cdb; + + if (likely(!test_and_set_bit(1, &g_debbuf_lock))) { + cdb = g_debbuf; + goto init; + } else + cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC); + if (!cdb) + return NULL; + cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC); + if (!cdb->buf) { + kfree(cdb); + return NULL; + } + cdb->size = CDEBUG_SIZE; +init: + cdb->buf[0] = 0; + cdb->p = cdb->buf; + cdb->pos = 0; + return cdb; +} - _cmsg cmsg; - p = buf; - p[0] = 0; +void cdebbuf_free(_cdebbuf *cdb) +{ + if (likely(cdb == g_debbuf)) { + test_and_clear_bit(1, &g_debbuf_lock); + return; + } + if (likely(cdb)) + kfree(cdb->buf); + kfree(cdb); +} - cmsg.m = msg; - cmsg.l = 8; - cmsg.p = 0; - byteTRcpy(cmsg.m + 4, &cmsg.Command); - byteTRcpy(cmsg.m + 5, &cmsg.Subcommand); - cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)]; - bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", - mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], +_cdebbuf *capi_message2str(u8 * msg) +{ + _cdebbuf *cdb; + _cmsg *cmsg; + + cdb = cdebbuf_alloc(); + if (unlikely(!cdb)) + return NULL; + if (likely(cdb == g_debbuf)) + cmsg = g_cmsg; + else + cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC); + if (unlikely(!cmsg)) { + cdebbuf_free(cdb); + return NULL; + } + cmsg->m = msg; + cmsg->l = 8; + cmsg->p = 0; + byteTRcpy(cmsg->m + 4, &cmsg->Command); + byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); + cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)]; + + cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n", + mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], ((unsigned short *) msg)[1], ((unsigned short *) msg)[3], ((unsigned short *) msg)[0]); - protocol_message_2_pars(&cmsg, 1); - return buf; + cdb = protocol_message_2_pars(cdb, cmsg, 1); + if (unlikely(cmsg != g_cmsg)) + kfree(cmsg); + return cdb; } -char *capi_cmsg2str(_cmsg * cmsg) +_cdebbuf *capi_cmsg2str(_cmsg * cmsg) { - p = buf; - p[0] = 0; + _cdebbuf *cdb; + + cdb = cdebbuf_alloc(); + if (!cdb) + return NULL; cmsg->l = 8; cmsg->p = 0; - bufprint("%s ID=%03d #0x%04x LEN=%04d\n", + cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], ((u16 *) cmsg->m)[1], ((u16 *) cmsg->m)[3], ((u16 *) cmsg->m)[0]); - protocol_message_2_pars(cmsg, 1); - return buf; + cdb = protocol_message_2_pars(cdb, cmsg, 1); + return cdb; } +int __init cdebug_init(void) +{ + g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL); + if (!g_cmsg) + return ENOMEM; + g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL); + if (!g_debbuf) { + kfree(g_cmsg); + return ENOMEM; + } + g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL); + if (!g_debbuf->buf) { + kfree(g_cmsg); + kfree(g_debbuf); + return ENOMEM;; + } + g_debbuf->size = CDEBUG_GSIZE; + g_debbuf->buf[0] = 0; + g_debbuf->p = g_debbuf->buf; + g_debbuf->pos = 0; + return 0; +} + +void __exit cdebug_exit(void) +{ + if (g_debbuf) + kfree(g_debbuf->buf); + kfree(g_debbuf); + kfree(g_cmsg); +} + +#else /* !CONFIG_CAPI_TRACE */ + +static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0}; + +_cdebbuf *capi_message2str(u8 * msg) +{ + return &g_debbuf; +} + +_cdebbuf *capi_cmsg2str(_cmsg * cmsg) +{ + return &g_debbuf; +} + +_cdebbuf *cdebbuf_alloc(void) +{ + return &g_debbuf; +} + +void cdebbuf_free(_cdebbuf *cdb) +{ +} + +int __init cdebug_init(void) +{ + return 0; +} + +void __exit cdebug_exit(void) +{ +} + +#endif + +EXPORT_SYMBOL(cdebbuf_alloc); +EXPORT_SYMBOL(cdebbuf_free); EXPORT_SYMBOL(capi_cmsg2message); EXPORT_SYMBOL(capi_message2cmsg); EXPORT_SYMBOL(capi_cmsg_header); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 783a255..3ed34f7 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -276,10 +276,17 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s int showctl = 0; u8 cmd, subcmd; unsigned long flags; + _cdebbuf *cdb; if (card->cardstate != CARD_RUNNING) { - printk(KERN_INFO "kcapi: controller %d not active, got: %s", - card->cnr, capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", + card->cnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", + card->cnr); goto error; } @@ -295,15 +302,21 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s showctl |= (card->traceflag & 1); if (showctl & 2) { if (showctl & 1) { - printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n", - (unsigned long) card->cnr, - CAPIMSG_APPID(skb->data), + printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", + card->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { - printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n", - (unsigned long) card->cnr, - capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_DEBUG "kcapi: got [%03d] %s\n", + card->cnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", + card->cnr, CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); } } @@ -312,8 +325,15 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); if ((!ap) || (ap->release_in_progress)) { read_unlock_irqrestore(&application_lock, flags); - printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", - CAPIMSG_APPID(skb->data), capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", + CAPIMSG_APPID(skb->data), cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n", + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd)); goto error; } skb_queue_tail(&ap->recv_queue, skb); @@ -332,7 +352,7 @@ void capi_ctr_ready(struct capi_ctr * card) { card->cardstate = CARD_RUNNING; - printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", + printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n", card->cnr, card->name); notify_push(KCI_CONTRUP, card->cnr, 0, 0); @@ -364,7 +384,7 @@ void capi_ctr_reseted(struct capi_ctr * card) capi_ctr_put(card); } - printk(KERN_NOTICE "kcapi: card %d down.\n", card->cnr); + printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr); notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); } @@ -374,7 +394,7 @@ EXPORT_SYMBOL(capi_ctr_reseted); void capi_ctr_suspend_output(struct capi_ctr *card) { if (!card->blocked) { - printk(KERN_DEBUG "kcapi: card %d suspend\n", card->cnr); + printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr); card->blocked = 1; } } @@ -384,7 +404,7 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); void capi_ctr_resume_output(struct capi_ctr *card) { if (card->blocked) { - printk(KERN_DEBUG "kcapi: card %d resume\n", card->cnr); + printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr); card->blocked = 0; } } @@ -432,7 +452,7 @@ attach_capi_ctr(struct capi_ctr *card) } ncards++; - printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n", + printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", card->cnr, card->name); return 0; } @@ -451,7 +471,7 @@ int detach_capi_ctr(struct capi_ctr *card) card->procent = NULL; } capi_cards[card->cnr - 1] = NULL; - printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n", + printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n", card->cnr, card->name); return 0; @@ -623,17 +643,25 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) showctl |= (card->traceflag & 1); if (showctl & 2) { if (showctl & 1) { - printk(KERN_DEBUG "kcapi: put [%#x] id#%d %s len=%u\n", + printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", CAPIMSG_CONTROLLER(skb->data), CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { - printk(KERN_DEBUG "kcapi: put [%#x] %s\n", - CAPIMSG_CONTROLLER(skb->data), - capi_message2str(skb->data)); + _cdebbuf *cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_DEBUG "kcapi: put [%03d] %s\n", + CAPIMSG_CONTROLLER(skb->data), + cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n", + CAPIMSG_CONTROLLER(skb->data), + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); } - } return card->send_message(card, skb); } @@ -894,7 +922,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) return -ESRCH; card->traceflag = fdef.flag; - printk(KERN_INFO "kcapi: contr %d set trace=%d\n", + printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", card->cnr, card->traceflag); return 0; } @@ -967,7 +995,11 @@ static int __init kcapi_init(void) { char *p; char rev[32]; + int ret; + ret = cdebug_init(); + if (ret) + return ret; kcapi_proc_init(); if ((p = strchr(revision, ':')) != 0 && p[1]) { @@ -988,6 +1020,7 @@ static void __exit kcapi_exit(void) /* make sure all notifiers are finished */ flush_scheduled_work(); + cdebug_exit(); } module_init(kcapi_init); diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index 5158be0..e9d3189 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,8 +1,9 @@ gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o usb_gigaset-y := usb-gigaset.o -bas_gigaset-y := bas-gigaset.o isocdata.o ser_gigaset-y := ser-gigaset.o +bas_gigaset-y := bas-gigaset.o isocdata.o -obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o -obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o -obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o gigaset.o +obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset.o +obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o +obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o +obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index f2f108f..00a3be5 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -13,11 +13,6 @@ * ===================================================================== */ -/* not set by Kbuild when building both ser_gigaset and usb_gigaset */ -#ifndef KBUILD_MODNAME -#define KBUILD_MODNAME "asy_gigaset" -#endif - #include "gigaset.h" #include #include diff --git a/drivers/md/md.c b/drivers/md/md.c index 05febfd..6c06e82 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1296,27 +1296,17 @@ static struct super_type super_types[] = { .sync_super = super_1_sync, }, }; - -static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev) -{ - struct list_head *tmp; - mdk_rdev_t *rdev; - - ITERATE_RDEV(mddev,rdev,tmp) - if (rdev->bdev->bd_contains == dev->bdev->bd_contains) - return rdev; - - return NULL; -} static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) { - struct list_head *tmp; - mdk_rdev_t *rdev; + struct list_head *tmp, *tmp2; + mdk_rdev_t *rdev, *rdev2; ITERATE_RDEV(mddev1,rdev,tmp) - if (match_dev_unit(mddev2, rdev)) - return 1; + ITERATE_RDEV(mddev2, rdev2, tmp2) + if (rdev->bdev->bd_contains == + rdev2->bdev->bd_contains) + return 1; return 0; } @@ -1325,8 +1315,7 @@ static LIST_HEAD(pending_raid_disks); static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) { - mdk_rdev_t *same_pdev; - char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + char b[BDEVNAME_SIZE]; struct kobject *ko; char *s; @@ -1342,14 +1331,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) else mddev->size = rdev->size; } - same_pdev = match_dev_unit(mddev, rdev); - if (same_pdev) - printk(KERN_WARNING - "%s: WARNING: %s appears to be on the same physical" - " disk as %s. True\n protection against single-disk" - " failure might be compromised.\n", - mdname(mddev), bdevname(rdev->bdev,b), - bdevname(same_pdev->bdev,b2)); /* Verify rdev->desc_nr is unique. * If it is -1, assign a free number, else @@ -3109,6 +3090,36 @@ static int do_md_run(mddev_t * mddev) return -EINVAL; } + if (pers->sync_request) { + /* Warn if this is a potentially silly + * configuration. + */ + char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + mdk_rdev_t *rdev2; + struct list_head *tmp2; + int warned = 0; + ITERATE_RDEV(mddev, rdev, tmp) { + ITERATE_RDEV(mddev, rdev2, tmp2) { + if (rdev < rdev2 && + rdev->bdev->bd_contains == + rdev2->bdev->bd_contains) { + printk(KERN_WARNING + "%s: WARNING: %s appears to be" + " on the same physical disk as" + " %s.\n", + mdname(mddev), + bdevname(rdev->bdev,b), + bdevname(rdev2->bdev,b2)); + warned = 1; + } + } + } + if (warned) + printk(KERN_WARNING + "True protection against single-disk" + " failure might be compromised.\n"); + } + mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->barriers_work = 1; @@ -3311,6 +3322,9 @@ static int do_md_stop(mddev_t * mddev, int mode) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); mddev->pers->stop(mddev); + mddev->queue->merge_bvec_fn = NULL; + mddev->queue->unplug_fn = NULL; + mddev->queue->issue_flush_fn = NULL; if (mddev->pers->sync_request) sysfs_remove_group(&mddev->kobj, &md_redundancy_group); @@ -5343,6 +5357,44 @@ void md_do_sync(mddev_t *mddev) EXPORT_SYMBOL_GPL(md_do_sync); +static int remove_and_add_spares(mddev_t *mddev) +{ + mdk_rdev_t *rdev; + struct list_head *rtmp; + int spares = 0; + + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk >= 0 && + (test_bit(Faulty, &rdev->flags) || + ! test_bit(In_sync, &rdev->flags)) && + atomic_read(&rdev->nr_pending)==0) { + if (mddev->pers->hot_remove_disk( + mddev, rdev->raid_disk)==0) { + char nm[20]; + sprintf(nm,"rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + rdev->raid_disk = -1; + } + } + + if (mddev->degraded) { + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk < 0 + && !test_bit(Faulty, &rdev->flags)) { + rdev->recovery_offset = 0; + if (mddev->pers->hot_add_disk(mddev,rdev)) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, + &rdev->kobj, nm); + spares++; + md_new_event(mddev); + } else + break; + } + } + return spares; +} /* * This routine is regularly called by all per-raid-array threads to * deal with generic issues like resync and super-block update. @@ -5397,7 +5449,7 @@ void md_check_recovery(mddev_t *mddev) return; if (mddev_trylock(mddev)) { - int spares =0; + int spares = 0; spin_lock_irq(&mddev->write_lock); if (mddev->safemode && !atomic_read(&mddev->writes_pending) && @@ -5460,35 +5512,13 @@ void md_check_recovery(mddev_t *mddev) * Spare are also removed and re-added, to allow * the personality to fail the re-add. */ - ITERATE_RDEV(mddev,rdev,rtmp) - if (rdev->raid_disk >= 0 && - (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && - atomic_read(&rdev->nr_pending)==0) { - if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { - char nm[20]; - sprintf(nm,"rd%d", rdev->raid_disk); - sysfs_remove_link(&mddev->kobj, nm); - rdev->raid_disk = -1; - } - } - - if (mddev->degraded) { - ITERATE_RDEV(mddev,rdev,rtmp) - if (rdev->raid_disk < 0 - && !test_bit(Faulty, &rdev->flags)) { - rdev->recovery_offset = 0; - if (mddev->pers->hot_add_disk(mddev,rdev)) { - char nm[20]; - sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); - spares++; - md_new_event(mddev); - } else - break; - } - } - if (spares) { + if (mddev->reshape_position != MaxSector) { + if (mddev->pers->check_reshape(mddev) != 0) + /* Cannot proceed */ + goto unlock; + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + } else if ((spares = remove_and_add_spares(mddev))) { clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); } else if (mddev->recovery_cp < MaxSector) { diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a9401c0..82249a6 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -429,7 +429,7 @@ static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev) if (dev < 0) dev += conf->raid_disks; } else { - while (sector > conf->stride) { + while (sector >= conf->stride) { sector -= conf->stride; if (dev < conf->near_copies) dev += conf->raid_disks - conf->near_copies; @@ -1801,6 +1801,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (k=0; kcopies; k++) if (r10_bio->devs[k].devnum == i) break; + BUG_ON(k == conf->copies); bio = r10_bio->devs[1].bio; bio->bi_next = biolist; biolist = bio; @@ -2021,19 +2022,30 @@ static int run(mddev_t *mddev) if (!conf->tmppage) goto out_free_conf; + conf->mddev = mddev; + conf->raid_disks = mddev->raid_disks; conf->near_copies = nc; conf->far_copies = fc; conf->copies = nc*fc; conf->far_offset = fo; conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1; conf->chunk_shift = ffz(~mddev->chunk_size) - 9; + size = mddev->size >> (conf->chunk_shift-1); + sector_div(size, fc); + size = size * conf->raid_disks; + sector_div(size, nc); + /* 'size' is now the number of chunks in the array */ + /* calculate "used chunks per device" in 'stride' */ + stride = size * conf->copies; + sector_div(stride, conf->raid_disks); + mddev->size = stride << (conf->chunk_shift-1); + if (fo) - conf->stride = 1 << conf->chunk_shift; - else { - stride = mddev->size >> (conf->chunk_shift-1); + stride = 1; + else sector_div(stride, fc); - conf->stride = stride << conf->chunk_shift; - } + conf->stride = stride << conf->chunk_shift; + conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, r10bio_pool_free, conf); if (!conf->r10bio_pool) { @@ -2063,8 +2075,6 @@ static int run(mddev_t *mddev) disk->head_position = 0; } - conf->raid_disks = mddev->raid_disks; - conf->mddev = mddev; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); @@ -2106,16 +2116,8 @@ static int run(mddev_t *mddev) /* * Ok, everything is just fine now */ - if (conf->far_offset) { - size = mddev->size >> (conf->chunk_shift-1); - size *= conf->raid_disks; - size <<= conf->chunk_shift; - sector_div(size, conf->far_copies); - } else - size = conf->stride * conf->raid_disks; - sector_div(size, conf->near_copies); - mddev->array_size = size/2; - mddev->resync_max_sectors = size; + mddev->array_size = size << (conf->chunk_shift-1); + mddev->resync_max_sectors = size << conf->chunk_shift; mddev->queue->unplug_fn = raid10_unplug; mddev->queue->issue_flush_fn = raid10_issue_flush; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 11c3d7b..d247429 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1050,7 +1050,7 @@ static void compute_parity5(struct stripe_head *sh, int method) static void compute_parity6(struct stripe_head *sh, int method) { raid6_conf_t *conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count; + int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = sh->disks, count; struct bio *chosen; /**** FIX THIS: This could be very bad if disks is close to 256 ****/ void *ptrs[disks]; @@ -1131,8 +1131,7 @@ static void compute_parity6(struct stripe_head *sh, int method) /* Compute one missing block */ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) { - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; void *ptr[MAX_XOR_BLOCKS], *p; int pd_idx = sh->pd_idx; int qd_idx = raid6_next_disk(pd_idx, disks); @@ -1170,8 +1169,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) /* Compute two missing blocks */ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) { - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; int pd_idx = sh->pd_idx; int qd_idx = raid6_next_disk(pd_idx, disks); int d0_idx = raid6_next_disk(qd_idx, disks); @@ -1887,11 +1885,11 @@ static void handle_stripe5(struct stripe_head *sh) static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) { raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks; + int disks = sh->disks; struct bio *return_bi= NULL; struct bio *bi; int i; - int syncing; + int syncing, expanding, expanded; int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; int non_overwrite = 0; int failed_num[2] = {0, 0}; @@ -1909,6 +1907,8 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) clear_bit(STRIPE_DELAYED, &sh->state); syncing = test_bit(STRIPE_SYNCING, &sh->state); + expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); + expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); /* Now to look around and see what can be done */ rcu_read_lock(); @@ -2114,13 +2114,15 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) { + if (to_read || non_overwrite || (to_write && failed) || + (syncing && (uptodate < disks)) || expanding) { for (i=disks; i--;) { dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread || (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || syncing || + expanding || (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) || (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write)) ) @@ -2355,6 +2357,79 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) } } } + + if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { + /* Need to write out all blocks after computing P&Q */ + sh->disks = conf->raid_disks; + sh->pd_idx = stripe_to_pdidx(sh->sector, conf, + conf->raid_disks); + compute_parity6(sh, RECONSTRUCT_WRITE); + for (i = conf->raid_disks ; i-- ; ) { + set_bit(R5_LOCKED, &sh->dev[i].flags); + locked++; + set_bit(R5_Wantwrite, &sh->dev[i].flags); + } + clear_bit(STRIPE_EXPANDING, &sh->state); + } else if (expanded) { + clear_bit(STRIPE_EXPAND_READY, &sh->state); + atomic_dec(&conf->reshape_stripes); + wake_up(&conf->wait_for_overlap); + md_done_sync(conf->mddev, STRIPE_SECTORS, 1); + } + + if (expanding && locked == 0) { + /* We have read all the blocks in this stripe and now we need to + * copy some of them into a target stripe for expand. + */ + clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); + for (i = 0; i < sh->disks ; i++) + if (i != pd_idx && i != qd_idx) { + int dd_idx2, pd_idx2, j; + struct stripe_head *sh2; + + sector_t bn = compute_blocknr(sh, i); + sector_t s = raid5_compute_sector( + bn, conf->raid_disks, + conf->raid_disks - conf->max_degraded, + &dd_idx2, &pd_idx2, conf); + sh2 = get_active_stripe(conf, s, + conf->raid_disks, + pd_idx2, 1); + if (sh2 == NULL) + /* so for only the early blocks of + * this stripe have been requests. + * When later blocks get requests, we + * will try again + */ + continue; + if (!test_bit(STRIPE_EXPANDING, &sh2->state) || + test_bit(R5_Expanded, + &sh2->dev[dd_idx2].flags)) { + /* must have already done this block */ + release_stripe(sh2); + continue; + } + memcpy(page_address(sh2->dev[dd_idx2].page), + page_address(sh->dev[i].page), + STRIPE_SIZE); + set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags); + set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags); + for (j = 0 ; j < conf->raid_disks ; j++) + if (j != sh2->pd_idx && + j != raid6_next_disk(sh2->pd_idx, + sh2->disks) && + !test_bit(R5_Expanded, + &sh2->dev[j].flags)) + break; + if (j == conf->raid_disks) { + set_bit(STRIPE_EXPAND_READY, + &sh2->state); + set_bit(STRIPE_HANDLE, &sh2->state); + } + release_stripe(sh2); + } + } + spin_unlock(&sh->lock); while ((bi=return_bi)) { @@ -2395,7 +2470,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) rcu_read_unlock(); if (rdev) { - if (syncing) + if (syncing || expanding || expanded) md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; @@ -2915,8 +2990,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped struct stripe_head *sh; int pd_idx; sector_t first_sector, last_sector; - int raid_disks; - int data_disks; + int raid_disks = conf->previous_raid_disks; + int data_disks = raid_disks - conf->max_degraded; + int new_data_disks = conf->raid_disks - conf->max_degraded; int i; int dd_idx; sector_t writepos, safepos, gap; @@ -2925,7 +3001,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped conf->expand_progress != 0) { /* restarting in the middle, skip the initial sectors */ sector_nr = conf->expand_progress; - sector_div(sector_nr, conf->raid_disks-1); + sector_div(sector_nr, new_data_disks); *skipped = 1; return sector_nr; } @@ -2939,14 +3015,14 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped * to after where expand_lo old_maps to */ writepos = conf->expand_progress + - conf->chunk_size/512*(conf->raid_disks-1); - sector_div(writepos, conf->raid_disks-1); + conf->chunk_size/512*(new_data_disks); + sector_div(writepos, new_data_disks); safepos = conf->expand_lo; - sector_div(safepos, conf->previous_raid_disks-1); + sector_div(safepos, data_disks); gap = conf->expand_progress - conf->expand_lo; if (writepos >= safepos || - gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { + gap > (new_data_disks)*3000*2 /*3Meg*/) { /* Cannot proceed until we've updated the superblock... */ wait_event(conf->wait_for_overlap, atomic_read(&conf->reshape_stripes)==0); @@ -2976,6 +3052,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped sector_t s; if (j == sh->pd_idx) continue; + if (conf->level == 6 && + j == raid6_next_disk(sh->pd_idx, sh->disks)) + continue; s = compute_blocknr(sh, j); if (s < (mddev->array_size<<1)) { skipped = 1; @@ -2999,21 +3078,20 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped * The source stripes are determined by mapping the first and last * block on the destination stripes. */ - raid_disks = conf->previous_raid_disks; - data_disks = raid_disks - 1; first_sector = - raid5_compute_sector(sector_nr*(conf->raid_disks-1), + raid5_compute_sector(sector_nr*(new_data_disks), raid_disks, data_disks, &dd_idx, &pd_idx, conf); last_sector = raid5_compute_sector((sector_nr+conf->chunk_size/512) - *(conf->raid_disks-1) -1, + *(new_data_disks) -1, raid_disks, data_disks, &dd_idx, &pd_idx, conf); if (last_sector >= (mddev->size<<1)) last_sector = (mddev->size<<1)-1; while (first_sector <= last_sector) { - pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); + pd_idx = stripe_to_pdidx(first_sector, conf, + conf->previous_raid_disks); sh = get_active_stripe(conf, first_sector, conf->previous_raid_disks, pd_idx, 0); set_bit(STRIPE_EXPAND_SOURCE, &sh->state); @@ -3348,35 +3426,44 @@ static int run(mddev_t *mddev) */ sector_t here_new, here_old; int old_disks; + int max_degraded = (mddev->level == 5 ? 1 : 2); if (mddev->new_level != mddev->level || mddev->new_layout != mddev->layout || mddev->new_chunk != mddev->chunk_size) { - printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n", + printk(KERN_ERR "raid5: %s: unsupported reshape " + "required - aborting.\n", mdname(mddev)); return -EINVAL; } if (mddev->delta_disks <= 0) { - printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n", + printk(KERN_ERR "raid5: %s: unsupported reshape " + "(reduce disks) required - aborting.\n", mdname(mddev)); return -EINVAL; } old_disks = mddev->raid_disks - mddev->delta_disks; /* reshape_position must be on a new-stripe boundary, and one - * further up in new geometry must map after here in old geometry. + * further up in new geometry must map after here in old + * geometry. */ here_new = mddev->reshape_position; - if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) { - printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n"); + if (sector_div(here_new, (mddev->chunk_size>>9)* + (mddev->raid_disks - max_degraded))) { + printk(KERN_ERR "raid5: reshape_position not " + "on a stripe boundary\n"); return -EINVAL; } /* here_new is the stripe we will write to */ here_old = mddev->reshape_position; - sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1)); - /* here_old is the first stripe that we might need to read from */ + sector_div(here_old, (mddev->chunk_size>>9)* + (old_disks-max_degraded)); + /* here_old is the first stripe that we might need to read + * from */ if (here_new >= here_old) { /* Reading from the same stripe as writing to - bad */ - printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n"); + printk(KERN_ERR "raid5: reshape_position too early for " + "auto-recovery - aborting.\n"); return -EINVAL; } printk(KERN_INFO "raid5: reshape will continue\n"); @@ -3814,6 +3901,8 @@ static int raid5_check_reshape(mddev_t *mddev) if (err) return err; + if (mddev->degraded > conf->max_degraded) + return -EINVAL; /* looks like we might be able to manage this */ return 0; } @@ -3827,8 +3916,7 @@ static int raid5_start_reshape(mddev_t *mddev) int added_devices = 0; unsigned long flags; - if (mddev->degraded || - test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; ITERATE_RDEV(mddev, rdev, rtmp) @@ -3836,7 +3924,7 @@ static int raid5_start_reshape(mddev_t *mddev) !test_bit(Faulty, &rdev->flags)) spares++; - if (spares < mddev->delta_disks-1) + if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded) /* Not enough devices even to make a degraded array * of that size */ @@ -3899,7 +3987,8 @@ static void end_reshape(raid5_conf_t *conf) struct block_device *bdev; if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { - conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1); + conf->mddev->array_size = conf->mddev->size * + (conf->raid_disks - conf->max_degraded); set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); conf->mddev->changed = 1; @@ -3972,6 +4061,10 @@ static struct mdk_personality raid6_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, +#ifdef CONFIG_MD_RAID5_RESHAPE + .check_reshape = raid5_check_reshape, + .start_reshape = raid5_start_reshape, +#endif .quiesce = raid5_quiesce, }; static struct mdk_personality raid5_personality = diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c index 359157a..6181a5a 100644 --- a/drivers/md/raid6mmx.c +++ b/drivers/md/raid6mmx.c @@ -30,14 +30,8 @@ const struct raid6_mmx_constants { static int raid6_have_mmx(void) { -#ifdef __KERNEL__ /* Not really "boot_cpu" but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX); -#else - /* User space test code */ - u32 features = cpuid_features(); - return ( (features & (1<<23)) == (1<<23) ); -#endif } /* @@ -48,13 +42,12 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -78,7 +71,7 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("pxor %mm4,%mm4"); } - raid6_after_mmx(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_mmxx1 = { @@ -96,13 +89,12 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -137,7 +129,7 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movq %%mm6,%0" : "=m" (q[d+8])); } - raid6_after_mmx(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_mmxx2 = { diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c index f7e7859..f0a1ba8 100644 --- a/drivers/md/raid6sse1.c +++ b/drivers/md/raid6sse1.c @@ -33,16 +33,10 @@ extern const struct raid6_mmx_constants { static int raid6_have_sse1_or_mmxext(void) { -#ifdef __KERNEL__ /* Not really boot_cpu but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX) && (boot_cpu_has(X86_FEATURE_XMM) || boot_cpu_has(X86_FEATURE_MMXEXT)); -#else - /* User space test code - this incorrectly breaks on some Athlons */ - u32 features = cpuid_features(); - return ( (features & (5<<23)) == (5<<23) ); -#endif } /* @@ -53,14 +47,12 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - /* This is really MMX code, not SSE */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -94,8 +86,8 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntq %%mm4,%0" : "=m" (q[d])); } - raid6_after_mmx(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse1x1 = { @@ -113,13 +105,12 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -157,8 +148,8 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntq %%mm6,%0" : "=m" (q[d+8])); } - raid6_after_mmx(&sa); asm volatile("sfence" : :: "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse1x2 = { diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c index b3aa7fe..0f01976 100644 --- a/drivers/md/raid6sse2.c +++ b/drivers/md/raid6sse2.c @@ -30,17 +30,11 @@ static const struct raid6_sse_constants { static int raid6_have_sse2(void) { -#ifdef __KERNEL__ /* Not really boot_cpu but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX) && boot_cpu_has(X86_FEATURE_FXSR) && boot_cpu_has(X86_FEATURE_XMM) && boot_cpu_has(X86_FEATURE_XMM2); -#else - /* User space test code */ - u32 features = cpuid_features(); - return ( (features & (15<<23)) == (15<<23) ); -#endif } /* @@ -51,13 +45,12 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse2(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */ @@ -93,8 +86,8 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("pxor %xmm4,%xmm4"); } - raid6_after_sse2(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x1 = { @@ -112,13 +105,12 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse2(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */ @@ -156,8 +148,8 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntdq %%xmm6,%0" : "=m" (q[d+16])); } - raid6_after_sse2(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x2 = { @@ -179,13 +171,12 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse16_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse16(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" :: "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm2,%xmm2"); /* P[0] */ @@ -256,8 +247,9 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntdq %%xmm14,%0" : "=m" (q[d+48])); asm volatile("pxor %xmm14,%xmm14"); } + asm volatile("sfence" : : : "memory"); - raid6_after_sse16(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x4 = { diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 4cf2053..9111950 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -21,224 +21,40 @@ #if defined(__i386__) || defined(__x86_64__) -#ifdef __x86_64__ - -typedef struct { - unsigned int fsave[27]; - unsigned long cr0; -} raid6_mmx_save_t __attribute__((aligned(16))); - -/* N.B.: For SSE we only save %xmm0-%xmm7 even for x86-64, since - the code doesn't know about the additional x86-64 registers */ -typedef struct { - unsigned int sarea[8*4+2]; - unsigned long cr0; -} raid6_sse_save_t __attribute__((aligned(16))); - -/* This is for x86-64-specific code which uses all 16 XMM registers */ -typedef struct { - unsigned int sarea[16*4+2]; - unsigned long cr0; -} raid6_sse16_save_t __attribute__((aligned(16))); - -/* On x86-64 the stack *SHOULD* be 16-byte aligned, but currently this - is buggy in the kernel and it's only 8-byte aligned in places, so - we need to do this anyway. Sigh. */ -#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) - -#else /* __i386__ */ - -typedef struct { - unsigned int fsave[27]; - unsigned long cr0; -} raid6_mmx_save_t; - -/* On i386, the stack is only 8-byte aligned, but SSE requires 16-byte - alignment. The +3 is so we have the slack space to manually align - a properly-sized area correctly. */ -typedef struct { - unsigned int sarea[8*4+3]; - unsigned long cr0; -} raid6_sse_save_t; - -/* Find the 16-byte aligned save area */ -#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) - -#endif - #ifdef __KERNEL__ /* Real code */ -/* Note: %cr0 is 32 bits on i386 and 64 bits on x86-64 */ - -static inline unsigned long raid6_get_fpu(void) -{ - unsigned long cr0; - - preempt_disable(); - asm volatile("mov %%cr0,%0 ; clts" : "=r" (cr0)); - return cr0; -} - -static inline void raid6_put_fpu(unsigned long cr0) -{ - asm volatile("mov %0,%%cr0" : : "r" (cr0)); - preempt_enable(); -} +#include #else /* Dummy code for user space testing */ -static inline unsigned long raid6_get_fpu(void) -{ - return 0xf00ba6; -} - -static inline void raid6_put_fpu(unsigned long cr0) -{ - (void)cr0; -} - -#endif - -static inline void raid6_before_mmx(raid6_mmx_save_t *s) -{ - s->cr0 = raid6_get_fpu(); - asm volatile("fsave %0 ; fwait" : "=m" (s->fsave[0])); -} - -static inline void raid6_after_mmx(raid6_mmx_save_t *s) -{ - asm volatile("frstor %0" : : "m" (s->fsave[0])); - raid6_put_fpu(s->cr0); -} - -static inline void raid6_before_sse(raid6_sse_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); - - asm volatile("movaps %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movaps %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movaps %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movaps %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movaps %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movaps %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movaps %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movaps %%xmm7,%0" : "=m" (rsa[28])); -} - -static inline void raid6_after_sse(raid6_sse_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - asm volatile("movaps %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movaps %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movaps %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movaps %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movaps %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movaps %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movaps %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movaps %0,%%xmm7" : : "m" (rsa[28])); - - raid6_put_fpu(s->cr0); -} - -static inline void raid6_before_sse2(raid6_sse_save_t *s) +static inline void kernel_fpu_begin(void) { - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); - - asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28])); } -static inline void raid6_after_sse2(raid6_sse_save_t *s) +static inline void kernel_fpu_end(void) { - unsigned int *rsa = SAREA(s); - - asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28])); - - raid6_put_fpu(s->cr0); } -#ifdef __x86_64__ - -static inline void raid6_before_sse16(raid6_sse16_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions + * (fast save and restore) */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ - asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28])); - asm volatile("movdqa %%xmm8,%0" : "=m" (rsa[32])); - asm volatile("movdqa %%xmm9,%0" : "=m" (rsa[36])); - asm volatile("movdqa %%xmm10,%0" : "=m" (rsa[40])); - asm volatile("movdqa %%xmm11,%0" : "=m" (rsa[44])); - asm volatile("movdqa %%xmm12,%0" : "=m" (rsa[48])); - asm volatile("movdqa %%xmm13,%0" : "=m" (rsa[52])); - asm volatile("movdqa %%xmm14,%0" : "=m" (rsa[56])); - asm volatile("movdqa %%xmm15,%0" : "=m" (rsa[60])); -} - -static inline void raid6_after_sse16(raid6_sse16_save_t *s) +/* Should work well enough on modern CPUs for testing */ +static inline int boot_cpu_has(int flag) { - unsigned int *rsa = SAREA(s); + u32 eax = (flag >> 5) ? 0x80000001 : 1; + u32 edx; - asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28])); - asm volatile("movdqa %0,%%xmm8" : : "m" (rsa[32])); - asm volatile("movdqa %0,%%xmm9" : : "m" (rsa[36])); - asm volatile("movdqa %0,%%xmm10" : : "m" (rsa[40])); - asm volatile("movdqa %0,%%xmm11" : : "m" (rsa[44])); - asm volatile("movdqa %0,%%xmm12" : : "m" (rsa[48])); - asm volatile("movdqa %0,%%xmm13" : : "m" (rsa[52])); - asm volatile("movdqa %0,%%xmm14" : : "m" (rsa[56])); - asm volatile("movdqa %0,%%xmm15" : : "m" (rsa[60])); + asm volatile("cpuid" + : "+a" (eax), "=d" (edx) + : : "ecx", "ebx"); - raid6_put_fpu(s->cr0); + return (edx >> (flag & 31)) & 1; } -#endif /* __x86_64__ */ - -/* User space test hack */ -#ifndef __KERNEL__ -static inline int cpuid_features(void) -{ - u32 eax = 1; - u32 ebx, ecx, edx; - - asm volatile("cpuid" : - "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)); - - return edx; -} #endif /* ndef __KERNEL__ */ #endif diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 15d12fc..127a94b 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -469,9 +469,9 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { fw->data[BLUEBIRD_01_ID_OFFSET + 2] = - udev->descriptor.idProduct + 1; + le16_to_cpu(udev->descriptor.idProduct) + 1; fw->data[BLUEBIRD_01_ID_OFFSET + 3] = - udev->descriptor.idProduct >> 8; + le16_to_cpu(udev->descriptor.idProduct) >> 8; return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); } diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 4a198d4..b5acb11 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -119,6 +119,8 @@ static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_f struct dvb_usb_adapter *adap = fe->dvb->priv; u8 b[5]; dvb_usb_tuner_calc_regs(fe,fep,b, 5); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0); } diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 682dc7c..710c11a 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1022,7 +1022,7 @@ static ssize_t cafe_v4l_read(struct file *filp, char __user *buffer, size_t len, loff_t *pos) { struct cafe_camera *cam = filp->private_data; - int ret; + int ret = 0; /* * Perhaps we're in speculative read mode and already @@ -1251,8 +1251,6 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv, if (cam->n_sbufs == 0) /* no luck at all - ret already set */ kfree(cam->sb_bufs); - else - ret = 0; req->count = cam->n_sbufs; /* In case of partial success */ out: diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index cc535ca..774d253 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -633,7 +633,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_CX25840) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -903,13 +903,13 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, state->vbi_line_offset = 8; state->id = id; + i2c_attach_client(client); + if (state->is_cx25836) cx25836_initialize(client); else cx25840_initialize(client, 1); - i2c_attach_client(client); - return 0; } diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1958d40..0e86b9d 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -37,7 +37,7 @@ */ #define FWSEND 48 -#define FWDEV(x) &((x)->adapter->dev) +#define FWDEV(x) &((x)->dev) static char *firmware = FWFILE; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index a97be1b..bdfe2af 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1389,7 +1389,7 @@ static int vidioc_g_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* cx2388x has a 24-bit register space */ reg->val = cx_read(reg->reg&0xffffff); @@ -1401,7 +1401,7 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; cx_write(reg->reg&0xffffff, reg->val); return 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a1ca0f5..1cd4bb3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3256,8 +3256,8 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - u32 chip_id, u64 reg_id, - int setFl,u32 *val_ptr) + u32 match_type, u32 match_chip, u64 reg_id, + int setFl,u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct list_head *item; @@ -3268,13 +3268,16 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - req.i2c_id = chip_id; + req.match_type = match_type; + req.match_chip = match_chip; req.reg = reg_id; if (setFl) req.val = *val_ptr; mutex_lock(&hdw->i2c_list_lock); do { list_for_each(item,&hdw->i2c_clients) { cp = list_entry(item,struct pvr2_i2c_client,list); - if (cp->client->driver->id != chip_id) continue; + if (!v4l2_chip_match_i2c_client(cp->client, req.match_type, req.match_chip)) { + continue; + } stat = pvr2_i2c_client_cmd( cp,(setFl ? VIDIOC_DBG_S_REGISTER : VIDIOC_DBG_G_REGISTER),&req); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 566a8ef..0c9cca4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -217,13 +217,14 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); /* Direct read/write access to chip's registers: - chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) + match_type - how to interpret match_chip (e.g. driver ID, i2c address) + match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) reg_id - register number to access setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ int pvr2_hdw_register_access(struct pvr2_hdw *, - u32 chip_id,u64 reg_id, - int setFl,u32 *val_ptr); + u32 match_type, u32 match_chip,u64 reg_id, + int setFl,u64 *val_ptr); /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 4fe4136..5313d34 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -740,11 +740,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: { - u32 val; + u64 val; struct v4l2_register *req = (struct v4l2_register *)arg; if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( - hdw,req->i2c_id,req->reg, + hdw,req->match_type,req->match_chip,req->reg, cmd == VIDIOC_DBG_S_REGISTER,&val); if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c4f066d..7735b67 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1425,7 +1425,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA711X) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index bd9c4f3..654863d 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -619,7 +619,7 @@ static int saa7127_command(struct i2c_client *client, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA7127) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 886b5df..d5ec05f 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -955,7 +955,7 @@ static int tvp5150_command(struct i2c_client *c, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_TVP5150) + if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index b3b5fd5..28d1133 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -167,7 +167,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64031A) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 8852903..fe38224 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -144,7 +144,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64083) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index ae5f425..6fc1455 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -521,7 +521,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, struct v4l2_register *reg = arg; int errCode; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -540,7 +540,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', - (unsigned int)reg->reg, reg->val); + (unsigned int)reg->reg, (unsigned int)reg->val); return 0; } #endif diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index ddfd80c..5474760 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -365,13 +366,21 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", -#if 1 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", -#endif [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", - [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS" + [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", +#if 1 + [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES", + [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS", + [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX", + [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", +#endif }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -395,9 +404,6 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", - [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", - [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", - [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", @@ -947,6 +953,28 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) return **ctrl_classes; } +int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + return (c != NULL && c->driver != NULL && c->driver->id == match_chip); + case V4L2_CHIP_MATCH_I2C_ADDR: + return (c != NULL && c->addr == match_chip); + default: + return 0; + } +} + +int v4l2_chip_match_host(u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_HOST: + return match_chip == 0; + default: + return 0; + } +} + /* ----------------------------------------------------------------- */ EXPORT_SYMBOL(v4l2_norm_to_name); @@ -970,6 +998,9 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); EXPORT_SYMBOL(v4l2_ctrl_query_fill); EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); +EXPORT_SYMBOL(v4l2_chip_match_i2c_client); +EXPORT_SYMBOL(v4l2_chip_match_host); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index dc9b1ef..011938f 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1342,6 +1342,42 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_s_jpegcomp(file, fh, p); break; } + case VIDIOC_G_ENC_INDEX: + { + struct v4l2_enc_idx *p=arg; + + if (!vfd->vidioc_g_enc_index) + break; + ret=vfd->vidioc_g_enc_index(file, fh, p); + if (!ret) + dbgarg (cmd, "entries=%d, entries_cap=%d\n", + p->entries,p->entries_cap); + break; + } + case VIDIOC_ENCODER_CMD: + { + struct v4l2_encoder_cmd *p=arg; + + if (!vfd->vidioc_encoder_cmd) + break; + ret=vfd->vidioc_encoder_cmd(file, fh, p); + if (!ret) + dbgarg (cmd, "cmd=%d, flags=%d\n", + p->cmd,p->flags); + break; + } + case VIDIOC_TRY_ENCODER_CMD: + { + struct v4l2_encoder_cmd *p=arg; + + if (!vfd->vidioc_try_encoder_cmd) + break; + ret=vfd->vidioc_try_encoder_cmd(file, fh, p); + if (!ret) + dbgarg (cmd, "cmd=%d, flags=%d\n", + p->cmd,p->flags); + break; + } case VIDIOC_G_PARM: { struct v4l2_streamparm *p=arg; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1e6eda2..1bf5482 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1218,45 +1218,68 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_a * do this early on to make the additional device appear during * the PCI scanning. */ - -static void quirk_jmicron_dualfn(struct pci_dev *pdev) +static void quirk_jmicron_ata(struct pci_dev *pdev) { - u32 conf; + u32 conf1, conf5, class; u8 hdr; /* Only poke fn 0 */ if (PCI_FUNC(pdev->devfn)) return; - switch(pdev->device) { - case PCI_DEVICE_ID_JMICRON_JMB365: - case PCI_DEVICE_ID_JMICRON_JMB366: - /* Redirect IDE second PATA port to the right spot */ - pci_read_config_dword(pdev, 0x80, &conf); - conf |= (1 << 24); - /* Fall through */ - pci_write_config_dword(pdev, 0x80, conf); - case PCI_DEVICE_ID_JMICRON_JMB361: - case PCI_DEVICE_ID_JMICRON_JMB363: - pci_read_config_dword(pdev, 0x40, &conf); - /* Enable dual function mode, AHCI on fn 0, IDE fn1 */ - /* Set the class codes correctly and then direct IDE 0 */ - conf &= ~0x000FF200; /* Clear bit 9 and 12-19 */ - conf |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */ - pci_write_config_dword(pdev, 0x40, conf); - - /* Reconfigure so that the PCI scanner discovers the - device is now multifunction */ - - pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr); - pdev->hdr_type = hdr & 0x7f; - pdev->multifunction = !!(hdr & 0x80); + pci_read_config_dword(pdev, 0x40, &conf1); + pci_read_config_dword(pdev, 0x80, &conf5); - break; + conf1 &= ~0x00CFF302; /* Clear bit 1, 8, 9, 12-19, 22, 23 */ + conf5 &= ~(1 << 24); /* Clear bit 24 */ + + switch (pdev->device) { + case PCI_DEVICE_ID_JMICRON_JMB360: + /* The controller should be in single function ahci mode */ + conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */ + break; + + case PCI_DEVICE_ID_JMICRON_JMB365: + case PCI_DEVICE_ID_JMICRON_JMB366: + /* Redirect IDE second PATA port to the right spot */ + conf5 |= (1 << 24); + /* Fall through */ + case PCI_DEVICE_ID_JMICRON_JMB361: + case PCI_DEVICE_ID_JMICRON_JMB363: + /* Enable dual function mode, AHCI on fn 0, IDE fn1 */ + /* Set the class codes correctly and then direct IDE 0 */ + conf1 |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */ + break; + + case PCI_DEVICE_ID_JMICRON_JMB368: + /* The controller should be in single function IDE mode */ + conf1 |= 0x00C00000; /* Set 22, 23 */ + break; } -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); + + pci_write_config_dword(pdev, 0x40, conf1); + pci_write_config_dword(pdev, 0x80, conf5); + + /* Update pdev accordingly */ + pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr); + pdev->hdr_type = hdr & 0x7f; + pdev->multifunction = !!(hdr & 0x80); + + pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class); + pdev->class = class >> 8; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); #endif diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 7a0d8ee..04aaa63 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -113,10 +113,16 @@ EXPORT_SYMBOL_GPL(rtc_device_register); */ void rtc_device_unregister(struct rtc_device *rtc) { - mutex_lock(&rtc->ops_lock); - rtc->ops = NULL; - mutex_unlock(&rtc->ops_lock); - class_device_unregister(&rtc->class_dev); + if (class_device_get(&rtc->class_dev) != NULL) { + mutex_lock(&rtc->ops_lock); + /* remove innards of this RTC, then disable it, before + * letting any rtc_class_open() users access it again + */ + class_device_unregister(&rtc->class_dev); + rtc->ops = NULL; + mutex_unlock(&rtc->ops_lock); + class_device_put(&rtc->class_dev); + } } EXPORT_SYMBOL_GPL(rtc_device_unregister); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 6f11f6d..ef40df0 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -179,7 +179,7 @@ struct class_device *rtc_class_open(char *name) down(&rtc_class->sem); list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { - class_dev = class_dev_tmp; + class_dev = class_device_get(class_dev_tmp); break; } } @@ -197,6 +197,7 @@ EXPORT_SYMBOL_GPL(rtc_class_open); void rtc_class_close(struct class_device *class_dev) { module_put(to_rtc_device(class_dev)->owner); + class_device_put(class_dev); } EXPORT_SYMBOL_GPL(rtc_class_close); diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index ef09952..12ec8b4 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -4,7 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina */ /* @@ -27,9 +27,6 @@ #include #include -#undef DEBUG -#undef DEBUG_DATA - #include #include @@ -758,6 +755,8 @@ void usbhid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 +#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 +#define USB_DEVICE_ID_DINOVO_EDGE 0xc714 #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 @@ -778,6 +777,8 @@ static const struct hid_blacklist { unsigned quirks; } hid_blacklist[] = { + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, @@ -944,6 +945,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR }, { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, @@ -1041,6 +1043,22 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) kfree(buf); } +/* + * Logitech S510 keyboard sends in report #3 keys which are far + * above the logical maximum described in descriptor. This extends + * the original value of 0x28c of logical maximum to 0x104d + */ +static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize) +{ + if (rsize >= 90 && rdesc[83] == 0x26 + && rdesc[84] == 0x8c + && rdesc[85] == 0x02) { + info("Fixing up Logitech S510 report descriptor"); + rdesc[84] = rdesc[89] = 0x4d; + rdesc[85] = rdesc[90] = 0x10; + } +} + static struct hid_device *usb_hid_configure(struct usb_interface *intf) { struct usb_host_interface *interface = intf->cur_altsetting; @@ -1109,7 +1127,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if ((quirks & HID_QUIRK_CYMOTION)) hid_fixup_cymotion_descriptor(rdesc, rsize); -#ifdef DEBUG_DATA + if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR) + hid_fixup_s510_descriptor(rdesc, rsize); + +#ifdef CONFIG_HID_DEBUG printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); for (n = 0; n < rsize; n++) printk(" %02x", (unsigned char) rdesc[n]); @@ -1225,8 +1246,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) le16_to_cpu(dev->descriptor.idProduct)); hid->bus = BUS_USB; - hid->vendor = dev->descriptor.idVendor; - hid->product = dev->descriptor.idProduct; + hid->vendor = le16_to_cpu(dev->descriptor.idVendor); + hid->product = le16_to_cpu(dev->descriptor.idProduct); usb_make_path(dev, hid->phys, sizeof(hid->phys)); strlcat(hid->phys, "/input", sizeof(hid->phys)); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index c1536d7..b8f0a11 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1618,8 +1618,7 @@ config FB_IBM_GXT4500 config FB_PS3 bool "PS3 GPU framebuffer driver" - depends on FB && PPC_PS3 - select PS3_PS3AV + depends on FB && PS3_PS3AV select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 02b290c..58c0ac7 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -136,8 +136,8 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) #define SM501_MEMF_CRT (4) #define SM501_MEMF_ACCEL (8) -int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, - unsigned int why, size_t size) +static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, + unsigned int why, size_t size) { unsigned int ptr = 0; @@ -926,7 +926,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) * set or change the hardware cursor parameters */ -int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) +static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; @@ -1225,7 +1225,7 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt, * initialise hw cursor parameters */ -int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) +static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) { struct sm501fb_par *par = fbi->par; struct sm501fb_info *info = par->info; @@ -1768,7 +1768,7 @@ static struct platform_driver sm501fb_driver = { }, }; -int __devinit sm501fb_init(void) +static int __devinit sm501fb_init(void) { return platform_driver_register(&sm501fb_driver); } diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index bd969ad..7a7d25d 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -205,6 +205,7 @@ int ecryptfs_open_lower_file(struct file **lower_file, { int rc = 0; + flags |= O_LARGEFILE; dget(lower_dentry); mntget(lower_mnt); *lower_file = dentry_open(lower_dentry, lower_mnt, flags); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 9fa7e0b..0cfff4f 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -200,9 +200,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) inode = ecryptfs_dentry->d_inode; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR; -#if BITS_PER_LONG != 32 - lower_flags |= O_LARGEFILE; -#endif lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); /* Corresponding fput() at end of this function */ if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 80044d1..812427e 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -487,7 +487,7 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) rc = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); if (rc) { ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n"); - goto out_free; + goto out; } lower_root = nd.dentry; if (!lower_root->d_inode) { diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 3a6f65c..7be8e91 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -238,7 +238,6 @@ int ecryptfs_do_readpage(struct file *file, struct page *page, lower_page_data = kmap_atomic(lower_page, KM_USER1); memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); kunmap_atomic(lower_page_data, KM_USER1); - flush_dcache_page(lower_page); kunmap_atomic(page_data, KM_USER0); flush_dcache_page(page); rc = 0; @@ -422,9 +421,11 @@ out: return rc; } -static void ecryptfs_release_lower_page(struct page *lower_page) +static +void ecryptfs_release_lower_page(struct page *lower_page, int page_locked) { - unlock_page(lower_page); + if (page_locked) + unlock_page(lower_page); page_cache_release(lower_page); } @@ -454,6 +455,13 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, } lower_a_ops = lower_inode->i_mapping->a_ops; rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8); + if (rc) { + if (rc == AOP_TRUNCATED_PAGE) + ecryptfs_release_lower_page(header_page, 0); + else + ecryptfs_release_lower_page(header_page, 1); + goto out; + } file_size = (u64)i_size_read(inode); ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); file_size = cpu_to_be64(file_size); @@ -465,7 +473,10 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, if (rc < 0) ecryptfs_printk(KERN_ERR, "Error commiting header page " "write\n"); - ecryptfs_release_lower_page(header_page); + if (rc == AOP_TRUNCATED_PAGE) + ecryptfs_release_lower_page(header_page, 0); + else + ecryptfs_release_lower_page(header_page, 1); lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; mark_inode_dirty_sync(inode); out: @@ -572,7 +583,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, } out: if (rc && (*lower_page)) { - ecryptfs_release_lower_page(*lower_page); + if (rc == AOP_TRUNCATED_PAGE) + ecryptfs_release_lower_page(*lower_page, 0); + else + ecryptfs_release_lower_page(*lower_page, 1); (*lower_page) = NULL; } return rc; @@ -588,16 +602,19 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, struct file *lower_file, int byte_offset, int region_size) { + int page_locked = 1; int rc = 0; rc = lower_inode->i_mapping->a_ops->commit_write( lower_file, lower_page, byte_offset, region_size); + if (rc == AOP_TRUNCATED_PAGE) + page_locked = 0; if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error committing write; rc = [%d]\n", rc); } else rc = 0; - ecryptfs_release_lower_page(lower_page); + ecryptfs_release_lower_page(lower_page, page_locked); return rc; } diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 99857a4..12f7dda 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -475,8 +475,15 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode, struct buffer_head *bh) { struct mb_cache_entry *ce = NULL; + int error = 0; ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_bdev, bh->b_blocknr); + error = ext3_journal_get_write_access(handle, bh); + if (error) + goto out; + + lock_buffer(bh); + if (BHDR(bh)->h_refcount == cpu_to_le32(1)) { ea_bdebug(bh, "refcount now=0; freeing"); if (ce) @@ -485,21 +492,20 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode, get_bh(bh); ext3_forget(handle, 1, inode, bh, bh->b_blocknr); } else { - if (ext3_journal_get_write_access(handle, bh) == 0) { - lock_buffer(bh); - BHDR(bh)->h_refcount = cpu_to_le32( + BHDR(bh)->h_refcount = cpu_to_le32( le32_to_cpu(BHDR(bh)->h_refcount) - 1); - ext3_journal_dirty_metadata(handle, bh); - if (IS_SYNC(inode)) - handle->h_sync = 1; - DQUOT_FREE_BLOCK(inode, 1); - unlock_buffer(bh); - ea_bdebug(bh, "refcount now=%d; releasing", - le32_to_cpu(BHDR(bh)->h_refcount)); - } + error = ext3_journal_dirty_metadata(handle, bh); + handle->h_sync = 1; + DQUOT_FREE_BLOCK(inode, 1); + ea_bdebug(bh, "refcount now=%d; releasing", + le32_to_cpu(BHDR(bh)->h_refcount)); if (ce) mb_cache_entry_release(ce); } + unlock_buffer(bh); +out: + ext3_std_error(inode->i_sb, error); + return; } struct ext3_xattr_info { @@ -675,7 +681,7 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, struct buffer_head *new_bh = NULL; struct ext3_xattr_search *s = &bs->s; struct mb_cache_entry *ce = NULL; - int error; + int error = 0; #define header(x) ((struct ext3_xattr_header *)(x)) @@ -684,16 +690,17 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, if (s->base) { ce = mb_cache_entry_get(ext3_xattr_cache, bs->bh->b_bdev, bs->bh->b_blocknr); + error = ext3_journal_get_write_access(handle, bs->bh); + if (error) + goto cleanup; + lock_buffer(bs->bh); + if (header(s->base)->h_refcount == cpu_to_le32(1)) { if (ce) { mb_cache_entry_free(ce); ce = NULL; } ea_bdebug(bs->bh, "modifying in-place"); - error = ext3_journal_get_write_access(handle, bs->bh); - if (error) - goto cleanup; - lock_buffer(bs->bh); error = ext3_xattr_set_entry(i, s); if (!error) { if (!IS_LAST_ENTRY(s->first)) @@ -713,6 +720,9 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, } else { int offset = (char *)s->here - bs->bh->b_data; + unlock_buffer(bs->bh); + journal_release_buffer(handle, bs->bh); + if (ce) { mb_cache_entry_release(ce); ce = NULL; diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index dc969c3..e832e96 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -475,8 +475,14 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, struct buffer_head *bh) { struct mb_cache_entry *ce = NULL; + int error = 0; ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr); + error = ext4_journal_get_write_access(handle, bh); + if (error) + goto out; + + lock_buffer(bh); if (BHDR(bh)->h_refcount == cpu_to_le32(1)) { ea_bdebug(bh, "refcount now=0; freeing"); if (ce) @@ -485,21 +491,21 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, get_bh(bh); ext4_forget(handle, 1, inode, bh, bh->b_blocknr); } else { - if (ext4_journal_get_write_access(handle, bh) == 0) { - lock_buffer(bh); - BHDR(bh)->h_refcount = cpu_to_le32( + BHDR(bh)->h_refcount = cpu_to_le32( le32_to_cpu(BHDR(bh)->h_refcount) - 1); - ext4_journal_dirty_metadata(handle, bh); - if (IS_SYNC(inode)) - handle->h_sync = 1; - DQUOT_FREE_BLOCK(inode, 1); - unlock_buffer(bh); - ea_bdebug(bh, "refcount now=%d; releasing", - le32_to_cpu(BHDR(bh)->h_refcount)); - } + error = ext4_journal_dirty_metadata(handle, bh); + if (IS_SYNC(inode)) + handle->h_sync = 1; + DQUOT_FREE_BLOCK(inode, 1); + ea_bdebug(bh, "refcount now=%d; releasing", + le32_to_cpu(BHDR(bh)->h_refcount)); if (ce) mb_cache_entry_release(ce); } + unlock_buffer(bh); +out: + ext4_std_error(inode->i_sb, error); + return; } struct ext4_xattr_info { @@ -675,7 +681,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, struct buffer_head *new_bh = NULL; struct ext4_xattr_search *s = &bs->s; struct mb_cache_entry *ce = NULL; - int error; + int error = 0; #define header(x) ((struct ext4_xattr_header *)(x)) @@ -684,16 +690,17 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, if (s->base) { ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, bs->bh->b_blocknr); + error = ext4_journal_get_write_access(handle, bs->bh); + if (error) + goto cleanup; + lock_buffer(bs->bh); + if (header(s->base)->h_refcount == cpu_to_le32(1)) { if (ce) { mb_cache_entry_free(ce); ce = NULL; } ea_bdebug(bs->bh, "modifying in-place"); - error = ext4_journal_get_write_access(handle, bs->bh); - if (error) - goto cleanup; - lock_buffer(bs->bh); error = ext4_xattr_set_entry(i, s); if (!error) { if (!IS_LAST_ENTRY(s->first)) @@ -713,6 +720,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, } else { int offset = (char *)s->here - bs->bh->b_data; + unlock_buffer(bs->bh); + jbd2_journal_release_buffer(handle, bs->bh); if (ce) { mb_cache_entry_release(ce); ce = NULL; diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h index ba1b37d..8a05aa1 100644 --- a/include/asm-frv/pgtable.h +++ b/include/asm-frv/pgtable.h @@ -70,7 +70,11 @@ static inline int pte_file(pte_t pte) { return 0; } #define swapper_pg_dir ((pgd_t *) NULL) -#define pgtable_cache_init() do {} while(0) +#define pgtable_cache_init() do {} while (0) +#define arch_enter_lazy_mmu_mode() do {} while (0) +#define arch_leave_lazy_mmu_mode() do {} while (0) +#define arch_enter_lazy_cpu_mode() do {} while (0) +#define arch_leave_lazy_cpu_mode() do {} while (0) #else /* !CONFIG_MMU */ /*****************************************************************************/ diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h index 93e5a06..1bf4f7a 100644 --- a/include/asm-sparc64/dma.h +++ b/include/asm-sparc64/dma.h @@ -205,10 +205,6 @@ do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ #define for_each_dvma(dma) \ for((dma) = dma_chain; (dma); (dma) = (dma)->next) -extern int get_dma_list(char *); -extern int request_dma(unsigned int, __const__ char *); -extern void free_dma(unsigned int); - /* From PCI */ #ifdef CONFIG_PCI diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index d389587..be9509c 100644 --- a/include/asm-sparc64/parport.h +++ b/include/asm-sparc64/parport.h @@ -23,8 +23,30 @@ static struct sparc_ebus_info { struct ebus_dma_info info; unsigned int addr; unsigned int count; + int lock; } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS]; +static __inline__ int request_dma(unsigned int dmanr, const char *device_id) +{ + if (dmanr >= PARPORT_PC_MAX_PORTS) + return -EINVAL; + if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0) + return -EBUSY; + return 0; +} + +static __inline__ void free_dma(unsigned int dmanr) +{ + if (dmanr >= PARPORT_PC_MAX_PORTS) { + printk(KERN_WARNING "Trying to free DMA%d\n", dmanr); + return; + } + if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) { + printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr); + return; + } +} + static __inline__ void enable_dma(unsigned int dmanr) { ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1); diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h index e57ff13..1b1090a 100644 --- a/include/asm-um/pgtable.h +++ b/include/asm-um/pgtable.h @@ -270,7 +270,7 @@ static inline pte_t pte_wrprotect(pte_t pte) static inline pte_t pte_mkread(pte_t pte) { - pte_set_bits(pte, _PAGE_RW); + pte_set_bits(pte, _PAGE_USER); return(pte_mknewprot(pte)); } diff --git a/include/linux/hid.h b/include/linux/hid.h index d26b08f..8c97d4d 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -6,7 +6,7 @@ * * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2001 Vojtech Pavlik - * Copyright (c) 2006 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina */ /* @@ -267,6 +267,8 @@ struct hid_item { #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 #define HID_QUIRK_IGNORE_MOUSE 0x00040000 #define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 +#define HID_QUIRK_LOGITECH_S510_DESCRIPTOR 0x00100000 +#define HID_QUIRK_DUPLICATE_USAGES 0x00200000 /* * This is the global environment of the parser. This information is @@ -292,7 +294,7 @@ struct hid_global { */ #define HID_MAX_DESCRIPTOR_SIZE 4096 -#define HID_MAX_USAGES 1024 +#define HID_MAX_USAGES 8192 #define HID_DEFAULT_NUM_COLLECTIONS 16 struct hid_local { diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 37f9279..3bef961 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -140,6 +140,7 @@ struct hrtimer_sleeper { /** * struct hrtimer_base - the timer base for a specific clock + * @cpu_base: per cpu clock base * @index: clock type index for per_cpu support when moving a * timer to a base on another cpu. * @active: red black tree root node for the active timers diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index a60995a..3f3e7a6 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -4,6 +4,7 @@ #ifdef CONFIG_HUGETLB_PAGE #include +#include #include struct ctl_table; @@ -168,7 +169,12 @@ void hugetlb_put_quota(struct address_space *mapping); static inline int is_file_hugepages(struct file *file) { - return file->f_op == &hugetlbfs_file_operations; + if (file->f_op == &hugetlbfs_file_operations) + return 1; + if (is_file_shm_hugepages(file)) + return 1; + + return 0; } static inline void set_file_hugepages(struct file *file) diff --git a/include/linux/irq.h b/include/linux/irq.h index b0a44b8..a689940 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/include/linux/isdn/capiutil.h b/include/linux/isdn/capiutil.h index 2e79f81..63bd9cf 100644 --- a/include/linux/isdn/capiutil.h +++ b/include/linux/isdn/capiutil.h @@ -174,9 +174,26 @@ char *capi_info2str(__u16 reason); /* * Debugging / Tracing functions */ + char *capi_cmd2str(__u8 cmd, __u8 subcmd); -char *capi_cmsg2str(_cmsg * cmsg); -char *capi_message2str(__u8 * msg); + +typedef struct { + u_char *buf; + u_char *p; + size_t size; + size_t pos; +} _cdebbuf; + +#define CDEBUG_SIZE 1024 +#define CDEBUG_GSIZE 4096 + +_cdebbuf *cdebbuf_alloc(void); +void cdebbuf_free(_cdebbuf *cdb); +int cdebug_init(void); +void cdebug_exit(void); + +_cdebbuf *capi_cmsg2str(_cmsg *cmsg); +_cdebbuf *capi_message2str(__u8 *msg); /*-----------------------------------------------------------------------*/ diff --git a/include/linux/mm.h b/include/linux/mm.h index a0eec16..60e0e4a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -660,15 +660,11 @@ static inline int page_mapped(struct page *page) extern void show_free_areas(void); #ifdef CONFIG_SHMEM -struct page *shmem_nopage(struct vm_area_struct *vma, - unsigned long address, int *type); int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new); struct mempolicy *shmem_get_policy(struct vm_area_struct *vma, unsigned long addr); int shmem_lock(struct file *file, int lock, struct user_struct *user); #else -#define shmem_nopage filemap_nopage - static inline int shmem_lock(struct file *file, int lock, struct user_struct *user) { @@ -688,7 +684,6 @@ static inline struct mempolicy *shmem_get_policy(struct vm_area_struct *vma, } #endif struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags); -extern int shmem_mmap(struct file *file, struct vm_area_struct *vma); int shmem_zero_setup(struct vm_area_struct *); diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 350878a..9cd0d0e 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -76,7 +76,7 @@ #define PG_active 6 #define PG_slab 7 /* slab debug (Suparna wants this) */ -#define PG_checked 8 /* kill me in 2.5.. */ +#define PG_owner_priv_1 8 /* Owner use. If pagecache, fs may use*/ #define PG_arch_1 9 #define PG_reserved 10 #define PG_private 11 /* If pagecache, has fs-private data */ @@ -91,6 +91,8 @@ #define PG_nosave_free 18 /* Used for system suspend/resume */ #define PG_buddy 19 /* Page is free, on buddy lists */ +/* PG_owner_priv_1 users should have descriptive aliases */ +#define PG_checked PG_owner_priv_1 /* Used by some filesystems */ #if (BITS_PER_LONG > 32) /* diff --git a/include/linux/shm.h b/include/linux/shm.h index a2c896a..ad2e3af 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -96,12 +96,17 @@ struct shmid_kernel /* private to the kernel */ #ifdef CONFIG_SYSVIPC long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr); +extern int is_file_shm_hugepages(struct file *file); #else static inline long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr) { return -ENOSYS; } +static inline int is_file_shm_hugepages(struct file *file) +{ + return 0; +} #endif #endif /* __KERNEL__ */ diff --git a/include/linux/socket.h b/include/linux/socket.h index 28157a3..fcd35a2 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -16,7 +16,7 @@ struct __kernel_sockaddr_storage { /* _SS_MAXSIZE value minus size of ss_family */ } __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */ -#ifdef __KERNEL__ +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) #include /* arch-dependent defines */ #include /* the SIOCxxx I/O controls */ diff --git a/include/linux/stat.h b/include/linux/stat.h index 4f8539c..679ef0d 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -7,7 +7,7 @@ #endif -#ifdef __KERNEL__ +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) #define S_IFMT 00170000 #define S_IFSOCK 0140000 diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 21805b5..523405e 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -211,9 +211,8 @@ static inline int sysfs_add_file_to_group(struct kobject *kobj, } static inline void sysfs_remove_file_from_group(struct kobject *kobj, - const struct attribute *attr, const char *group); + const struct attribute *attr, const char *group) { - ; } static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65a165f..441b877 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1193,6 +1193,55 @@ struct v4l2_audioout }; /* + * M P E G S E R V I C E S + * + * NOTE: EXPERIMENTAL API + */ +#if 1 +#define V4L2_ENC_IDX_FRAME_I (0) +#define V4L2_ENC_IDX_FRAME_P (1) +#define V4L2_ENC_IDX_FRAME_B (2) +#define V4L2_ENC_IDX_FRAME_MASK (0xf) + +struct v4l2_enc_idx_entry { + __u64 offset; + __u64 pts; + __u32 length; + __u32 flags; + __u32 reserved[2]; +}; + +#define V4L2_ENC_IDX_ENTRIES (64) +struct v4l2_enc_idx { + __u32 entries; + __u32 entries_cap; + __u32 reserved[4]; + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; +}; + + +#define V4L2_ENC_CMD_START (0) +#define V4L2_ENC_CMD_STOP (1) +#define V4L2_ENC_CMD_PAUSE (2) +#define V4L2_ENC_CMD_RESUME (3) + +/* Flags for V4L2_ENC_CMD_STOP */ +#define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) + +struct v4l2_encoder_cmd { + __u32 cmd; + __u32 flags; + union { + struct { + __u32 data[8]; + } raw; + }; +}; + +#endif + + +/* * D A T A S E R V I C E S ( V B I ) * * Data services API by Michael Schimek @@ -1303,13 +1352,21 @@ struct v4l2_streamparm /* * A D V A N C E D D E B U G G I N G + * + * NOTE: EXPERIMENTAL API */ /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ + +#define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 for the host) */ +#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver ID */ +#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ + struct v4l2_register { + __u32 match_type; /* Match type */ + __u32 match_chip; /* Match this chip, meaning determined by match_type */ __u64 reg; - __u32 i2c_id; /* I2C driver ID of the I2C chip, or 0 for the host */ - __u32 val; + __u64 val; }; /* @@ -1378,10 +1435,14 @@ struct v4l2_register { #if 1 #define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum) #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR ('V', 75, struct v4l2_frmivalenum) +#define VIDIOC_G_ENC_INDEX _IOR ('V', 76, struct v4l2_enc_idx) +#define VIDIOC_ENCODER_CMD _IOWR ('V', 77, struct v4l2_encoder_cmd) +#define VIDIOC_TRY_ENCODER_CMD _IOWR ('V', 78, struct v4l2_encoder_cmd) + +/* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ +#define VIDIOC_DBG_S_REGISTER _IOW ('V', 79, struct v4l2_register) +#define VIDIOC_DBG_G_REGISTER _IOWR ('V', 80, struct v4l2_register) #endif -/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ -#define VIDIOC_DBG_S_REGISTER _IOW ('d', 100, struct v4l2_register) -#define VIDIOC_DBG_G_REGISTER _IOWR('d', 101, struct v4l2_register) #ifdef __OLD_VIDIOC_ /* for compatibility, will go away some day */ diff --git a/include/linux/writeback.h b/include/linux/writeback.h index fc35e6b..0c78f7f 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -84,7 +84,7 @@ static inline void wait_on_inode(struct inode *inode) int wakeup_pdflush(long nr_pages); void laptop_io_completion(void); void laptop_sync_completion(void); -void throttle_vm_writeout(void); +void throttle_vm_writeout(gfp_t gfp_mask); /* These are exported to sysctl. */ extern int dirty_background_ratio; diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 244e440..6eaeec9 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -94,6 +94,14 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ +/* Register/chip ident helper function */ + +struct i2c_client; /* forward reference */ +int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id); +int v4l2_chip_match_host(u32 id_type, u32 chip_id); + +/* ------------------------------------------------------------------------- */ + /* Internal ioctls */ /* VIDIOC_INT_DECODE_VBI_LINE */ diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index aeec569..1dd3d32 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -271,6 +271,12 @@ struct video_device struct v4l2_jpegcompression *a); int (*vidioc_s_jpegcomp) (struct file *file, void *fh, struct v4l2_jpegcompression *a); + int (*vidioc_g_enc_index) (struct file *file, void *fh, + struct v4l2_enc_idx *a); + int (*vidioc_encoder_cmd) (struct file *file, void *fh, + struct v4l2_encoder_cmd *a); + int (*vidioc_try_encoder_cmd) (struct file *file, void *fh, + struct v4l2_encoder_cmd *a); /* Stream type-dependent parameter ioctls */ int (*vidioc_g_parm) (struct file *file, void *fh, diff --git a/include/net/sock.h b/include/net/sock.h index 03684e7..2c7d60c 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1278,7 +1278,7 @@ static inline int sock_writeable(const struct sock *sk) static inline gfp_t gfp_any(void) { - return in_softirq() ? GFP_ATOMIC : GFP_KERNEL; + return in_atomic() ? GFP_ATOMIC : GFP_KERNEL; } static inline long sock_rcvtimeo(const struct sock *sk, int noblock) diff --git a/ipc/shm.c b/ipc/shm.c index eb57e22..4fefbad 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -226,8 +226,8 @@ static void shm_close(struct vm_area_struct *vma) mutex_unlock(&shm_ids(ns).mutex); } -struct page *shm_nopage(struct vm_area_struct *vma, unsigned long address, - int *type) +static struct page *shm_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) { struct file *file = vma->vm_file; struct shm_file_data *sfd = shm_file_data(file); @@ -285,21 +285,41 @@ static int shm_release(struct inode *ino, struct file *file) return 0; } -#ifndef CONFIG_MMU +static int shm_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + int (*fsync) (struct file *, struct dentry *, int datasync); + struct shm_file_data *sfd = shm_file_data(file); + int ret = -EINVAL; + + fsync = sfd->file->f_op->fsync; + if (fsync) + ret = fsync(sfd->file, sfd->file->f_path.dentry, datasync); + return ret; +} + static unsigned long shm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct shm_file_data *sfd = shm_file_data(file); - return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len, pgoff, - flags); + return get_unmapped_area(sfd->file, addr, len, pgoff, flags); +} + +int is_file_shm_hugepages(struct file *file) +{ + int ret = 0; + + if (file->f_op == &shm_file_operations) { + struct shm_file_data *sfd; + sfd = shm_file_data(file); + ret = is_file_hugepages(sfd->file); + } + return ret; } -#else -#define shm_get_unmapped_area NULL -#endif static const struct file_operations shm_file_operations = { .mmap = shm_mmap, + .fsync = shm_fsync, .release = shm_release, .get_unmapped_area = shm_get_unmapped_area, }; diff --git a/kernel/lockdep.c b/kernel/lockdep.c index a08a172..8dc24c9 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2602,7 +2602,7 @@ out_restore: raw_local_irq_restore(flags); } -void __init lockdep_init(void) +void lockdep_init(void) { int i; diff --git a/kernel/relay.c b/kernel/relay.c index ef8a935..577f251 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -474,13 +474,12 @@ static void setup_callbacks(struct rchan *chan, } /** - * * relay_hotcpu_callback - CPU hotplug callback * @nb: notifier block * @action: hotplug action to take * @hcpu: CPU number * - * Returns the success/failure of the operation. (NOTIFY_OK, NOTIFY_BAD) + * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) */ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb, unsigned long action, diff --git a/kernel/sched.c b/kernel/sched.c index 0dc7572..5f102e6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3547,7 +3547,7 @@ need_resched_nonpreemptible: } } next->sleep_type = SLEEP_NORMAL; - if (dependent_sleeper(cpu, rq, next)) + if (rq->nr_running == 1 && dependent_sleeper(cpu, rq, next)) next = rq->idle; switch_tasks: if (next == rq->idle) @@ -3566,7 +3566,7 @@ switch_tasks: sched_info_switch(prev, next); if (likely(prev != next)) { - next->timestamp = now; + next->timestamp = next->last_ran = now; rq->nr_switches++; rq->curr = next; ++*switch_count; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3ca1d5f..34b2301 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1359,8 +1359,7 @@ void unregister_sysctl_table(struct ctl_table_header * header) } #else /* !CONFIG_SYSCTL */ -struct ctl_table_header * register_sysctl_table(ctl_table * table, - int insert_at_head) +struct ctl_table_header *register_sysctl_table(ctl_table * table) { return NULL; } diff --git a/kernel/timer.c b/kernel/timer.c index cb1b86a..6663a87 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -711,6 +711,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now, /** * next_timer_interrupt - return the jiffy of the next pending timer + * @now: current time (in jiffies) */ unsigned long get_next_timer_interrupt(unsigned long now) { @@ -908,7 +909,7 @@ static inline void change_clocksource(void) { } #endif /** - * timeofday_is_continuous - check to see if timekeeping is free running + * timekeeping_is_continuous - check to see if timekeeping is free running */ int timekeeping_is_continuous(void) { diff --git a/lib/bitmap.c b/lib/bitmap.c index ee6e58f..26ebafa 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -97,10 +97,10 @@ EXPORT_SYMBOL(__bitmap_complement); /** * __bitmap_shift_right - logical right shift of the bits in a bitmap - * @dst - destination bitmap - * @src - source bitmap - * @nbits - shift by this many bits - * @bits - bitmap size, in bits + * @dst : destination bitmap + * @src : source bitmap + * @shift : shift by this many bits + * @bits : bitmap size, in bits * * Shifting right (dividing) means moving bits in the MS -> LS bit * direction. Zeros are fed into the vacated MS positions and the @@ -141,10 +141,10 @@ EXPORT_SYMBOL(__bitmap_shift_right); /** * __bitmap_shift_left - logical left shift of the bits in a bitmap - * @dst - destination bitmap - * @src - source bitmap - * @nbits - shift by this many bits - * @bits - bitmap size, in bits + * @dst : destination bitmap + * @src : source bitmap + * @shift : shift by this many bits + * @bits : bitmap size, in bits * * Shifting left (multiplying) means moving bits in the LS -> MS * direction. Zeros are fed into the vacated LS bit positions diff --git a/mm/mmap.c b/mm/mmap.c index eb509ae..84f997d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -299,6 +299,8 @@ static int browse_rb(struct rb_root *root) printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start); i++; pn = nd; + prev = vma->vm_start; + pend = vma->vm_end; } j = 0; for (nd = pn; nd; nd = rb_prev(nd)) { diff --git a/mm/page-writeback.c b/mm/page-writeback.c index f7e088f..f469e3c 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -296,11 +296,21 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, } EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr); -void throttle_vm_writeout(void) +void throttle_vm_writeout(gfp_t gfp_mask) { long background_thresh; long dirty_thresh; + if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO)) { + /* + * The caller might hold locks which can prevent IO completion + * or progress in the filesystem. So we cannot just sit here + * waiting for IO to complete. + */ + congestion_wait(WRITE, HZ/10); + return; + } + for ( ; ; ) { get_dirty_limits(&background_thresh, &dirty_thresh, NULL); @@ -317,7 +327,6 @@ void throttle_vm_writeout(void) } } - /* * writeback at least _min_pages, and keep writing until the amount of dirty * memory is less than the background threshold, or until we're all clean. diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4173739..353ce90 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -600,7 +600,7 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags) page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_referenced | 1 << PG_arch_1 | - 1 << PG_checked | 1 << PG_mappedtodisk); + 1 << PG_owner_priv_1 | 1 << PG_mappedtodisk); set_page_private(page, 0); set_page_refcounted(page); diff --git a/mm/rmap.c b/mm/rmap.c index 669acb2..22ed3f7 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -183,7 +183,7 @@ void __init anon_vma_init(void) */ static struct anon_vma *page_lock_anon_vma(struct page *page) { - struct anon_vma *anon_vma = NULL; + struct anon_vma *anon_vma; unsigned long anon_mapping; rcu_read_lock(); @@ -195,9 +195,16 @@ static struct anon_vma *page_lock_anon_vma(struct page *page) anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON); spin_lock(&anon_vma->lock); + return anon_vma; out: rcu_read_unlock(); - return anon_vma; + return NULL; +} + +static void page_unlock_anon_vma(struct anon_vma *anon_vma) +{ + spin_unlock(&anon_vma->lock); + rcu_read_unlock(); } /* @@ -333,7 +340,8 @@ static int page_referenced_anon(struct page *page) if (!mapcount) break; } - spin_unlock(&anon_vma->lock); + + page_unlock_anon_vma(anon_vma); return referenced; } @@ -802,7 +810,8 @@ static int try_to_unmap_anon(struct page *page, int migration) if (ret == SWAP_FAIL || !page_mapped(page)) break; } - spin_unlock(&anon_vma->lock); + + page_unlock_anon_vma(anon_vma); return ret; } diff --git a/mm/shmem.c b/mm/shmem.c index 8820530..fcb0788 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1228,7 +1228,8 @@ failed: return error; } -struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type) +static struct page *shmem_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) { struct inode *inode = vma->vm_file->f_path.dentry->d_inode; struct page *page = NULL; @@ -1335,7 +1336,7 @@ out_nomem: return retval; } -int shmem_mmap(struct file *file, struct vm_area_struct *vma) +static int shmem_mmap(struct file *file, struct vm_area_struct *vma) { file_accessed(file); vma->vm_ops = &shmem_vm_ops; diff --git a/mm/slab.c b/mm/slab.c index 8fdaffa..57f7aa4 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4026,7 +4026,7 @@ void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3, /** * cache_reap - Reclaim memory from caches. - * @unused: unused parameter + * @w: work descriptor * * Called from workqueue/eventd every few seconds. * Purpose: diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index c7f6e19..8803471 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -126,6 +126,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page) return 0; } +#if 0 int shmem_mmap(struct file *file, struct vm_area_struct *vma) { file_accessed(file); @@ -135,6 +136,7 @@ int shmem_mmap(struct file *file, struct vm_area_struct *vma) return 0; #endif } +#endif /* 0 */ #ifndef CONFIG_MMU unsigned long shmem_get_unmapped_area(struct file *file, diff --git a/mm/truncate.c b/mm/truncate.c index ebf3fcb..0f4b6d1 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -375,10 +375,10 @@ int invalidate_inode_pages2_range(struct address_space *mapping, pagevec_init(&pvec, 0); next = start; - while (next <= end && !ret && !wrapped && + while (next <= end && !wrapped && pagevec_lookup(&pvec, mapping, next, min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { - for (i = 0; !ret && i < pagevec_count(&pvec); i++) { + for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; pgoff_t page_index; diff --git a/mm/vmscan.c b/mm/vmscan.c index 0655d5f..db023e2 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -952,7 +952,7 @@ static unsigned long shrink_zone(int priority, struct zone *zone, } } - throttle_vm_writeout(); + throttle_vm_writeout(sc->gfp_mask); atomic_dec(&zone->reclaim_in_progress); return nr_reclaimed; diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 3ab153d..147015f 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -291,12 +291,11 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_bh(&br->lock); if ((p = br_get_port(br, args[1])) == NULL) ret = -EINVAL; else br_stp_set_path_cost(p, args[2]); - spin_unlock_bh(&br->lock); + return ret; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f89ff15..820761f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2037,7 +2037,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) err: while ((skb = segs)) { segs = skb->next; - kfree(skb); + kfree_skb(skb); } return ERR_PTR(err); } diff --git a/net/dccp/output.c b/net/dccp/output.c index f5c6aca..3282f2f 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -269,7 +269,7 @@ void dccp_write_xmit(struct sock *sk, int block) err); } else { dccp_pr_debug("packet discarded\n"); - kfree(skb); + kfree_skb(skb); } } } diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 30b1e52..6b5c64f 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -381,7 +381,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, if (newsk != NULL) { const struct inet_request_sock *ireq = inet_rsk(req); struct tcp_request_sock *treq = tcp_rsk(req); - struct inet_connection_sock *newicsk = inet_csk(sk); + struct inet_connection_sock *newicsk = inet_csk(newsk); struct tcp_sock *newtp; /* Now setup tcp_sock */ diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f6ac65d..e16f1bb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -400,6 +400,8 @@ static void dev_forward_change(struct inet6_dev *idev) ipv6_dev_mc_dec(dev, &addr); } for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { + if (ifa->flags&IFA_F_TENTATIVE) + continue; if (idev->cnf.forwarding) addrconf_join_anycast(ifa); else diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index e5ef597..09117d6 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -461,6 +461,7 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) break; } read_unlock_bh(&idev->lock); + in6_dev_put(idev); } return im; } diff --git a/net/ipx/ChangeLog b/net/ipx/ChangeLog deleted file mode 100644 index 3b29763..0000000 --- a/net/ipx/ChangeLog +++ /dev/null @@ -1,101 +0,0 @@ - Revision 0.21: Uses the new generic socket option code. - - Revision 0.22: Gcc clean ups and drop out device registration. Use the - new multi-protocol edition of hard_header - - Revision 0.23: IPX /proc by Mark Evans. Adding a route will - will overwrite any existing route to the same network. - - Revision 0.24: Supports new /proc with no 4K limit - - Revision 0.25: Add ephemeral sockets, passive local network - identification, support for local net 0 and - multiple datalinks - - Revision 0.26: Device drop kills IPX routes via it. (needed for module) - - Revision 0.27: Autobind - - Revision 0.28: Small fix for multiple local networks - - Revision 0.29: Assorted major errors removed - Small correction to promisc mode error fix - Asynchronous I/O support. Changed to use notifiers - and the newer packet_type stuff. Assorted major - fixes - - Revision 0.30: Moved to net/ipx/... - Don't set address length on recvfrom that errors. - Incorrect verify_area. - - Revision 0.31: New sk_buffs. This still needs a lot of - testing. - - Revision 0.32: Using sock_alloc_send_skb, firewall hooks. - Supports sendmsg/recvmsg - - Revision 0.33: Internal network support, routing changes, uses a - protocol private area for ipx data. - - Revision 0.34: Module support. - - Revision 0.35: Checksum support. , hooked in by - Handles WIN95 discovery packets - - Revision 0.36: Internal bump up for 2.1 - - Revision 0.37: Began adding POSIXisms. - - Revision 0.38: Asynchronous socket stuff made current. - - Revision 0.39: SPX interfaces - - Revision 0.40: Tiny SIOCGSTAMP fix (chris@cybernet.co.nz) - - Revision 0.41: 802.2TR removed (p.norton@computer.org) - Fixed connecting to primary net, - Automatic binding on send & receive, - Martijn van Oosterhout - - Revision 042: Multithreading - use spinlocks and refcounting to - protect some structures: ipx_interface sock list, list - of ipx interfaces, etc. - Bugfixes - do refcounting on net_devices, check function - results, etc. Thanks to davem and freitag for - suggestions and guidance. - Arnaldo Carvalho de Melo , - November, 2000 - - Revision 043: Shared SKBs, don't mangle packets, some cleanups - Arnaldo Carvalho de Melo , - December, 2000 - - Revision 044: Call ipxitf_hold on NETDEV_UP - acme - - Revision 045: fix PPROP routing bug - acme - - Revision 046: Further fixes to PPROP, ipxitf_create_internal was - doing an unneeded MOD_INC_USE_COUNT, implement - sysctl for ipx_pprop_broacasting, fix the ipx sysctl - handling, making it dynamic, some cleanups, thanks to - Petr Vandrovec for review and good suggestions. (acme) - - Revision 047: Cleanups, CodingStyle changes, move the ncp connection - hack out of line - acme - - Revision 048: Use sk->protinfo to store the pointer to IPX private - area, remove af_ipx from sk->protinfo and move ipx_opt - to include/net/ipx.h, use IPX_SK like DecNET, etc - acme - - Revision 049: SPX support dropped, see comment in ipx_create - acme - - Revision 050: Use seq_file for proc stuff, moving it to ipx_proc.c - acme - -Other fixes: - - Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT pair. Also, now - usage count is managed this way: - -Count one if the auto_interface mode is on - -Count one per configured interface - - Jacques Gelinas (jacques@solucorp.qc.ca) diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig index 980a826..e9ad006 100644 --- a/net/ipx/Kconfig +++ b/net/ipx/Kconfig @@ -16,8 +16,7 @@ config IPX support", below. IPX is similar in scope to IP, while SPX, which runs on top of IPX, - is similar to TCP. There is also experimental support for SPX in - Linux (see "SPX networking", below). + is similar to TCP. To turn your Linux box into a fully featured NetWare file server and IPX router, say Y here and fetch either lwared from @@ -26,9 +25,6 @@ config IPX information, read the IPX-HOWTO available from . - General information about how to connect Linux, Windows machines and - Macs is on the WWW at . - The IPX driver would enlarge your kernel by about 16 KB. To compile this driver as a module, choose M here: the module will be called ipx. Unless you want to integrate your Linux box with a local Novell diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 11d504d..bf23e48 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -197,13 +197,12 @@ EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) { - gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; int err = 0; NETLINK_CB(skb).dst_group = group; if (echo) atomic_inc(&skb->users); - netlink_broadcast(nfnl, skb, pid, group, allocation); + netlink_broadcast(nfnl, skb, pid, group, gfp_any()); if (echo) err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT); diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 5bc3718..b931ede 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -173,7 +173,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) return 0; list_failure: - kfree(ans_skb); + kfree_skb(ans_skb); return ret_val; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2567453..956cfe0 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1401,7 +1401,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family); if (x == NULL) { - kfree(r_skb); + kfree_skb(r_skb); return -ESRCH; } @@ -1557,14 +1557,13 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_usersa_info *p = &ue->state; x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family); - err = -ENOENT; + err = -ENOENT; if (x == NULL) return err; - err = -EINVAL; - spin_lock_bh(&x->lock); + err = -EINVAL; if (x->km.state != XFRM_STATE_VALID) goto out; km_state_expired(x, ue->hard, current->pid); @@ -1574,6 +1573,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, AUDIT_MAC_IPSEC_DELSA, 1, NULL, x); } + err = 0; out: spin_unlock_bh(&x->lock); xfrm_state_put(x); diff --git a/scripts/kernel-doc b/scripts/kernel-doc index fb43c64..8be269f 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1547,7 +1547,7 @@ sub dump_function($$) { $prototype =~ s/^noinline +//; $prototype =~ s/__devinit +//; $prototype =~ s/^#define\s+//; #ak added - $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//; + $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; # Yes, this truly is vile. We are looking for: # 1. Return type (may be nothing if we're looking at a macro)