diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-04-26 19:36:14 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-04-26 19:36:17 +0200 |
commit | 7bd5fafeb414cf00deee32c82834f8bf1426b9ac (patch) | |
tree | 1103053fa40576e9f9fc2818ea1910180e09b752 | |
parent | fa7b69475a6c192853949ba496dd9c37b497b548 (diff) | |
parent | ec75a71634dabe439db91c1ef51d5099f4493808 (diff) | |
download | kernel_samsung_tuna-7bd5fafeb414cf00deee32c82834f8bf1426b9ac.zip kernel_samsung_tuna-7bd5fafeb414cf00deee32c82834f8bf1426b9ac.tar.gz kernel_samsung_tuna-7bd5fafeb414cf00deee32c82834f8bf1426b9ac.tar.bz2 |
Merge branch 'perf/urgent' into perf/stat
Merge reason: We want to queue up dependent changes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
60 files changed, 598 insertions, 278 deletions
diff --git a/Documentation/sound/alsa/SB-Live-mixer.txt b/Documentation/sound/alsa/SB-Live-mixer.txt index f5639d4..f4b5988 100644 --- a/Documentation/sound/alsa/SB-Live-mixer.txt +++ b/Documentation/sound/alsa/SB-Live-mixer.txt @@ -87,14 +87,14 @@ accumulator. ALSA uses accumulators 0 and 1 for left and right PCM. The result is forwarded to the ADC capture FIFO (thus to the standard capture PCM device). -name='Music Playback Volume',index=0 +name='Synth Playback Volume',index=0 This control is used to attenuate samples for left and right MIDI FX-bus accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples. The result samples are forwarded to the front DAC PCM slots of the AC97 codec. -name='Music Capture Volume',index=0 -name='Music Capture Switch',index=0 +name='Synth Capture Volume',index=0 +name='Synth Capture Switch',index=0 These controls are used to attenuate samples for left and right MIDI FX-bus accumulator. ALSA uses accumulators 4 and 5 for left and right PCM. diff --git a/MAINTAINERS b/MAINTAINERS index 1e2724e..1380312 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5396,7 +5396,7 @@ F: drivers/media/video/*7146* F: include/media/*7146* SAMSUNG AUDIO (ASoC) DRIVERS -M: Jassi Brar <jassi.brar@samsung.com> +M: Jassi Brar <jassisinghbrar@gmail.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/samsung diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index 0db2411..7166620 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -409,6 +409,10 @@ struct platform_device s3c24xx_pwm_device = { .num_resources = 0, }; +static struct platform_device gta02_dfbmcs320_device = { + .name = "dfbmcs320", +}; + static struct i2c_board_info gta02_i2c_devs[] __initdata = { { I2C_BOARD_INFO("pcf50633", 0x73), @@ -523,6 +527,7 @@ static struct platform_device *gta02_devices[] __initdata = { &s3c_device_iis, &samsung_asoc_dma, &s3c_device_i2c0, + >a02_dfbmcs320_device, >a02_buttons_device, &s3c_device_adc, &s3c_device_ts, diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index af91374..6e1907fa 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -178,16 +178,15 @@ static struct i2c_board_info __initdata mop500_i2c0_devices[] = { .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, -}; - -/* I2C0 devices only available prior to HREFv60 */ -static struct i2c_board_info __initdata mop500_i2c0_old_devices[] = { + /* I2C0 devices only available prior to HREFv60 */ { I2C_BOARD_INFO("tps61052", 0x33), .platform_data = &mop500_tps61052_data, }, }; +#define NUM_PRE_V60_I2C0_DEVICES 1 + static struct i2c_board_info __initdata mop500_i2c2_devices[] = { { /* lp5521 LED driver, 1st device */ @@ -425,6 +424,8 @@ static void __init mop500_uart_init(void) static void __init mop500_init_machine(void) { + int i2c0_devs; + /* * The HREFv60 board removed a GPIO expander and routed * all these GPIO pins to the internal GPIO controller @@ -448,11 +449,11 @@ static void __init mop500_init_machine(void) platform_device_register(&ab8500_device); - i2c_register_board_info(0, mop500_i2c0_devices, - ARRAY_SIZE(mop500_i2c0_devices)); - if (!machine_is_hrefv60()) - i2c_register_board_info(0, mop500_i2c0_old_devices, - ARRAY_SIZE(mop500_i2c0_old_devices)); + i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); + if (machine_is_hrefv60()) + i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; + + i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, ARRAY_SIZE(mop500_i2c2_devices)); } diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 0b4be43..adee12e 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -228,6 +228,7 @@ #include <linux/kthread.h> #include <linux/jiffies.h> #include <linux/acpi.h> +#include <linux/syscore_ops.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -1238,6 +1239,7 @@ static int suspend(int vetoable) local_irq_disable(); sysdev_suspend(PMSG_SUSPEND); + syscore_suspend(); local_irq_enable(); @@ -1255,6 +1257,7 @@ static int suspend(int vetoable) apm_error("suspend", err); err = (err == APM_SUCCESS) ? 0 : -EIO; + syscore_resume(); sysdev_resume(); local_irq_enable(); @@ -1280,6 +1283,7 @@ static void standby(void) local_irq_disable(); sysdev_suspend(PMSG_SUSPEND); + syscore_suspend(); local_irq_enable(); err = set_system_power_state(APM_STATE_STANDBY); @@ -1287,6 +1291,7 @@ static void standby(void) apm_error("standby", err); local_irq_disable(); + syscore_resume(); sysdev_resume(); local_irq_enable(); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 224a84f..dc9e212 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -593,8 +593,12 @@ static int x86_setup_perfctr(struct perf_event *event) return -EOPNOTSUPP; } + /* + * Do not allow config1 (extended registers) to propagate, + * there's no sane user-space generalization yet: + */ if (attr->type == PERF_TYPE_RAW) - return x86_pmu_extra_regs(event->attr.config, event); + return 0; if (attr->type == PERF_TYPE_HW_CACHE) return set_ext_hw_attr(hwc, event); @@ -616,8 +620,8 @@ static int x86_setup_perfctr(struct perf_event *event) /* * Branch tracing: */ - if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && - (hwc->sample_period == 1)) { + if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS && + !attr->freq && hwc->sample_period == 1) { /* BTS is not supported by this architecture. */ if (!x86_pmu.bts_active) return -EOPNOTSUPP; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 8fc2b2c..9ae4a2a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -25,7 +25,7 @@ struct intel_percore { /* * Intel PerfMon, used on Core and later. */ -static const u64 intel_perfmon_event_map[] = +static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly = { [PERF_COUNT_HW_CPU_CYCLES] = 0x003c, [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, @@ -391,12 +391,12 @@ static __initconst const u64 nehalem_hw_cache_event_ids { [ C(L1D) ] = { [ C(OP_READ) ] = { - [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI */ - [ C(RESULT_MISS) ] = 0x0140, /* L1D_CACHE_LD.I_STATE */ + [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS */ + [ C(RESULT_MISS) ] = 0x0151, /* L1D.REPL */ }, [ C(OP_WRITE) ] = { - [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI */ - [ C(RESULT_MISS) ] = 0x0141, /* L1D_CACHE_ST.I_STATE */ + [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES */ + [ C(RESULT_MISS) ] = 0x0251, /* L1D.M_REPL */ }, [ C(OP_PREFETCH) ] = { [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS */ @@ -998,6 +998,9 @@ intel_bts_constraints(struct perf_event *event) struct hw_perf_event *hwc = &event->hw; unsigned int hw_event, bts_event; + if (event->attr.freq) + return NULL; + hw_event = hwc->config & INTEL_ARCH_EVENT_MASK; bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS); @@ -1305,7 +1308,7 @@ static void intel_clovertown_quirks(void) * AJ106 could possibly be worked around by not allowing LBR * usage from PEBS, including the fixup. * AJ68 could possibly be worked around by always programming - * a pebs_event_reset[0] value and coping with the lost events. + * a pebs_event_reset[0] value and coping with the lost events. * * But taken together it might just make sense to not enable PEBS on * these chips. @@ -1409,6 +1412,18 @@ static __init int intel_pmu_init(void) x86_pmu.percore_constraints = intel_nehalem_percore_constraints; x86_pmu.enable_all = intel_pmu_nhm_enable_all; x86_pmu.extra_regs = intel_nehalem_extra_regs; + + if (ebx & 0x40) { + /* + * Erratum AAJ80 detected, we work it around by using + * the BR_MISP_EXEC.ANY event. This will over-count + * branch-misses, but it's still much better than the + * architectural event which is often completely bogus: + */ + intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89; + + pr_cont("erratum AAJ80 worked around, "); + } pr_cont("Nehalem events, "); break; @@ -1425,6 +1440,7 @@ static __init int intel_pmu_init(void) case 37: /* 32 nm nehalem, "Clarkdale" */ case 44: /* 32 nm nehalem, "Gulftown" */ + case 47: /* 32 nm Xeon E7 */ memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs, diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index f4c1da2..44d4383 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -946,7 +946,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) if (!x86_perf_event_set_period(event)) continue; if (perf_event_overflow(event, 1, &data, regs)) - p4_pmu_disable_event(event); + x86_pmu_stop(event, 0); } if (handled) { diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index d77089d..4340ee0 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -64,47 +64,41 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) int arch_show_interrupts(struct seq_file *p, int prec) { - int j; - - seq_printf(p, "%*s: ", prec, "NMI"); - for_each_online_cpu(j) - seq_printf(p, "%10u ", nmi_count(j)); - seq_putc(p, '\n'); seq_printf(p, "%*s: ", prec, "ERR"); seq_printf(p, "%10u\n", atomic_read(&irq_err_count)); return 0; } -static void xtensa_irq_mask(struct irq_chip *d) +static void xtensa_irq_mask(struct irq_data *d) { cached_irq_mask &= ~(1 << d->irq); set_sr (cached_irq_mask, INTENABLE); } -static void xtensa_irq_unmask(struct irq_chip *d) +static void xtensa_irq_unmask(struct irq_data *d) { cached_irq_mask |= 1 << d->irq; set_sr (cached_irq_mask, INTENABLE); } -static void xtensa_irq_enable(struct irq_chip *d) +static void xtensa_irq_enable(struct irq_data *d) { variant_irq_enable(d->irq); xtensa_irq_unmask(d->irq); } -static void xtensa_irq_disable(struct irq_chip *d) +static void xtensa_irq_disable(struct irq_data *d) { xtensa_irq_mask(d->irq); variant_irq_disable(d->irq); } -static void xtensa_irq_ack(struct irq_chip *d) +static void xtensa_irq_ack(struct irq_data *d) { set_sr(1 << d->irq, INTCLEAR); } -static int xtensa_irq_retrigger(struct irq_chip *d) +static int xtensa_irq_retrigger(struct irq_data *d) { set_sr (1 << d->irq, INTSET); return 1; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 39d829c..71afe03 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -150,7 +150,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ), - .flags = AHCI_FLAG_COMMON, + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, @@ -261,6 +261,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ + { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ + { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ + { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ /* 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, diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 3986500..12c5282 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -229,6 +229,10 @@ enum { EM_CTL_ALHD = (1 << 26), /* Activity LED */ EM_CTL_XMT = (1 << 25), /* Transmit Only */ EM_CTL_SMB = (1 << 24), /* Single Message Buffer */ + EM_CTL_SGPIO = (1 << 19), /* SGPIO messages supported */ + EM_CTL_SES = (1 << 18), /* SES-2 messages supported */ + EM_CTL_SAFTE = (1 << 17), /* SAF-TE messages supported */ + EM_CTL_LED = (1 << 16), /* LED messages supported */ /* em message type */ EM_MSG_TYPE_LED = (1 << 0), /* LED */ diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 0bc3fd6..6f6e771 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -309,6 +309,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (PBG) */ { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 26d4523..ff9d832 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -109,6 +109,8 @@ static ssize_t ahci_read_em_buffer(struct device *dev, static ssize_t ahci_store_em_buffer(struct device *dev, struct device_attribute *attr, const char *buf, size_t size); +static ssize_t ahci_show_em_supported(struct device *dev, + struct device_attribute *attr, char *buf); static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); @@ -116,6 +118,7 @@ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, ahci_read_em_buffer, ahci_store_em_buffer); +static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL); struct device_attribute *ahci_shost_attrs[] = { &dev_attr_link_power_management_policy, @@ -126,6 +129,7 @@ struct device_attribute *ahci_shost_attrs[] = { &dev_attr_ahci_host_version, &dev_attr_ahci_port_cmd, &dev_attr_em_buffer, + &dev_attr_em_message_supported, NULL }; EXPORT_SYMBOL_GPL(ahci_shost_attrs); @@ -343,6 +347,24 @@ static ssize_t ahci_store_em_buffer(struct device *dev, return size; } +static ssize_t ahci_show_em_supported(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct ata_port *ap = ata_shost_to_port(shost); + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *mmio = hpriv->mmio; + u32 em_ctl; + + em_ctl = readl(mmio + HOST_EM_CTL); + + return sprintf(buf, "%s%s%s%s\n", + em_ctl & EM_CTL_LED ? "led " : "", + em_ctl & EM_CTL_SAFTE ? "saf-te " : "", + em_ctl & EM_CTL_SES ? "ses-2 " : "", + em_ctl & EM_CTL_SGPIO ? "sgpio " : ""); +} + /** * ahci_save_initial_config - Save and fixup initial config values * @dev: target AHCI device @@ -539,6 +561,27 @@ void ahci_start_engine(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; + u8 status; + + status = readl(port_mmio + PORT_TFDATA) & 0xFF; + + /* + * At end of section 10.1 of AHCI spec (rev 1.3), it states + * Software shall not set PxCMD.ST to 1 until it is determined + * that a functoinal device is present on the port as determined by + * PxTFD.STS.BSY=0, PxTFD.STS.DRQ=0 and PxSSTS.DET=3h + * + * Even though most AHCI host controllers work without this check, + * specific controller will fail under this condition + */ + if (status & (ATA_BUSY | ATA_DRQ)) + return; + else { + ahci_scr_read(&ap->link, SCR_STATUS, &tmp); + + if ((tmp & 0xf) != 0x3) + return; + } /* start DMA */ tmp = readl(port_mmio + PORT_CMD); @@ -1897,7 +1940,17 @@ static void ahci_pmp_attach(struct ata_port *ap) ahci_enable_fbs(ap); pp->intr_mask |= PORT_IRQ_BAD_PMP; - writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* + * We must not change the port interrupt mask register if the + * port is marked frozen, the value in pp->intr_mask will be + * restored later when the port is thawed. + * + * Note that during initialization, the port is marked as + * frozen since the irq handler is not yet registered. + */ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); } static void ahci_pmp_detach(struct ata_port *ap) @@ -1913,7 +1966,10 @@ static void ahci_pmp_detach(struct ata_port *ap) writel(cmd, port_mmio + PORT_CMD); pp->intr_mask &= ~PORT_IRQ_BAD_PMP; - writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + + /* see comment above in ahci_pmp_attach() */ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); } int ahci_port_resume(struct ata_port *ap) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 423c0a6..76c3c15 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4139,6 +4139,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { */ { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-216D", "1.08", ATA_HORKAGE_NOSETXFER }, /* End Marker */ { } @@ -5480,7 +5481,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) if (!ap) return NULL; - ap->pflags |= ATA_PFLAG_INITIALIZING; + ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN; ap->lock = &host->lock; ap->print_id = -1; ap->host = host; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 88cd22f..f26f2fe 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3316,6 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, struct ata_eh_context *ehc = &link->eh_context; struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; enum ata_lpm_policy old_policy = link->lpm_policy; + bool no_dipm = ap->flags & ATA_FLAG_NO_DIPM; unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM; unsigned int err_mask; int rc; @@ -3332,7 +3333,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, */ ata_for_each_dev(dev, link, ENABLED) { bool hipm = ata_id_has_hipm(dev->id); - bool dipm = ata_id_has_dipm(dev->id); + bool dipm = ata_id_has_dipm(dev->id) && !no_dipm; /* find the first enabled and LPM enabled devices */ if (!link_dev) @@ -3389,7 +3390,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, /* host config updated, enable DIPM if transitioning to MIN_POWER */ ata_for_each_dev(dev, link, ENABLED) { - if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) { + if (policy == ATA_LPM_MIN_POWER && !no_dipm && + ata_id_has_dipm(dev->id)) { err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE, SATA_DIPM); if (err_mask && err_mask != AC_ERR_DEV) { diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 0da0dcc..a5fdbdc 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -33,11 +33,12 @@ #define DRV_NAME "pata_at91" -#define DRV_VERSION "0.1" +#define DRV_VERSION "0.2" #define CF_IDE_OFFSET 0x00c00000 #define CF_ALT_IDE_OFFSET 0x00e00000 #define CF_IDE_RES_SIZE 0x08 +#define NCS_RD_PULSE_LIMIT 0x3f /* maximal value for pulse bitfields */ struct at91_ide_info { unsigned long mode; @@ -49,8 +50,18 @@ struct at91_ide_info { void __iomem *alt_addr; }; -static const struct ata_timing initial_timing = - {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0}; +static const struct ata_timing initial_timing = { + .mode = XFER_PIO_0, + .setup = 70, + .act8b = 290, + .rec8b = 240, + .cyc8b = 600, + .active = 165, + .recover = 150, + .dmack_hold = 0, + .cycle = 600, + .udma = 0 +}; static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz) { @@ -109,6 +120,11 @@ static void set_smc_timing(struct device *dev, /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */ ncs_read_setup = 1; ncs_read_pulse = read_cycle - 2; + if (ncs_read_pulse > NCS_RD_PULSE_LIMIT) { + ncs_read_pulse = NCS_RD_PULSE_LIMIT; + dev_warn(dev, "ncs_read_pulse limited to maximal value %lu\n", + ncs_read_pulse); + } /* Write timings same as read timings */ write_cycle = read_cycle; diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c index 90af294..c126db3 100644 --- a/drivers/base/syscore.c +++ b/drivers/base/syscore.c @@ -73,6 +73,7 @@ int syscore_suspend(void) return ret; } +EXPORT_SYMBOL_GPL(syscore_suspend); /** * syscore_resume - Execute all the registered system core resume callbacks. @@ -95,6 +96,7 @@ void syscore_resume(void) "Interrupts enabled after %pF\n", ops->resume); } } +EXPORT_SYMBOL_GPL(syscore_resume); #endif /* CONFIG_PM_SLEEP */ /** diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index a3755ff..bc8ce48 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2550,7 +2550,6 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, const struct parport_pc_via_data *via) { short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 }; - struct resource *base_res; u32 ite8872set; u32 ite8872_lpt, ite8872_lpthi; u8 ite8872_irq, type; @@ -2561,8 +2560,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, /* make sure which one chip */ for (i = 0; i < 5; i++) { - base_res = request_region(inta_addr[i], 32, "it887x"); - if (base_res) { + if (request_region(inta_addr[i], 32, "it887x")) { int test; pci_write_config_dword(pdev, 0x60, 0xe5000000 | inta_addr[i]); @@ -2571,7 +2569,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, test = inb(inta_addr[i]); if (test != 0xff) break; - release_region(inta_addr[i], 0x8); + release_region(inta_addr[i], 32); } } if (i >= 5) { @@ -2635,7 +2633,7 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, /* * Release the resource so that parport_pc_probe_port can get it. */ - release_resource(base_res); + release_region(inta_addr[i], 32); if (parport_pc_probe_port(ite8872_lpt, ite8872_lpthi, irq, PARPORT_DMA_NONE, &pdev->dev, 0)) { printk(KERN_INFO diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 316f484..80f9c88 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -220,6 +220,7 @@ static int __init coh901331_probe(struct platform_device *pdev) } clk_disable(rtap->clk); + platform_set_drvdata(pdev, rtap); rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops, THIS_MODULE); if (IS_ERR(rtap->rtc)) { @@ -227,11 +228,10 @@ static int __init coh901331_probe(struct platform_device *pdev) goto out_no_rtc; } - platform_set_drvdata(pdev, rtap); - return 0; out_no_rtc: + platform_set_drvdata(pdev, NULL); out_no_clk_enable: clk_put(rtap->clk); out_no_clk: diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 47f8cdb..74273e6 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1658,8 +1658,12 @@ static void gsm_queue(struct gsm_mux *gsm) if ((gsm->control & ~PF) == UI) gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); - /* generate final CRC with received FCS */ - gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); + if (gsm->encoding == 0){ + /* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only. + In this case it contain the last piece of data + required to generate final CRC */ + gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); + } if (gsm->fcs != GOOD_FCS) { gsm->bad_fcs++; if (debug & 4) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index cb36b0d..62df72d 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -382,12 +382,13 @@ static void imx_start_tx(struct uart_port *port) static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = dev_id; - unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; + unsigned int val; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); writel(USR1_RTSD, sport->port.membase + USR1); + val = readl(sport->port.membase + USR1) & USR1_RTSS; uart_handle_cts_change(&sport->port, !!val); wake_up_interruptible(&sport->port.state->port.delta_msr_wait); diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 1ac9412..a2eee57 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -8,6 +8,7 @@ #include <linux/sysrq.h> #include <linux/stop_machine.h> #include <linux/freezer.h> +#include <linux/syscore_ops.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -70,8 +71,13 @@ static int xen_suspend(void *data) BUG_ON(!irqs_disabled()); err = sysdev_suspend(PMSG_FREEZE); + if (!err) { + err = syscore_suspend(); + if (err) + sysdev_resume(); + } if (err) { - printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", + printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n", err); return err; } @@ -95,6 +101,7 @@ static int xen_suspend(void *data) xen_timer_resume(); } + syscore_resume(); sysdev_resume(); return 0; diff --git a/fs/dcache.c b/fs/dcache.c index 129a357..22a0ef4 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -99,12 +99,9 @@ static struct kmem_cache *dentry_cache __read_mostly; static unsigned int d_hash_mask __read_mostly; static unsigned int d_hash_shift __read_mostly; -struct dcache_hash_bucket { - struct hlist_bl_head head; -}; -static struct dcache_hash_bucket *dentry_hashtable __read_mostly; +static struct hlist_bl_head *dentry_hashtable __read_mostly; -static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, +static inline struct hlist_bl_head *d_hash(struct dentry *parent, unsigned long hash) { hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; @@ -112,16 +109,6 @@ static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, return dentry_hashtable + (hash & D_HASHMASK); } -static inline void spin_lock_bucket(struct dcache_hash_bucket *b) -{ - bit_spin_lock(0, (unsigned long *)&b->head.first); -} - -static inline void spin_unlock_bucket(struct dcache_hash_bucket *b) -{ - __bit_spin_unlock(0, (unsigned long *)&b->head.first); -} - /* Statistics gathering. */ struct dentry_stat_t dentry_stat = { .age_limit = 45, @@ -167,8 +154,8 @@ static void d_free(struct dentry *dentry) if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); - /* if dentry was never inserted into hash, immediate free is OK */ - if (hlist_bl_unhashed(&dentry->d_hash)) + /* if dentry was never visible to RCU, immediate free is OK */ + if (!(dentry->d_flags & DCACHE_RCUACCESS)) __d_free(&dentry->d_u.d_rcu); else call_rcu(&dentry->d_u.d_rcu, __d_free); @@ -330,28 +317,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) */ void __d_drop(struct dentry *dentry) { - if (!(dentry->d_flags & DCACHE_UNHASHED)) { - if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) { - bit_spin_lock(0, - (unsigned long *)&dentry->d_sb->s_anon.first); - dentry->d_flags |= DCACHE_UNHASHED; - hlist_bl_del_init(&dentry->d_hash); - __bit_spin_unlock(0, - (unsigned long *)&dentry->d_sb->s_anon.first); - } else { - struct dcache_hash_bucket *b; + if (!d_unhashed(dentry)) { + struct hlist_bl_head *b; + if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) + b = &dentry->d_sb->s_anon; + else b = d_hash(dentry->d_parent, dentry->d_name.hash); - spin_lock_bucket(b); - /* - * We may not actually need to put DCACHE_UNHASHED - * manipulations under the hash lock, but follow - * the principle of least surprise. - */ - dentry->d_flags |= DCACHE_UNHASHED; - hlist_bl_del_rcu(&dentry->d_hash); - spin_unlock_bucket(b); - dentry_rcuwalk_barrier(dentry); - } + + hlist_bl_lock(b); + __hlist_bl_del(&dentry->d_hash); + dentry->d_hash.pprev = NULL; + hlist_bl_unlock(b); + + dentry_rcuwalk_barrier(dentry); } } EXPORT_SYMBOL(__d_drop); @@ -1304,7 +1282,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) dname[name->len] = 0; dentry->d_count = 1; - dentry->d_flags = DCACHE_UNHASHED; + dentry->d_flags = 0; spin_lock_init(&dentry->d_lock); seqcount_init(&dentry->d_seq); dentry->d_inode = NULL; @@ -1606,10 +1584,9 @@ struct dentry *d_obtain_alias(struct inode *inode) tmp->d_inode = inode; tmp->d_flags |= DCACHE_DISCONNECTED; list_add(&tmp->d_alias, &inode->i_dentry); - bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first); - tmp->d_flags &= ~DCACHE_UNHASHED; + hlist_bl_lock(&tmp->d_sb->s_anon); hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); - __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); + hlist_bl_unlock(&tmp->d_sb->s_anon); spin_unlock(&tmp->d_lock); spin_unlock(&inode->i_lock); security_d_instantiate(tmp, inode); @@ -1789,7 +1766,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; - struct dcache_hash_bucket *b = d_hash(parent, hash); + struct hlist_bl_head *b = d_hash(parent, hash); struct hlist_bl_node *node; struct dentry *dentry; @@ -1813,7 +1790,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, * * See Documentation/filesystems/path-lookup.txt for more details. */ - hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { + hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { struct inode *i; const char *tname; int tlen; @@ -1908,7 +1885,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; - struct dcache_hash_bucket *b = d_hash(parent, hash); + struct hlist_bl_head *b = d_hash(parent, hash); struct hlist_bl_node *node; struct dentry *found = NULL; struct dentry *dentry; @@ -1935,7 +1912,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) */ rcu_read_lock(); - hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { + hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { const char *tname; int tlen; @@ -2086,13 +2063,13 @@ again: } EXPORT_SYMBOL(d_delete); -static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b) +static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b) { BUG_ON(!d_unhashed(entry)); - spin_lock_bucket(b); - entry->d_flags &= ~DCACHE_UNHASHED; - hlist_bl_add_head_rcu(&entry->d_hash, &b->head); - spin_unlock_bucket(b); + hlist_bl_lock(b); + entry->d_flags |= DCACHE_RCUACCESS; + hlist_bl_add_head_rcu(&entry->d_hash, b); + hlist_bl_unlock(b); } static void _d_rehash(struct dentry * entry) @@ -3025,7 +3002,7 @@ static void __init dcache_init_early(void) dentry_hashtable = alloc_large_system_hash("Dentry cache", - sizeof(struct dcache_hash_bucket), + sizeof(struct hlist_bl_head), dhash_entries, 13, HASH_EARLY, @@ -3034,7 +3011,7 @@ static void __init dcache_init_early(void) 0); for (loop = 0; loop < (1 << d_hash_shift); loop++) - INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); + INIT_HLIST_BL_HEAD(dentry_hashtable + loop); } static void __init dcache_init(void) @@ -3057,7 +3034,7 @@ static void __init dcache_init(void) dentry_hashtable = alloc_large_system_hash("Dentry cache", - sizeof(struct dcache_hash_bucket), + sizeof(struct hlist_bl_head), dhash_entries, 13, 0, @@ -3066,7 +3043,7 @@ static void __init dcache_init(void) 0); for (loop = 0; loop < (1 << d_hash_shift); loop++) - INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); + INIT_HLIST_BL_HEAD(dentry_hashtable + loop); } /* SLAB cache for __getname() consumers */ diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index d2a70a4..b8d5c80 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; } +void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) +{ + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; + u64 file_size; + + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + mount_crypt_stat = + &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; + if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { + file_size = i_size_read(ecryptfs_inode_to_lower(inode)); + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) + file_size += crypt_stat->metadata_size; + } else + file_size = get_unaligned_be64(page_virt); + i_size_write(inode, (loff_t)file_size); + crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; +} + /** * ecryptfs_read_headers_virt * @page_virt: The virtual address into which to read the headers @@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt, rc = -EINVAL; goto out; } + if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) + ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), &bytes_read); diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index bd3cafd..e702827 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat { #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 #define ECRYPTFS_UNLINK_SIGS 0x00002000 +#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000 u32 flags; unsigned int file_version; size_t iv_bytes; @@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat { struct ecryptfs_inode_info { struct inode vfs_inode; struct inode *wii_inode; + struct mutex lower_file_mutex; + atomic_t lower_file_count; struct file *lower_file; struct ecryptfs_crypt_stat crypt_stat; }; @@ -626,6 +629,7 @@ struct ecryptfs_open_req { int ecryptfs_interpose(struct dentry *hidden_dentry, struct dentry *this_dentry, struct super_block *sb, u32 flags); +void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct dentry *lower_dentry, struct inode *ecryptfs_dir_inode); @@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file, struct dentry *lower_dentry, struct vfsmount *lower_mnt, const struct cred *cred); -int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); +int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry); +void ecryptfs_put_lower_file(struct inode *inode); int ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, size_t *packet_size, diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index cedc913..566e547 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | ECRYPTFS_ENCRYPTED); } mutex_unlock(&crypt_stat->cs_mutex); - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); + rc = ecryptfs_get_lower_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " - "the persistent file for the dentry with name " + "the lower file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out_free; @@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { rc = -EPERM; - printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " + printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " "file must hence be opened RO\n", __func__); - goto out_free; + goto out_put; } ecryptfs_set_file_lower( file, ecryptfs_inode_to_private(inode)->lower_file); @@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) "Plaintext passthrough mode is not " "enabled; returning -EIO\n"); mutex_unlock(&crypt_stat->cs_mutex); - goto out_free; + goto out_put; } rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); mutex_unlock(&crypt_stat->cs_mutex); goto out; } @@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, (unsigned long long)i_size_read(inode)); goto out; +out_put: + ecryptfs_put_lower_file(inode); out_free: kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); @@ -254,17 +257,13 @@ out: static int ecryptfs_flush(struct file *file, fl_owner_t td) { - int rc = 0; - struct file *lower_file = NULL; - - lower_file = ecryptfs_file_to_lower(file); - if (lower_file->f_op && lower_file->f_op->flush) - rc = lower_file->f_op->flush(lower_file, td); - return rc; + return file->f_mode & FMODE_WRITE + ? filemap_write_and_wait(file->f_mapping) : 0; } static int ecryptfs_release(struct inode *inode, struct file *file) { + ecryptfs_put_lower_file(inode); kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); return 0; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f99051b..4d4cc6a 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) "context; rc = [%d]\n", rc); goto out; } - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); + rc = ecryptfs_get_lower_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " - "the persistent file for the dentry with name " + "the lower file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out; } rc = ecryptfs_write_metadata(ecryptfs_dentry); - if (rc) { + if (rc) printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); - goto out; - } + ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); out: return rc; } @@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct dentry *lower_dir_dentry; struct vfsmount *lower_mnt; struct inode *lower_inode; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct ecryptfs_crypt_stat *crypt_stat; char *page_virt = NULL; - u64 file_size; - int rc = 0; + int put_lower = 0, rc = 0; lower_dir_dentry = lower_dentry->d_parent; lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( @@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, rc = -ENOMEM; goto out; } - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); + rc = ecryptfs_get_lower_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " - "the persistent file for the dentry with name " + "the lower file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out_free_kmem; } + put_lower = 1; crypt_stat = &ecryptfs_inode_to_private( ecryptfs_dentry->d_inode)->crypt_stat; /* TODO: lock for crypt_stat comparison */ @@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, } crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; } - mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - file_size = (crypt_stat->metadata_size - + i_size_read(lower_dentry->d_inode)); - else - file_size = i_size_read(lower_dentry->d_inode); - } else { - file_size = get_unaligned_be64(page_virt); - } - i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); + ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); out_free_kmem: kmem_cache_free(ecryptfs_header_cache_2, page_virt); goto out; @@ -322,6 +309,8 @@ out_put: mntput(lower_mnt); d_drop(ecryptfs_dentry); out: + if (put_lower) + ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); return rc; } @@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); dput(lower_dentry); - if (!rc) - d_delete(lower_dentry); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); @@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); out_lock: unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - dput(lower_new_dentry->d_parent); - dput(lower_old_dentry->d_parent); + dput(lower_new_dir_dentry); + dput(lower_old_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); return rc; @@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, if (unlikely((ia->ia_size == i_size))) { lower_ia->ia_valid &= ~ATTR_SIZE; - goto out; + return 0; } + rc = ecryptfs_get_lower_file(dentry); + if (rc) + return rc; crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; /* Switch on growing or shrinking file */ if (ia->ia_size > i_size) { @@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, lower_ia->ia_valid &= ~ATTR_SIZE; } out: + ecryptfs_put_lower_file(inode); return rc; } @@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) mount_crypt_stat = &ecryptfs_superblock_to_private( dentry->d_sb)->mount_crypt_stat; + rc = ecryptfs_get_lower_file(dentry); + if (rc) { + mutex_unlock(&crypt_stat->cs_mutex); + goto out; + } rc = ecryptfs_read_metadata(dentry); + ecryptfs_put_lower_file(inode); if (rc) { if (!(mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { @@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) goto out; } rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); } } mutex_unlock(&crypt_stat->cs_mutex); + if (S_ISREG(inode->i_mode)) { + rc = filemap_write_and_wait(inode->i_mapping); + if (rc) + goto out; + fsstack_copy_attr_all(inode, lower_inode); + } memcpy(&lower_ia, ia, sizeof(lower_ia)); if (ia->ia_valid & ATTR_FILE) lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 0851ab6..69f994a 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c @@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread; * @ignored: ignored * * The eCryptfs kernel thread that has the responsibility of getting - * the lower persistent file with RW permissions. + * the lower file with RW permissions. * * Returns zero on success; non-zero otherwise */ @@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file, int rc = 0; /* Corresponding dput() and mntput() are done when the - * persistent file is fput() when the eCryptfs inode is - * destroyed. */ + * lower file is fput() when all eCryptfs files for the inode are + * released. */ dget(lower_dentry); mntget(lower_mnt); flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index fdb2eb0..89b9338 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...) } /** - * ecryptfs_init_persistent_file + * ecryptfs_init_lower_file * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with * the lower dentry and the lower mount set * @@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...) * inode. All I/O operations to the lower inode occur through that * file. When the first eCryptfs dentry that interposes with the first * lower dentry for that inode is created, this function creates the - * persistent file struct and associates it with the eCryptfs - * inode. When the eCryptfs inode is destroyed, the file is closed. + * lower file struct and associates it with the eCryptfs + * inode. When all eCryptfs files associated with the inode are released, the + * file is closed. * - * The persistent file will be opened with read/write permissions, if + * The lower file will be opened with read/write permissions, if * possible. Otherwise, it is opened read-only. * - * This function does nothing if a lower persistent file is already + * This function does nothing if a lower file is already * associated with the eCryptfs inode. * * Returns zero on success; non-zero otherwise */ -int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) +static int ecryptfs_init_lower_file(struct dentry *dentry, + struct file **lower_file) { const struct cred *cred = current_cred(); - struct ecryptfs_inode_info *inode_info = - ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); - int rc = 0; + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); + int rc; - if (!inode_info->lower_file) { - struct dentry *lower_dentry; - struct vfsmount *lower_mnt = - ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); + rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, + cred); + if (rc) { + printk(KERN_ERR "Error opening lower file " + "for lower_dentry [0x%p] and lower_mnt [0x%p]; " + "rc = [%d]\n", lower_dentry, lower_mnt, rc); + (*lower_file) = NULL; + } + return rc; +} - lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); - rc = ecryptfs_privileged_open(&inode_info->lower_file, - lower_dentry, lower_mnt, cred); - if (rc) { - printk(KERN_ERR "Error opening lower persistent file " - "for lower_dentry [0x%p] and lower_mnt [0x%p]; " - "rc = [%d]\n", lower_dentry, lower_mnt, rc); - inode_info->lower_file = NULL; - } +int ecryptfs_get_lower_file(struct dentry *dentry) +{ + struct ecryptfs_inode_info *inode_info = + ecryptfs_inode_to_private(dentry->d_inode); + int count, rc = 0; + + mutex_lock(&inode_info->lower_file_mutex); + count = atomic_inc_return(&inode_info->lower_file_count); + if (WARN_ON_ONCE(count < 1)) + rc = -EINVAL; + else if (count == 1) { + rc = ecryptfs_init_lower_file(dentry, + &inode_info->lower_file); + if (rc) + atomic_set(&inode_info->lower_file_count, 0); } + mutex_unlock(&inode_info->lower_file_mutex); return rc; } +void ecryptfs_put_lower_file(struct inode *inode) +{ + struct ecryptfs_inode_info *inode_info; + + inode_info = ecryptfs_inode_to_private(inode); + if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, + &inode_info->lower_file_mutex)) { + fput(inode_info->lower_file); + inode_info->lower_file = NULL; + mutex_unlock(&inode_info->lower_file_mutex); + } +} + static struct inode *ecryptfs_get_inode(struct inode *lower_inode, struct super_block *sb) { diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index bacc882..245b517 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) if (unlikely(!inode_info)) goto out; ecryptfs_init_crypt_stat(&inode_info->crypt_stat); + mutex_init(&inode_info->lower_file_mutex); + atomic_set(&inode_info->lower_file_count, 0); inode_info->lower_file = NULL; inode = &inode_info->vfs_inode; out: @@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head) * * This is used during the final destruction of the inode. All * allocation of memory related to the inode, including allocated - * memory in the crypt_stat struct, will be released here. This - * function also fput()'s the persistent file for the lower inode. + * memory in the crypt_stat struct, will be released here. * There should be no chance that this deallocation will be missed. */ static void ecryptfs_destroy_inode(struct inode *inode) @@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode) struct ecryptfs_inode_info *inode_info; inode_info = ecryptfs_inode_to_private(inode); - if (inode_info->lower_file) { - struct dentry *lower_dentry = - inode_info->lower_file->f_dentry; - - BUG_ON(!lower_dentry); - if (lower_dentry->d_inode) { - fput(inode_info->lower_file); - inode_info->lower_file = NULL; - } - } + BUG_ON(inode_info->lower_file); ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); call_rcu(&inode->i_rcu, ecryptfs_i_callback); } diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f07643e..7a4fb63 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -93,14 +93,12 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, static inline void spin_lock_bucket(unsigned int hash) { - struct hlist_bl_head *bl = &gl_hash_table[hash]; - bit_spin_lock(0, (unsigned long *)bl); + hlist_bl_lock(&gl_hash_table[hash]); } static inline void spin_unlock_bucket(unsigned int hash) { - struct hlist_bl_head *bl = &gl_hash_table[hash]; - __bit_spin_unlock(0, (unsigned long *)bl); + hlist_bl_unlock(&gl_hash_table[hash]); } static void gfs2_glock_dealloc(struct rcu_head *rcu) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 936f2cb..3dbad6f 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) goto out_free; } memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); + + /* + * We had to recover the master node, which means there was an + * unclean reboot. However, it is possible that the master node + * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. + * E.g., consider the following chain of events: + * + * 1. UBIFS was cleanly unmounted, so the master node is clean + * 2. UBIFS is being mounted R/W and starts changing the master + * node in the first (%UBIFS_MST_LNUM). A power cut happens, + * so this LEB ends up with some amount of garbage at the + * end. + * 3. UBIFS is being mounted R/O. We reach this place and + * recover the master node from the second LEB + * (%UBIFS_MST_LNUM + 1). But we cannot update the media + * because we are being mounted R/O. We have to defer the + * operation. + * 4. However, this master node (@c->mst_node) is marked as + * clean (since the step 1). And if we just return, the + * mount code will be confused and won't recover the master + * node when it is re-mounter R/W later. + * + * Thus, to force the recovery by marking the master node as + * dirty. + */ + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); } else { /* Write the recovered master node */ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index c75f613..be6c7b0 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1671,14 +1671,25 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (err) goto out; + dbg_gen("re-mounted read-write"); + c->remounting_rw = 0; + if (c->need_recovery) { c->need_recovery = 0; ubifs_msg("deferred recovery completed"); + } else { + /* + * Do not run the debugging space check if the were doing + * recovery, because when we saved the information we had the + * file-system in a state where the TNC and lprops has been + * modified in memory, but all the I/O operations (including a + * commit) were deferred. So the file-system was in + * "non-committed" state. Now the file-system is in committed + * state, and of course the amount of free space will change + * because, for example, the old index size was imprecise. + */ + err = dbg_check_space_info(c); } - - dbg_gen("re-mounted read-write"); - c->remounting_rw = 0; - err = dbg_check_space_info(c); mutex_unlock(&c->umount_mutex); return err; @@ -1761,10 +1772,12 @@ static void ubifs_put_super(struct super_block *sb) * of the media. For example, there will be dirty inodes if we failed * to write them back because of I/O errors. */ - ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); - ubifs_assert(c->budg_idx_growth == 0); - ubifs_assert(c->budg_dd_growth == 0); - ubifs_assert(c->budg_data_growth == 0); + if (!c->ro_error) { + ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); + ubifs_assert(c->budg_idx_growth == 0); + ubifs_assert(c->budg_dd_growth == 0); + ubifs_assert(c->budg_data_growth == 0); + } /* * The 'c->umount_lock' prevents races between UBIFS memory shrinker diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h index e612575..b4326bf 100644 --- a/include/linux/bit_spinlock.h +++ b/include/linux/bit_spinlock.h @@ -23,11 +23,11 @@ static inline void bit_spin_lock(int bitnum, unsigned long *addr) preempt_disable(); #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) while (unlikely(test_and_set_bit_lock(bitnum, addr))) { - while (test_bit(bitnum, addr)) { - preempt_enable(); + preempt_enable(); + do { cpu_relax(); - preempt_disable(); - } + } while (test_bit(bitnum, addr)); + preempt_disable(); } #endif __acquire(bitlock); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f2afed4..19d90a5 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -197,7 +197,7 @@ struct dentry_operations { * typically using d_splice_alias. */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -#define DCACHE_UNHASHED 0x0010 +#define DCACHE_RCUACCESS 0x0010 /* Entry has ever been RCU-visible */ #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched by inotify */ @@ -384,7 +384,7 @@ extern struct dentry *dget_parent(struct dentry *dentry); static inline int d_unhashed(struct dentry *dentry) { - return (dentry->d_flags & DCACHE_UNHASHED); + return hlist_bl_unhashed(&dentry->d_hash); } static inline int d_unlinked(struct dentry *dentry) diff --git a/include/linux/libata.h b/include/linux/libata.h index 7f675aa..04f32a3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -137,8 +137,6 @@ enum { ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_AN = (1 << 7), /* AN configured */ - ATA_DFLAG_HIPM = (1 << 8), /* device supports HIPM */ - ATA_DFLAG_DIPM = (1 << 9), /* device supports DIPM */ ATA_DFLAG_DMADIR = (1 << 10), /* device requires DMADIR */ ATA_DFLAG_CFG_MASK = (1 << 12) - 1, @@ -198,6 +196,7 @@ enum { * management */ ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity * led */ + ATA_FLAG_NO_DIPM = (1 << 23), /* host not happy with DIPM */ /* bits 24:31 of ap->flags are reserved for LLD specific flags */ diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h index 5bad17d..31f9d75 100644 --- a/include/linux/list_bl.h +++ b/include/linux/list_bl.h @@ -2,6 +2,7 @@ #define _LINUX_LIST_BL_H #include <linux/list.h> +#include <linux/bit_spinlock.h> /* * Special version of lists, where head of the list has a lock in the lowest @@ -114,6 +115,16 @@ static inline void hlist_bl_del_init(struct hlist_bl_node *n) } } +static inline void hlist_bl_lock(struct hlist_bl_head *b) +{ + bit_spin_lock(0, (unsigned long *)b); +} + +static inline void hlist_bl_unlock(struct hlist_bl_head *b) +{ + __bit_spin_unlock(0, (unsigned long *)b); +} + /** * hlist_bl_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop cursor. diff --git a/include/linux/security.h b/include/linux/security.h index ca02f17..8ce59ef 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1456,7 +1456,7 @@ struct security_operations { struct inode *new_dir, struct dentry *new_dentry); int (*inode_readlink) (struct dentry *dentry); int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); - int (*inode_permission) (struct inode *inode, int mask); + int (*inode_permission) (struct inode *inode, int mask, unsigned flags); int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); int (*inode_setxattr) (struct dentry *dentry, const char *name, diff --git a/kernel/kexec.c b/kernel/kexec.c index 55936f9..87b77de 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -33,6 +33,7 @@ #include <linux/vmalloc.h> #include <linux/swap.h> #include <linux/kmsg_dump.h> +#include <linux/syscore_ops.h> #include <asm/page.h> #include <asm/uaccess.h> @@ -1532,6 +1533,11 @@ int kernel_kexec(void) local_irq_disable(); /* Suspend system devices */ error = sysdev_suspend(PMSG_FREEZE); + if (!error) { + error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (error) goto Enable_irqs; } else @@ -1546,6 +1552,7 @@ int kernel_kexec(void) #ifdef CONFIG_KEXEC_JUMP if (kexec_image->preserve_context) { + syscore_resume(); sysdev_resume(); Enable_irqs: local_irq_enable(); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index aeabd26..50aae66 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -273,8 +273,11 @@ static int create_image(int platform_mode) local_irq_disable(); error = sysdev_suspend(PMSG_FREEZE); - if (!error) + if (!error) { error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (error) { printk(KERN_ERR "PM: Some system devices failed to power down, " "aborting hibernation\n"); @@ -407,8 +410,11 @@ static int resume_target_kernel(bool platform_mode) local_irq_disable(); error = sysdev_suspend(PMSG_QUIESCE); - if (!error) + if (!error) { error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (error) goto Enable_irqs; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 2814c32..8935369 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -164,8 +164,11 @@ static int suspend_enter(suspend_state_t state) BUG_ON(!irqs_disabled()); error = sysdev_suspend(PMSG_SUSPEND); - if (!error) + if (!error) { error = syscore_suspend(); + if (error) + sysdev_resume(); + } if (!error) { if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { error = suspend_ops->enter(state); diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 659326c..006ad81 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -332,7 +332,7 @@ static int conf_choice(struct menu *menu) } if (!child) continue; - if (line[strlen(line) - 1] == '?') { + if (line[0] && line[strlen(line) - 1] == '?') { print_help(child); continue; } diff --git a/security/capability.c b/security/capability.c index 2984ea4..bbb5115 100644 --- a/security/capability.c +++ b/security/capability.c @@ -181,7 +181,7 @@ static int cap_inode_follow_link(struct dentry *dentry, return 0; } -static int cap_inode_permission(struct inode *inode, int mask) +static int cap_inode_permission(struct inode *inode, int mask, unsigned flags) { return 0; } diff --git a/security/security.c b/security/security.c index 1011423..4ba6d4c 100644 --- a/security/security.c +++ b/security/security.c @@ -518,16 +518,14 @@ int security_inode_permission(struct inode *inode, int mask) { if (unlikely(IS_PRIVATE(inode))) return 0; - return security_ops->inode_permission(inode, mask); + return security_ops->inode_permission(inode, mask, 0); } int security_inode_exec_permission(struct inode *inode, unsigned int flags) { if (unlikely(IS_PRIVATE(inode))) return 0; - if (flags) - return -ECHILD; - return security_ops->inode_permission(inode, MAY_EXEC); + return security_ops->inode_permission(inode, MAY_EXEC, flags); } int security_inode_setattr(struct dentry *dentry, struct iattr *attr) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 9da6420..1d027e2 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -471,6 +471,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) * @avd: access vector decisions * @result: result from avc_has_perm_noaudit * @a: auxiliary audit data + * @flags: VFS walk flags * * Audit the granting or denial of permissions in accordance * with the policy. This function is typically called by @@ -481,9 +482,10 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) * be performed under a lock, to allow the lock to be released * before calling the auditing code. */ -void avc_audit(u32 ssid, u32 tsid, +int avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, - struct av_decision *avd, int result, struct common_audit_data *a) + struct av_decision *avd, int result, struct common_audit_data *a, + unsigned flags) { struct common_audit_data stack_data; u32 denied, audited; @@ -515,11 +517,24 @@ void avc_audit(u32 ssid, u32 tsid, else audited = requested & avd->auditallow; if (!audited) - return; + return 0; + if (!a) { a = &stack_data; COMMON_AUDIT_DATA_INIT(a, NONE); } + + /* + * When in a RCU walk do the audit on the RCU retry. This is because + * the collection of the dname in an inode audit message is not RCU + * safe. Note this may drop some audits when the situation changes + * during retry. However this is logically just as if the operation + * happened a little later. + */ + if ((a->type == LSM_AUDIT_DATA_FS) && + (flags & IPERM_FLAG_RCU)) + return -ECHILD; + a->selinux_audit_data.tclass = tclass; a->selinux_audit_data.requested = requested; a->selinux_audit_data.ssid = ssid; @@ -529,6 +544,7 @@ void avc_audit(u32 ssid, u32 tsid, a->lsm_pre_audit = avc_audit_pre_callback; a->lsm_post_audit = avc_audit_post_callback; common_lsm_audit(a); + return 0; } /** @@ -793,6 +809,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @auditdata: auxiliary audit data + * @flags: VFS walk flags * * Check the AVC to determine whether the @requested permissions are granted * for the SID pair (@ssid, @tsid), interpreting the permissions @@ -802,14 +819,19 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, * permissions are granted, -%EACCES if any permissions are denied, or * another -errno upon other errors. */ -int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, - u32 requested, struct common_audit_data *auditdata) +int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *auditdata, + unsigned flags) { struct av_decision avd; - int rc; + int rc, rc2; rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); - avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); + + rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata, + flags); + if (rc2) + return rc2; return rc; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f9c3764..f7cf0ea 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1446,8 +1446,11 @@ static int task_has_capability(struct task_struct *tsk, } rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); - if (audit == SECURITY_CAP_AUDIT) - avc_audit(sid, sid, sclass, av, &avd, rc, &ad); + if (audit == SECURITY_CAP_AUDIT) { + int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); + if (rc2) + return rc2; + } return rc; } @@ -1467,7 +1470,8 @@ static int task_has_system(struct task_struct *tsk, static int inode_has_perm(const struct cred *cred, struct inode *inode, u32 perms, - struct common_audit_data *adp) + struct common_audit_data *adp, + unsigned flags) { struct inode_security_struct *isec; struct common_audit_data ad; @@ -1487,7 +1491,7 @@ static int inode_has_perm(const struct cred *cred, ad.u.fs.inode = inode; } - return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); + return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); } /* Same as inode_has_perm, but pass explicit audit data containing @@ -1504,7 +1508,7 @@ static inline int dentry_has_perm(const struct cred *cred, COMMON_AUDIT_DATA_INIT(&ad, FS); ad.u.fs.path.mnt = mnt; ad.u.fs.path.dentry = dentry; - return inode_has_perm(cred, inode, av, &ad); + return inode_has_perm(cred, inode, av, &ad, 0); } /* Check whether a task can use an open file descriptor to @@ -1540,7 +1544,7 @@ static int file_has_perm(const struct cred *cred, /* av is zero if only checking access to the descriptor. */ rc = 0; if (av) - rc = inode_has_perm(cred, inode, av, &ad); + rc = inode_has_perm(cred, inode, av, &ad, 0); out: return rc; @@ -2103,7 +2107,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, file = file_priv->file; inode = file->f_path.dentry->d_inode; if (inode_has_perm(cred, inode, - FILE__READ | FILE__WRITE, NULL)) { + FILE__READ | FILE__WRITE, NULL, 0)) { drop_tty = 1; } } @@ -2635,7 +2639,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na return dentry_has_perm(cred, NULL, dentry, FILE__READ); } -static int selinux_inode_permission(struct inode *inode, int mask) +static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) { const struct cred *cred = current_cred(); struct common_audit_data ad; @@ -2657,7 +2661,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) perms = file_mask_to_av(inode->i_mode, mask); - return inode_has_perm(cred, inode, perms, &ad); + return inode_has_perm(cred, inode, perms, &ad, flags); } static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) @@ -3205,7 +3209,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) * new inode label or new policy. * This check is not redundant - do not remove. */ - return inode_has_perm(cred, inode, open_file_to_av(file), NULL); + return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); } /* task security operations */ diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 5615081..e77b2ac 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -54,11 +54,11 @@ struct avc_cache_stats { void __init avc_init(void); -void avc_audit(u32 ssid, u32 tsid, +int avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd, int result, - struct common_audit_data *a); + struct common_audit_data *a, unsigned flags); #define AVC_STRICT 1 /* Ignore permissive mode. */ int avc_has_perm_noaudit(u32 ssid, u32 tsid, @@ -66,9 +66,17 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, unsigned flags, struct av_decision *avd); -int avc_has_perm(u32 ssid, u32 tsid, - u16 tclass, u32 requested, - struct common_audit_data *auditdata); +int avc_has_perm_flags(u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *auditdata, + unsigned); + +static inline int avc_has_perm(u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *auditdata) +{ + return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0); +} u32 avc_policy_seqno(void); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index c6f8fca..400a5d5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -686,7 +686,7 @@ static int smack_inode_rename(struct inode *old_inode, * * Returns 0 if access is permitted, -EACCES otherwise */ -static int smack_inode_permission(struct inode *inode, int mask) +static int smack_inode_permission(struct inode *inode, int mask, unsigned flags) { struct smk_audit_info ad; @@ -696,6 +696,10 @@ static int smack_inode_permission(struct inode *inode, int mask) */ if (mask == 0) return 0; + + /* May be droppable after audit */ + if (flags & IPERM_FLAG_RCU) + return -ECHILD; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); smk_ad_setfield_u_fs_inode(&ad, inode); return smk_curacc(smk_of_inode(inode), mask, &ad); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 430f41d..759ade1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -937,6 +937,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec) } EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); +#ifdef SND_HDA_NEEDS_RESUME /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ static void restore_shutup_pins(struct hda_codec *codec) { @@ -953,6 +954,7 @@ static void restore_shutup_pins(struct hda_codec *codec) } codec->pins_shutup = 0; } +#endif static void init_hda_cache(struct hda_cache_rec *cache, unsigned int record_size); @@ -1329,6 +1331,7 @@ static void purify_inactive_streams(struct hda_codec *codec) } } +#ifdef SND_HDA_NEEDS_RESUME /* clean up all streams; called from suspend */ static void hda_cleanup_all_streams(struct hda_codec *codec) { @@ -1340,6 +1343,7 @@ static void hda_cleanup_all_streams(struct hda_codec *codec) really_cleanup_stream(codec, p); } } +#endif /* * amp access functions diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 52928d9..d3bd2c1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -14868,6 +14868,23 @@ static void alc269_fixup_hweq(struct hda_codec *codec, alc_write_coef_idx(codec, 0x1e, coef | 0x80); } +static void alc271_fixup_dmic(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + static struct hda_verb verbs[] = { + {0x20, AC_VERB_SET_COEF_INDEX, 0x0d}, + {0x20, AC_VERB_SET_PROC_COEF, 0x4000}, + {} + }; + unsigned int cfg; + + if (strcmp(codec->chip_name, "ALC271X")) + return; + cfg = snd_hda_codec_get_pincfg(codec, 0x12); + if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED) + snd_hda_sequence_write(codec, verbs); +} + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -14876,6 +14893,7 @@ enum { ALC269_FIXUP_ASUS_G73JW, ALC269_FIXUP_LENOVO_EAPD, ALC275_FIXUP_SONY_HWEQ, + ALC271_FIXUP_DMIC, }; static const struct alc_fixup alc269_fixups[] = { @@ -14929,7 +14947,11 @@ static const struct alc_fixup alc269_fixups[] = { .v.func = alc269_fixup_hweq, .chained = true, .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2 - } + }, + [ALC271_FIXUP_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc271_fixup_dmic, + }, }; static struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -14938,6 +14960,7 @@ static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), + SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index f7cd346..f5ccdbf 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -308,8 +308,6 @@ static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) snd_soc_dapm_add_routes(dapm, jz4740_codec_dapm_routes, ARRAY_SIZE(jz4740_codec_dapm_routes)); - snd_soc_dapm_new_widgets(codec); - jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index a54d2a5..4d9fb27 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -927,7 +927,7 @@ static struct platform_driver sn95031_codec_driver = { .owner = THIS_MODULE, }, .probe = sn95031_device_probe, - .remove = sn95031_device_remove, + .remove = __devexit_p(sn95031_device_remove), }; static int __init sn95031_init(void) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index ae1cadf..f52b623 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -247,8 +247,6 @@ static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int re case WM8903_REVISION_NUMBER: case WM8903_INTERRUPT_STATUS_1: case WM8903_WRITE_SEQUENCER_4: - case WM8903_POWER_MANAGEMENT_3: - case WM8903_POWER_MANAGEMENT_2: case WM8903_DC_SERVO_READBACK_1: case WM8903_DC_SERVO_READBACK_2: case WM8903_DC_SERVO_READBACK_3: @@ -875,34 +873,40 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0, SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), -SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, - 4, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, +SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2, + 1, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0, +SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0, +SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 0, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPL_ENA", 1, WM8903_ANALOGUE_HP_0, 4, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0), SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), +SND_SOC_DAPM_PGA_S("HPR_ENA", 1, WM8903_ANALOGUE_HP_0, 0, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0, +SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 5, 0, + NULL, 0), +SND_SOC_DAPM_PGA_S("LINEOUTL_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 4, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0, NULL, 0), SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0, +SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 1, 0, + NULL, 0), +SND_SOC_DAPM_PGA_S("LINEOUTR_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0), @@ -1037,10 +1041,14 @@ static const struct snd_soc_dapm_route intercon[] = { { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, - { "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" }, - { "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" }, - { "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" }, - { "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" }, + { "HPL_ENA", NULL, "Left Headphone Output PGA" }, + { "HPR_ENA", NULL, "Right Headphone Output PGA" }, + { "HPL_ENA_DLY", NULL, "HPL_ENA" }, + { "HPR_ENA_DLY", NULL, "HPR_ENA" }, + { "LINEOUTL_ENA", NULL, "Left Line Output PGA" }, + { "LINEOUTR_ENA", NULL, "Right Line Output PGA" }, + { "LINEOUTL_ENA_DLY", NULL, "LINEOUTL_ENA" }, + { "LINEOUTR_ENA_DLY", NULL, "LINEOUTR_ENA" }, { "HPL_DCS", NULL, "DCS Master" }, { "HPR_DCS", NULL, "DCS Master" }, diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 3290333..84e1bd1 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3261,20 +3261,36 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch volume updates (right only; we always do left then right). */ + snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, + WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME, + WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME, + WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, + WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME, + WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME, + WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME, + WM8994_DAC1_VU, WM8994_DAC1_VU); snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU, WM8994_DAC1_VU); + snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME, + WM8994_DAC2_VU, WM8994_DAC2_VU); snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU, WM8994_DAC2_VU); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 7b6b3c1..4005e9a 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -740,12 +740,12 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKL", "Input Switch", "MIXINL" }, { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output Mixer" }, + { "SPKL", "Output Switch", "Left Output PGA" }, { "SPKL", NULL, "TOCLK" }, { "SPKR", "Input Switch", "MIXINR" }, { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output Mixer" }, + { "SPKR", "Output Switch", "Right Output PGA" }, { "SPKR", NULL, "TOCLK" }, { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, @@ -767,8 +767,8 @@ static const struct snd_soc_dapm_route analogue_routes[] = { { "SPKOUTRP", NULL, "SPKR Driver" }, { "SPKOUTRN", NULL, "SPKR Driver" }, - { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, - { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, + { "Left Headphone Mux", "Mixer", "Left Output PGA" }, + { "Right Headphone Mux", "Mixer", "Right Output PGA" }, { "Headphone PGA", NULL, "Left Headphone Mux" }, { "Headphone PGA", NULL, "Right Headphone Mux" }, diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index b2e9198..d567c32 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c @@ -116,18 +116,20 @@ struct snd_soc_dai_driver sst_platform_dai[] = { static inline void sst_set_stream_status(struct sst_runtime_stream *stream, int state) { - spin_lock(&stream->status_lock); + unsigned long flags; + spin_lock_irqsave(&stream->status_lock, flags); stream->stream_status = state; - spin_unlock(&stream->status_lock); + spin_unlock_irqrestore(&stream->status_lock, flags); } static inline int sst_get_stream_status(struct sst_runtime_stream *stream) { int state; + unsigned long flags; - spin_lock(&stream->status_lock); + spin_lock_irqsave(&stream->status_lock, flags); state = stream->stream_status; - spin_unlock(&stream->status_lock); + spin_unlock_irqrestore(&stream->status_lock, flags); return state; } diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 38aac7d..9c7e8b4 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -350,8 +350,8 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, ctl = readl(regs + S3C_PCM_CTL); switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* Nothing to do, NB_NF by default */ + case SND_SOC_DAIFMT_IB_NF: + /* Nothing to do, IB_NF by default */ break; default: dev_err(pcm->dev, "Unsupported clock inversion!\n"); diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0c9997e..23c0e83 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1200,10 +1200,11 @@ static int fsi_probe(struct platform_device *pdev) master->fsib.master = master; pm_runtime_enable(&pdev->dev); - pm_runtime_resume(&pdev->dev); dev_set_drvdata(&pdev->dev, master); + pm_runtime_get_sync(&pdev->dev); fsi_soft_all_reset(master); + pm_runtime_put_sync(&pdev->dev); ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, id_entry->name, master); @@ -1218,8 +1219,17 @@ static int fsi_probe(struct platform_device *pdev) goto exit_free_irq; } - return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); + ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai, + ARRAY_SIZE(fsi_soc_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "cannot snd dai register\n"); + goto exit_snd_soc; + } + + return ret; +exit_snd_soc: + snd_soc_unregister_platform(&pdev->dev); exit_free_irq: free_irq(irq, master); exit_iounmap: @@ -1238,12 +1248,11 @@ static int fsi_remove(struct platform_device *pdev) master = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); - snd_soc_unregister_platform(&pdev->dev); - + free_irq(master->irq, master); pm_runtime_disable(&pdev->dev); - free_irq(master->irq, master); + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); + snd_soc_unregister_platform(&pdev->dev); iounmap(master->base); kfree(master); @@ -1321,3 +1330,4 @@ module_exit(fsi_mobile_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SuperH onchip FSI audio driver"); MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); +MODULE_ALIAS("platform:fsi-pcm-audio"); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b76b74d..d8562ce 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -629,6 +629,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rates |= codec_dai_drv->capture.rates; } + ret = -EINVAL; snd_pcm_limit_hw_rates(runtime); if (!runtime->hw.rates) { printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", @@ -640,7 +641,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) codec_dai->name, cpu_dai->name); goto config_err; } - if (!runtime->hw.channels_min || !runtime->hw.channels_max) { + if (!runtime->hw.channels_min || !runtime->hw.channels_max || + runtime->hw.channels_min > runtime->hw.channels_max) { printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", codec_dai->name, cpu_dai->name); goto config_err; @@ -2060,6 +2062,7 @@ const struct dev_pm_ops snd_soc_pm_ops = { .resume = snd_soc_resume, .poweroff = snd_soc_poweroff, }; +EXPORT_SYMBOL_GPL(snd_soc_pm_ops); /* ASoC platform driver */ static struct platform_driver soc_driver = { diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c index 8585957..556a571 100644 --- a/sound/soc/tegra/harmony.c +++ b/sound/soc/tegra/harmony.c @@ -370,6 +370,7 @@ static struct platform_driver tegra_snd_harmony_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, }, .probe = tegra_snd_harmony_probe, .remove = __devexit_p(tegra_snd_harmony_remove), |