Skip to content

Commit

Permalink
Merge pull request #48 from torvalds/master
Browse files Browse the repository at this point in the history
Sync up with Linus
  • Loading branch information
dabrace committed Mar 6, 2015
2 parents 9e013c9 + 84399bb commit 022b0d1
Show file tree
Hide file tree
Showing 86 changed files with 1,066 additions and 419 deletions.
22 changes: 17 additions & 5 deletions Documentation/power/suspend-and-interrupts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ but also to IPIs and to some other special-purpose interrupts.

The IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when
requesting a special-purpose interrupt. It causes suspend_device_irqs() to
leave the corresponding IRQ enabled so as to allow the interrupt to work all
the time as expected.
leave the corresponding IRQ enabled so as to allow the interrupt to work as
expected during the suspend-resume cycle, but does not guarantee that the
interrupt will wake the system from a suspended state -- for such cases it is
necessary to use enable_irq_wake().

Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one
user of it. Thus, if the IRQ is shared, all of the interrupt handlers installed
Expand Down Expand Up @@ -110,8 +112,9 @@ any special interrupt handling logic for it to work.
IRQF_NO_SUSPEND and enable_irq_wake()
-------------------------------------

There are no valid reasons to use both enable_irq_wake() and the IRQF_NO_SUSPEND
flag on the same IRQ.
There are very few valid reasons to use both enable_irq_wake() and the
IRQF_NO_SUSPEND flag on the same IRQ, and it is never valid to use both for the
same device.

First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND
interrupts (interrupt handlers are invoked after suspend_device_irqs()) are
Expand All @@ -120,4 +123,13 @@ handlers are not invoked after suspend_device_irqs()).

Second, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not
to individual interrupt handlers, so sharing an IRQ between a system wakeup
interrupt source and an IRQF_NO_SUSPEND interrupt source does not make sense.
interrupt source and an IRQF_NO_SUSPEND interrupt source does not generally
make sense.

In rare cases an IRQ can be shared between a wakeup device driver and an
IRQF_NO_SUSPEND user. In order for this to be safe, the wakeup device driver
must be able to discern spurious IRQs from genuine wakeup events (signalling
the latter to the core with pm_system_wakeup()), must use enable_irq_wake() to
ensure that the IRQ will function as a wakeup source, and must request the IRQ
with IRQF_COND_SUSPEND to tell the core that it meets these requirements. If
these requirements are not met, it is not valid to use IRQF_COND_SUSPEND.
8 changes: 8 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -8480,6 +8480,14 @@ S: Supported
L: netdev@vger.kernel.org
F: drivers/net/ethernet/samsung/sxgbe/

SAMSUNG THERMAL DRIVER
M: Lukasz Majewski <l.majewski@samsung.com>
L: linux-pm@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Supported
T: https://github.com/lmajewski/linux-samsung-thermal.git
F: drivers/thermal/samsung/

SAMSUNG USB2 PHY DRIVER
M: Kamil Debski <k.debski@samsung.com>
L: linux-kernel@vger.kernel.org
Expand Down
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ config X86_INTEL_QUARK
depends on X86_IO_APIC
select IOSF_MBI
select INTEL_IMR
select COMMON_CLK
---help---
Select to include support for Quark X1000 SoC.
Say Y here if you have a Quark based system such as the Arduino
Expand Down
28 changes: 11 additions & 17 deletions arch/x86/include/asm/xsave.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,15 @@ static inline int xsave_state_booting(struct xsave_struct *fx, u64 mask)
if (boot_cpu_has(X86_FEATURE_XSAVES))
asm volatile("1:"XSAVES"\n\t"
"2:\n\t"
: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
xstate_fault
: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
: "memory");
else
asm volatile("1:"XSAVE"\n\t"
"2:\n\t"
: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
xstate_fault
: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
: "memory");

asm volatile(xstate_fault
: "0" (0)
: "memory");

return err;
}

Expand All @@ -112,18 +109,15 @@ static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask)
if (boot_cpu_has(X86_FEATURE_XSAVES))
asm volatile("1:"XRSTORS"\n\t"
"2:\n\t"
: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
xstate_fault
: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
: "memory");
else
asm volatile("1:"XRSTOR"\n\t"
"2:\n\t"
: : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
xstate_fault
: "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
: "memory");

asm volatile(xstate_fault
: "0" (0)
: "memory");

return err;
}

Expand All @@ -149,9 +143,9 @@ static inline int xsave_state(struct xsave_struct *fx, u64 mask)
*/
alternative_input_2(
"1:"XSAVE,
"1:"XSAVEOPT,
XSAVEOPT,
X86_FEATURE_XSAVEOPT,
"1:"XSAVES,
XSAVES,
X86_FEATURE_XSAVES,
[fx] "D" (fx), "a" (lmask), "d" (hmask) :
"memory");
Expand All @@ -178,7 +172,7 @@ static inline int xrstor_state(struct xsave_struct *fx, u64 mask)
*/
alternative_input(
"1: " XRSTOR,
"1: " XRSTORS,
XRSTORS,
X86_FEATURE_XSAVES,
"D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
: "memory");
Expand Down
13 changes: 8 additions & 5 deletions arch/x86/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,14 @@ ENTRY(ret_from_fork)
testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread?
jz 1f

testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET
jnz int_ret_from_sys_call

RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
jmp ret_from_sys_call # go to the SYSRET fastpath
/*
* By the time we get here, we have no idea whether our pt_regs,
* ti flags, and ti status came from the 64-bit SYSCALL fast path,
* the slow path, or one of the ia32entry paths.
* Use int_ret_from_sys_call to return, since it can safely handle
* all of the above.
*/
jmp int_ret_from_sys_call

1:
subq $REST_SKIP, %rsp # leave space for volatiles
Expand Down
11 changes: 8 additions & 3 deletions arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
struct list_head *list)
{
int ret;
struct resource_entry *entry;
struct resource_entry *entry, *tmp;

sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
info->bridge = device;
Expand All @@ -345,8 +345,13 @@ static void probe_pci_root_info(struct pci_root_info *info,
dev_dbg(&device->dev,
"no IO and memory resources present in _CRS\n");
else
resource_list_for_each_entry(entry, list)
entry->res->name = info->name;
resource_list_for_each_entry_safe(entry, tmp, list) {
if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
(entry->res->flags & IORESOURCE_DISABLED))
resource_list_destroy_entry(entry);
else
entry->res->name = info->name;
}
}

struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
Expand Down
4 changes: 3 additions & 1 deletion drivers/acpi/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
* CHECKME: len might be required to check versus a minimum
* length as well. 1 for io is fine, but for memory it does
* not make any sense at all.
* Note: some BIOSes report incorrect length for ACPI address space
* descriptor, so remove check of 'reslen == len' to avoid regression.
*/
if (len && reslen && reslen == len && start <= end)
if (len && reslen && start <= end)
return true;

pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
Expand Down
20 changes: 16 additions & 4 deletions drivers/acpi/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -2110,7 +2110,8 @@ static int __init intel_opregion_present(void)

int acpi_video_register(void)
{
int result = 0;
int ret;

if (register_count) {
/*
* if the function of acpi_video_register is already called,
Expand All @@ -2122,9 +2123,9 @@ int acpi_video_register(void)
mutex_init(&video_list_lock);
INIT_LIST_HEAD(&video_bus_head);

result = acpi_bus_register_driver(&acpi_video_bus);
if (result < 0)
return -ENODEV;
ret = acpi_bus_register_driver(&acpi_video_bus);
if (ret)
return ret;

/*
* When the acpi_video_bus is loaded successfully, increase
Expand Down Expand Up @@ -2176,6 +2177,17 @@ EXPORT_SYMBOL(acpi_video_unregister_backlight);

static int __init acpi_video_init(void)
{
/*
* Let the module load even if ACPI is disabled (e.g. due to
* a broken BIOS) so that i915.ko can still be loaded on such
* old systems without an AcpiOpRegion.
*
* acpi_video_register() will report -ENODEV later as well due
* to acpi_disabled when i915.ko tries to register itself afterwards.
*/
if (acpi_disabled)
return 0;

dmi_check_system(video_dmi_table);

if (intel_opregion_present())
Expand Down
24 changes: 12 additions & 12 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,7 @@ static void rtpm_status_str(struct seq_file *s, struct device *dev)
}

static int pm_genpd_summary_one(struct seq_file *s,
struct generic_pm_domain *gpd)
struct generic_pm_domain *genpd)
{
static const char * const status_lookup[] = {
[GPD_STATE_ACTIVE] = "on",
Expand All @@ -2256,26 +2256,26 @@ static int pm_genpd_summary_one(struct seq_file *s,
struct gpd_link *link;
int ret;

ret = mutex_lock_interruptible(&gpd->lock);
ret = mutex_lock_interruptible(&genpd->lock);
if (ret)
return -ERESTARTSYS;

if (WARN_ON(gpd->status >= ARRAY_SIZE(status_lookup)))
if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup)))
goto exit;
seq_printf(s, "%-30s %-15s ", gpd->name, status_lookup[gpd->status]);
seq_printf(s, "%-30s %-15s ", genpd->name, status_lookup[genpd->status]);

/*
* Modifications on the list require holding locks on both
* master and slave, so we are safe.
* Also gpd->name is immutable.
* Also genpd->name is immutable.
*/
list_for_each_entry(link, &gpd->master_links, master_node) {
list_for_each_entry(link, &genpd->master_links, master_node) {
seq_printf(s, "%s", link->slave->name);
if (!list_is_last(&link->master_node, &gpd->master_links))
if (!list_is_last(&link->master_node, &genpd->master_links))
seq_puts(s, ", ");
}

list_for_each_entry(pm_data, &gpd->dev_list, list_node) {
list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL);
if (kobj_path == NULL)
continue;
Expand All @@ -2287,14 +2287,14 @@ static int pm_genpd_summary_one(struct seq_file *s,

seq_puts(s, "\n");
exit:
mutex_unlock(&gpd->lock);
mutex_unlock(&genpd->lock);

return 0;
}

static int pm_genpd_summary_show(struct seq_file *s, void *data)
{
struct generic_pm_domain *gpd;
struct generic_pm_domain *genpd;
int ret = 0;

seq_puts(s, " domain status slaves\n");
Expand All @@ -2305,8 +2305,8 @@ static int pm_genpd_summary_show(struct seq_file *s, void *data)
if (ret)
return -ERESTARTSYS;

list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
ret = pm_genpd_summary_one(s, gpd);
list_for_each_entry(genpd, &gpd_list, gpd_list_node) {
ret = pm_genpd_summary_one(s, genpd);
if (ret)
break;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/base/power/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,7 @@ void pm_system_wakeup(void)
pm_abort_suspend = true;
freeze_wake();
}
EXPORT_SYMBOL_GPL(pm_system_wakeup);

void pm_wakeup_clear(void)
{
Expand Down
20 changes: 19 additions & 1 deletion drivers/clk/at91/pmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,29 @@ static int pmc_irq_set_type(struct irq_data *d, unsigned type)
return 0;
}

static void pmc_irq_suspend(struct irq_data *d)
{
struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);

pmc->imr = pmc_read(pmc, AT91_PMC_IMR);
pmc_write(pmc, AT91_PMC_IDR, pmc->imr);
}

static void pmc_irq_resume(struct irq_data *d)
{
struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);

pmc_write(pmc, AT91_PMC_IER, pmc->imr);
}

static struct irq_chip pmc_irq = {
.name = "PMC",
.irq_disable = pmc_irq_mask,
.irq_mask = pmc_irq_mask,
.irq_unmask = pmc_irq_unmask,
.irq_set_type = pmc_irq_set_type,
.irq_suspend = pmc_irq_suspend,
.irq_resume = pmc_irq_resume,
};

static struct lock_class_key pmc_lock_class;
Expand Down Expand Up @@ -224,7 +241,8 @@ static struct at91_pmc *__init at91_pmc_init(struct device_node *np,
goto out_free_pmc;

pmc_write(pmc, AT91_PMC_IDR, 0xffffffff);
if (request_irq(pmc->virq, pmc_irq_handler, IRQF_SHARED, "pmc", pmc))
if (request_irq(pmc->virq, pmc_irq_handler,
IRQF_SHARED | IRQF_COND_SUSPEND, "pmc", pmc))
goto out_remove_irqdomain;

return pmc;
Expand Down
1 change: 1 addition & 0 deletions drivers/clk/at91/pmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct at91_pmc {
spinlock_t lock;
const struct at91_pmc_caps *caps;
struct irq_domain *irqdomain;
u32 imr;
};

static inline void pmc_lock(struct at91_pmc *pmc)
Expand Down
21 changes: 6 additions & 15 deletions drivers/cpufreq/exynos-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ static struct cpufreq_driver exynos_driver = {

static int exynos_cpufreq_probe(struct platform_device *pdev)
{
struct device_node *cpus, *np;
struct device_node *cpu0;
int ret = -EINVAL;

exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
Expand Down Expand Up @@ -206,28 +206,19 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
if (ret)
goto err_cpufreq_reg;

cpus = of_find_node_by_path("/cpus");
if (!cpus) {
pr_err("failed to find cpus node\n");
cpu0 = of_get_cpu_node(0, NULL);
if (!cpu0) {
pr_err("failed to find cpu0 node\n");
return 0;
}

np = of_get_next_child(cpus, NULL);
if (!np) {
pr_err("failed to find cpus child node\n");
of_node_put(cpus);
return 0;
}

if (of_find_property(np, "#cooling-cells", NULL)) {
cdev = of_cpufreq_cooling_register(np,
if (of_find_property(cpu0, "#cooling-cells", NULL)) {
cdev = of_cpufreq_cooling_register(cpu0,
cpu_present_mask);
if (IS_ERR(cdev))
pr_err("running cpufreq without cooling device: %ld\n",
PTR_ERR(cdev));
}
of_node_put(np);
of_node_put(cpus);

return 0;

Expand Down
Loading

0 comments on commit 022b0d1

Please sign in to comment.