summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpi_lpss.c21
-rw-r--r--drivers/acpi/acpica/utdebug.c4
-rw-r--r--drivers/acpi/ec.c129
-rw-r--r--drivers/acpi/event.c7
-rw-r--r--drivers/acpi/processor_idle.c48
-rw-r--r--drivers/acpi/resource.c2
-rw-r--r--drivers/acpi/video.c9
7 files changed, 91 insertions, 129 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 02e835f3cf8a..657964e8ab7e 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -105,7 +105,7 @@ static void lpss_uart_setup(struct lpss_private_data *pdata)
}
}
-static void byt_i2c_setup(struct lpss_private_data *pdata)
+static void lpss_deassert_reset(struct lpss_private_data *pdata)
{
unsigned int offset;
u32 val;
@@ -114,9 +114,18 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
val = readl(pdata->mmio_base + offset);
val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
writel(val, pdata->mmio_base + offset);
+}
+
+#define LPSS_I2C_ENABLE 0x6c
+
+static void byt_i2c_setup(struct lpss_private_data *pdata)
+{
+ lpss_deassert_reset(pdata);
if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset))
pdata->fixed_clk_rate = 133000000;
+
+ writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
}
static struct lpss_device_desc lpt_dev_desc = {
@@ -125,7 +134,7 @@ static struct lpss_device_desc lpt_dev_desc = {
};
static struct lpss_device_desc lpt_i2c_dev_desc = {
- .flags = LPSS_CLK | LPSS_LTR,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
.prv_offset = 0x800,
};
@@ -166,6 +175,12 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
.setup = byt_i2c_setup,
};
+static struct lpss_device_desc bsw_spi_dev_desc = {
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
+ .prv_offset = 0x400,
+ .setup = lpss_deassert_reset,
+};
+
#else
#define LPSS_ADDR(desc) (0UL)
@@ -198,7 +213,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
/* Braswell LPSS devices */
{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
- { "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
+ { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index 57078e3ea9b7..4f3f888d33bb 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -111,8 +111,8 @@ void acpi_ut_track_stack_ptr(void)
* RETURN: Updated pointer to the function name
*
* DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
- * This allows compiler macros such as __FUNCTION__ to be used
- * with no change to the debug output.
+ * This allows compiler macros such as __func__ to be used with no
+ * change to the debug output.
*
******************************************************************************/
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 14d0c89ada2a..a8dd2f763382 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -31,7 +31,6 @@
/* Uncomment next line to get verbose printout */
/* #define DEBUG */
-#define DEBUG_REF 0
#define pr_fmt(fmt) "ACPI : EC: " fmt
#include <linux/kernel.h>
@@ -77,9 +76,7 @@ enum ec_command {
* when trying to clear the EC */
enum {
- EC_FLAGS_EVENT_ENABLED, /* Event is enabled */
- EC_FLAGS_EVENT_PENDING, /* Event is pending */
- EC_FLAGS_EVENT_DETECTED, /* Event is detected */
+ EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
* OpReg are installed */
EC_FLAGS_STARTED, /* Driver is started */
@@ -91,13 +88,6 @@ enum {
#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */
#define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */
-#define ec_debug_ref(ec, fmt, ...) \
- do { \
- if (DEBUG_REF) \
- pr_debug("%lu: " fmt, ec->reference_count, \
- ## __VA_ARGS__); \
- } while (0)
-
/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
@@ -161,12 +151,6 @@ static bool acpi_ec_flushed(struct acpi_ec *ec)
return ec->reference_count == 1;
}
-static bool acpi_ec_has_pending_event(struct acpi_ec *ec)
-{
- return test_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags) ||
- test_bit(EC_FLAGS_EVENT_PENDING, &ec->flags);
-}
-
/* --------------------------------------------------------------------------
* EC Registers
* -------------------------------------------------------------------------- */
@@ -334,97 +318,34 @@ static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag)
* the flush operation is not in
* progress
* @ec: the EC device
- * @allow_event: whether event should be handled
*
* This function must be used before taking a new action that should hold
* the reference count. If this function returns false, then the action
* must be discarded or it will prevent the flush operation from being
* completed.
- *
- * During flushing, QR_EC command need to pass this check when there is a
- * pending event, so that the reference count held for the pending event
- * can be decreased by the completion of the QR_EC command.
*/
-static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec,
- bool allow_event)
+static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)
{
- if (!acpi_ec_started(ec)) {
- if (!allow_event || !acpi_ec_has_pending_event(ec))
- return false;
- }
+ if (!acpi_ec_started(ec))
+ return false;
acpi_ec_submit_request(ec);
return true;
}
-static void acpi_ec_submit_event(struct acpi_ec *ec)
+static void acpi_ec_submit_query(struct acpi_ec *ec)
{
- if (!test_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags) ||
- !test_bit(EC_FLAGS_EVENT_ENABLED, &ec->flags))
- return;
- /* Hold reference for pending event */
- if (!acpi_ec_submit_flushable_request(ec, true))
- return;
- ec_debug_ref(ec, "Increase event\n");
- if (!test_and_set_bit(EC_FLAGS_EVENT_PENDING, &ec->flags)) {
- pr_debug("***** Event query started *****\n");
+ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
+ pr_debug("***** Event started *****\n");
schedule_work(&ec->work);
- return;
}
- acpi_ec_complete_request(ec);
- ec_debug_ref(ec, "Decrease event\n");
}
-static void acpi_ec_complete_event(struct acpi_ec *ec)
+static void acpi_ec_complete_query(struct acpi_ec *ec)
{
if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
- clear_bit(EC_FLAGS_EVENT_PENDING, &ec->flags);
- pr_debug("***** Event query stopped *****\n");
- /* Unhold reference for pending event */
- acpi_ec_complete_request(ec);
- ec_debug_ref(ec, "Decrease event\n");
- /* Check if there is another SCI_EVT detected */
- acpi_ec_submit_event(ec);
- }
-}
-
-static void acpi_ec_submit_detection(struct acpi_ec *ec)
-{
- /* Hold reference for query submission */
- if (!acpi_ec_submit_flushable_request(ec, false))
- return;
- ec_debug_ref(ec, "Increase query\n");
- if (!test_and_set_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags)) {
- pr_debug("***** Event detection blocked *****\n");
- acpi_ec_submit_event(ec);
- return;
+ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+ pr_debug("***** Event stopped *****\n");
}
- acpi_ec_complete_request(ec);
- ec_debug_ref(ec, "Decrease query\n");
-}
-
-static void acpi_ec_complete_detection(struct acpi_ec *ec)
-{
- if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
- clear_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags);
- pr_debug("***** Event detetion unblocked *****\n");
- /* Unhold reference for query submission */
- acpi_ec_complete_request(ec);
- ec_debug_ref(ec, "Decrease query\n");
- }
-}
-
-static void acpi_ec_enable_event(struct acpi_ec *ec)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ec->lock, flags);
- set_bit(EC_FLAGS_EVENT_ENABLED, &ec->flags);
- /*
- * An event may be pending even with SCI_EVT=0, so QR_EC should
- * always be issued right after started.
- */
- acpi_ec_submit_detection(ec);
- spin_unlock_irqrestore(&ec->lock, flags);
}
static int ec_transaction_completed(struct acpi_ec *ec)
@@ -468,7 +389,6 @@ static void advance_transaction(struct acpi_ec *ec)
t->rdata[t->ri++] = acpi_ec_read_data(ec);
if (t->rlen == t->ri) {
t->flags |= ACPI_EC_COMMAND_COMPLETE;
- acpi_ec_complete_event(ec);
if (t->command == ACPI_EC_COMMAND_QUERY)
pr_debug("***** Command(%s) hardware completion *****\n",
acpi_ec_cmd_string(t->command));
@@ -479,7 +399,6 @@ static void advance_transaction(struct acpi_ec *ec)
} else if (t->wlen == t->wi &&
(status & ACPI_EC_FLAG_IBF) == 0) {
t->flags |= ACPI_EC_COMMAND_COMPLETE;
- acpi_ec_complete_event(ec);
wakeup = true;
}
goto out;
@@ -488,17 +407,16 @@ static void advance_transaction(struct acpi_ec *ec)
!(status & ACPI_EC_FLAG_SCI) &&
(t->command == ACPI_EC_COMMAND_QUERY)) {
t->flags |= ACPI_EC_COMMAND_POLL;
- acpi_ec_complete_detection(ec);
+ acpi_ec_complete_query(ec);
t->rdata[t->ri++] = 0x00;
t->flags |= ACPI_EC_COMMAND_COMPLETE;
- acpi_ec_complete_event(ec);
pr_debug("***** Command(%s) software completion *****\n",
acpi_ec_cmd_string(t->command));
wakeup = true;
} else if ((status & ACPI_EC_FLAG_IBF) == 0) {
acpi_ec_write_cmd(ec, t->command);
t->flags |= ACPI_EC_COMMAND_POLL;
- acpi_ec_complete_detection(ec);
+ acpi_ec_complete_query(ec);
} else
goto err;
goto out;
@@ -519,7 +437,7 @@ err:
}
out:
if (status & ACPI_EC_FLAG_SCI)
- acpi_ec_submit_detection(ec);
+ acpi_ec_submit_query(ec);
if (wakeup && in_interrupt())
wake_up(&ec->wait);
}
@@ -580,11 +498,10 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
/* start transaction */
spin_lock_irqsave(&ec->lock, tmp);
/* Enable GPE for command processing (IBF=0/OBF=1) */
- if (!acpi_ec_submit_flushable_request(ec, true)) {
+ if (!acpi_ec_submit_flushable_request(ec)) {
ret = -EINVAL;
goto unlock;
}
- ec_debug_ref(ec, "Increase command\n");
/* following two actions should be kept atomic */
ec->curr = t;
pr_debug("***** Command(%s) started *****\n",
@@ -600,7 +517,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
ec->curr = NULL;
/* Disable GPE for command processing (IBF=0/OBF=1) */
acpi_ec_complete_request(ec);
- ec_debug_ref(ec, "Decrease command\n");
unlock:
spin_unlock_irqrestore(&ec->lock, tmp);
return ret;
@@ -762,11 +678,9 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) {
pr_debug("+++++ Starting EC +++++\n");
/* Enable GPE for event processing (SCI_EVT=1) */
- if (!resuming) {
+ if (!resuming)
acpi_ec_submit_request(ec);
- ec_debug_ref(ec, "Increase driver\n");
- }
- pr_info("+++++ EC started +++++\n");
+ pr_debug("EC started\n");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -794,13 +708,11 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
wait_event(ec->wait, acpi_ec_stopped(ec));
spin_lock_irqsave(&ec->lock, flags);
/* Disable GPE for event processing (SCI_EVT=1) */
- if (!suspending) {
+ if (!suspending)
acpi_ec_complete_request(ec);
- ec_debug_ref(ec, "Decrease driver\n");
- }
clear_bit(EC_FLAGS_STARTED, &ec->flags);
clear_bit(EC_FLAGS_STOPPED, &ec->flags);
- pr_info("+++++ EC stopped +++++\n");
+ pr_debug("EC stopped\n");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -967,9 +879,7 @@ static void acpi_ec_gpe_poller(struct work_struct *work)
{
struct acpi_ec *ec = container_of(work, struct acpi_ec, work);
- pr_debug("***** Event poller started *****\n");
acpi_ec_query(ec, NULL);
- pr_debug("***** Event poller stopped *****\n");
}
static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
@@ -1039,6 +949,7 @@ static struct acpi_ec *make_acpi_ec(void)
if (!ec)
return NULL;
+ ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
mutex_init(&ec->mutex);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
@@ -1189,7 +1100,7 @@ static int acpi_ec_add(struct acpi_device *device)
ret = ec_install_handlers(ec);
/* EC is fully operational, allow queries */
- acpi_ec_enable_event(ec);
+ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
/* Clear stale _Q events if hardware might require that */
if (EC_FLAGS_CLEAR_ON_RESUME)
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index ef2d730734dc..e24ea4e796e4 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -100,7 +100,6 @@ int acpi_bus_generate_netlink_event(const char *device_class,
struct acpi_genl_event *event;
void *msg_header;
int size;
- int result;
/* allocate memory */
size = nla_total_size(sizeof(struct acpi_genl_event)) +
@@ -137,11 +136,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
event->data = data;
/* send multicast genetlink message */
- result = genlmsg_end(skb, msg_header);
- if (result < 0) {
- nlmsg_free(skb);
- return result;
- }
+ genlmsg_end(skb, msg_header);
genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
return 0;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index c256bd7fbd78..c6bb9f1257c9 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -732,9 +732,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
static bool acpi_idle_fallback_to_c1(struct acpi_processor *pr)
{
- return IS_ENABLED(CONFIG_HOTPLUG_CPU) && num_online_cpus() > 1 &&
- !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED) &&
- !pr->flags.has_cst;
+ return IS_ENABLED(CONFIG_HOTPLUG_CPU) && !pr->flags.has_cst &&
+ !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED);
}
static int c3_cpu_count;
@@ -744,9 +743,10 @@ static DEFINE_RAW_SPINLOCK(c3_lock);
* acpi_idle_enter_bm - enters C3 with proper BM handling
* @pr: Target processor
* @cx: Target state context
+ * @timer_bc: Whether or not to change timer mode to broadcast
*/
static void acpi_idle_enter_bm(struct acpi_processor *pr,
- struct acpi_processor_cx *cx)
+ struct acpi_processor_cx *cx, bool timer_bc)
{
acpi_unlazy_tlb(smp_processor_id());
@@ -754,7 +754,8 @@ static void acpi_idle_enter_bm(struct acpi_processor *pr,
* Must be done before busmaster disable as we might need to
* access HPET !
*/
- lapic_timer_state_broadcast(pr, cx, 1);
+ if (timer_bc)
+ lapic_timer_state_broadcast(pr, cx, 1);
/*
* disable bus master
@@ -784,7 +785,8 @@ static void acpi_idle_enter_bm(struct acpi_processor *pr,
raw_spin_unlock(&c3_lock);
}
- lapic_timer_state_broadcast(pr, cx, 0);
+ if (timer_bc)
+ lapic_timer_state_broadcast(pr, cx, 0);
}
static int acpi_idle_enter(struct cpuidle_device *dev,
@@ -798,12 +800,12 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
return -EINVAL;
if (cx->type != ACPI_STATE_C1) {
- if (acpi_idle_fallback_to_c1(pr)) {
+ if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) {
index = CPUIDLE_DRIVER_STATE_START;
cx = per_cpu(acpi_cstate[index], dev->cpu);
} else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) {
if (cx->bm_sts_skip || !acpi_idle_bm_check()) {
- acpi_idle_enter_bm(pr, cx);
+ acpi_idle_enter_bm(pr, cx, true);
return index;
} else if (drv->safe_state_index >= 0) {
index = drv->safe_state_index;
@@ -827,6 +829,27 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
return index;
}
+static void acpi_idle_enter_freeze(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
+
+ if (cx->type == ACPI_STATE_C3) {
+ struct acpi_processor *pr = __this_cpu_read(processors);
+
+ if (unlikely(!pr))
+ return;
+
+ if (pr->flags.bm_check) {
+ acpi_idle_enter_bm(pr, cx, false);
+ return;
+ } else {
+ ACPI_FLUSH_CPU_CACHE();
+ }
+ }
+ acpi_idle_do_entry(cx);
+}
+
struct cpuidle_driver acpi_idle_driver = {
.name = "acpi_idle",
.owner = THIS_MODULE,
@@ -925,6 +948,15 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
state->enter_dead = acpi_idle_play_dead;
drv->safe_state_index = count;
}
+ /*
+ * Halt-induced C1 is not good for ->enter_freeze, because it
+ * re-enables interrupts on exit. Moreover, C1 is generally not
+ * particularly interesting from the suspend-to-idle angle, so
+ * avoid C1 and the situations in which we may need to fall back
+ * to it altogether.
+ */
+ if (cx->type != ACPI_STATE_C1 && !acpi_idle_fallback_to_c1(pr))
+ state->enter_freeze = acpi_idle_enter_freeze;
count++;
if (count == CPUIDLE_STATE_MAX)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 4752b9939987..c723668e3e27 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -46,7 +46,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
if (len && reslen && reslen == len && start <= end)
return true;
- pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
+ pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
io ? "io" : "mem", start, end, len);
return false;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 88a4f99dd2a7..debd30917010 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -540,6 +540,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
},
},
+ {
+ /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
+ .callback = video_disable_native_backlight,
+ .ident = "SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "900X3C/900X3D/900X3E/900X4C/900X4D"),
+ },
+ },
{
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
OpenPOWER on IntegriCloud