Skip to content

Commit

Permalink
Merge branches 'acpi-ec', 'acpi-dma', 'acpi-processor' and 'acpi-cppc'
Browse files Browse the repository at this point in the history
* acpi-ec:
  ACPI / EC: Clean up EC GPE mask flag
  ACPI: EC: Fix possible issues related to EC initialization order

* acpi-dma:
  ACPI/IORT: Add IORT named component memory address limits
  ACPI: Make acpi_dma_configure() DMA regions aware
  ACPI: Introduce DMA ranges parsing
  ACPI: Make acpi_dev_get_resources() method agnostic

* acpi-processor:
  ACPI / processor: make function acpi_processor_check_duplicates() static
  ACPI: processor: use dev_dbg() instead of dev_warn() when CPPC probe failed

* acpi-cppc:
  mailbox: pcc: Drop uninformative output during boot
  • Loading branch information
Rafael J. Wysocki committed Sep 3, 2017
5 parents 4467ade + 56f77ee + 10d8ab2 + 0ed780e + 66ed4ca commit f928a49
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 57 deletions.
2 changes: 1 addition & 1 deletion drivers/acpi/acpi_processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ static acpi_status __init acpi_processor_ids_walk(acpi_handle handle,

}

void __init acpi_processor_check_duplicates(void)
static void __init acpi_processor_check_duplicates(void)
{
/* check the correctness for all processors in ACPI namespace */
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
Expand Down
57 changes: 55 additions & 2 deletions drivers/acpi/arm64/iort.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,13 +680,36 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
return ret ? NULL : ops;
}

static int nc_dma_get_range(struct device *dev, u64 *size)
{
struct acpi_iort_node *node;
struct acpi_iort_named_component *ncomp;

node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
iort_match_node_callback, dev);
if (!node)
return -ENODEV;

ncomp = (struct acpi_iort_named_component *)node->node_data;

*size = ncomp->memory_address_limit >= 64 ? U64_MAX :
1ULL<<ncomp->memory_address_limit;

return 0;
}

/**
* iort_set_dma_mask - Set-up dma mask for a device.
* iort_dma_setup() - Set-up device DMA parameters.
*
* @dev: device to configure
* @dma_addr: device DMA address result pointer
* @size: DMA range size result pointer
*/
void iort_set_dma_mask(struct device *dev)
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
{
u64 mask, dmaaddr = 0, size = 0, offset = 0;
int ret, msb;

/*
* Set default coherent_dma_mask to 32 bit. Drivers are expected to
* setup the correct supported mask.
Expand All @@ -700,6 +723,36 @@ void iort_set_dma_mask(struct device *dev)
*/
if (!dev->dma_mask)
dev->dma_mask = &dev->coherent_dma_mask;

size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);

if (dev_is_pci(dev))
ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
else
ret = nc_dma_get_range(dev, &size);

if (!ret) {
msb = fls64(dmaaddr + size - 1);
/*
* Round-up to the power-of-two mask or set
* the mask to the whole 64-bit address space
* in case the DMA region covers the full
* memory window.
*/
mask = msb == 64 ? U64_MAX : (1ULL << msb) - 1;
/*
* Limit coherent and dma mask based on size
* retrieved from firmware.
*/
dev->coherent_dma_mask = mask;
*dev->dma_mask = mask;
}

*dma_addr = dmaaddr;
*dma_size = size;

dev->dma_pfn_offset = PFN_DOWN(offset);
dev_dbg(dev, "dma_pfn_offset(%#08llx)\n", offset);
}

/**
Expand Down
48 changes: 27 additions & 21 deletions drivers/acpi/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ enum {
EC_FLAGS_EVT_HANDLER_INSTALLED, /* _Qxx handlers installed */
EC_FLAGS_STARTED, /* Driver is started */
EC_FLAGS_STOPPED, /* Driver is stopped */
EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the
* current command processing */
EC_FLAGS_GPE_MASKED, /* GPE masked */
};

#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */
Expand Down Expand Up @@ -425,19 +424,19 @@ static void acpi_ec_complete_request(struct acpi_ec *ec)
wake_up(&ec->wait);
}

static void acpi_ec_set_storm(struct acpi_ec *ec, u8 flag)
static void acpi_ec_mask_gpe(struct acpi_ec *ec)
{
if (!test_bit(flag, &ec->flags)) {
if (!test_bit(EC_FLAGS_GPE_MASKED, &ec->flags)) {
acpi_ec_disable_gpe(ec, false);
ec_dbg_drv("Polling enabled");
set_bit(flag, &ec->flags);
set_bit(EC_FLAGS_GPE_MASKED, &ec->flags);
}
}

static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag)
static void acpi_ec_unmask_gpe(struct acpi_ec *ec)
{
if (test_bit(flag, &ec->flags)) {
clear_bit(flag, &ec->flags);
if (test_bit(EC_FLAGS_GPE_MASKED, &ec->flags)) {
clear_bit(EC_FLAGS_GPE_MASKED, &ec->flags);
acpi_ec_enable_gpe(ec, false);
ec_dbg_drv("Polling disabled");
}
Expand All @@ -464,7 +463,7 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)

static void acpi_ec_submit_query(struct acpi_ec *ec)
{
acpi_ec_set_storm(ec, EC_FLAGS_COMMAND_STORM);
acpi_ec_mask_gpe(ec);
if (!acpi_ec_event_enabled(ec))
return;
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
Expand All @@ -480,7 +479,7 @@ static void acpi_ec_complete_query(struct acpi_ec *ec)
if (test_and_clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
ec_dbg_evt("Command(%s) unblocked",
acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM);
acpi_ec_unmask_gpe(ec);
}

static inline void __acpi_ec_enable_event(struct acpi_ec *ec)
Expand Down Expand Up @@ -700,7 +699,7 @@ static void advance_transaction(struct acpi_ec *ec)
++t->irq_count;
/* Allow triggering on 0 threshold */
if (t->irq_count == ec_storm_threshold)
acpi_ec_set_storm(ec, EC_FLAGS_COMMAND_STORM);
acpi_ec_mask_gpe(ec);
}
}
out:
Expand Down Expand Up @@ -798,7 +797,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,

spin_lock_irqsave(&ec->lock, tmp);
if (t->irq_count == ec_storm_threshold)
acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM);
acpi_ec_unmask_gpe(ec);
ec_dbg_req("Command(%s) stopped", acpi_ec_cmd_string(t->command));
ec->curr = NULL;
/* Disable GPE for command processing (IBF=0/OBF=1) */
Expand Down Expand Up @@ -1586,9 +1585,7 @@ static bool acpi_is_boot_ec(struct acpi_ec *ec)
{
if (!boot_ec)
return false;
if (ec->handle == boot_ec->handle &&
ec->gpe == boot_ec->gpe &&
ec->command_addr == boot_ec->command_addr &&
if (ec->command_addr == boot_ec->command_addr &&
ec->data_addr == boot_ec->data_addr)
return true;
return false;
Expand All @@ -1613,6 +1610,13 @@ static int acpi_ec_add(struct acpi_device *device)

if (acpi_is_boot_ec(ec)) {
boot_ec_is_ecdt = false;
/*
* Trust PNP0C09 namespace location rather than ECDT ID.
*
* But trust ECDT GPE rather than _GPE because of ASUS quirks,
* so do not change boot_ec->gpe to ec->gpe.
*/
boot_ec->handle = ec->handle;
acpi_handle_debug(ec->handle, "duplicated.\n");
acpi_ec_free(ec);
ec = boot_ec;
Expand Down Expand Up @@ -1747,18 +1751,20 @@ static int __init acpi_ec_ecdt_start(void)

if (!boot_ec)
return -ENODEV;
/*
* The DSDT EC should have already been started in
* acpi_ec_add().
*/
/* In case acpi_ec_ecdt_start() is called after acpi_ec_add() */
if (!boot_ec_is_ecdt)
return -ENODEV;

/*
* At this point, the namespace and the GPE is initialized, so
* start to find the namespace objects and handle the events.
*
* Note: ec->handle can be valid if this function is called after
* acpi_ec_add(), hence the fast path.
*/
if (!acpi_ec_ecdt_get_handle(&handle))
if (boot_ec->handle != ACPI_ROOT_OBJECT)
handle = boot_ec->handle;
else if (!acpi_ec_ecdt_get_handle(&handle))
return -ENODEV;
return acpi_config_boot_ec(boot_ec, handle, true, true);
}
Expand Down Expand Up @@ -2011,8 +2017,8 @@ int __init acpi_ec_init(void)
return result;

/* Drivers must be started after acpi_ec_query_init() */
ecdt_fail = acpi_ec_ecdt_start();
dsdt_fail = acpi_bus_register_driver(&acpi_ec_driver);
ecdt_fail = acpi_ec_ecdt_start();
return ecdt_fail && dsdt_fail ? -ENODEV : 0;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/processor_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ static int __acpi_processor_start(struct acpi_device *device)

result = acpi_cppc_processor_probe(pr);
if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
dev_warn(&device->dev, "CPPC data invalid or not present\n");
dev_dbg(&device->dev, "CPPC data invalid or not present\n");

if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
acpi_processor_power_init(pr);
Expand Down
82 changes: 63 additions & 19 deletions drivers/acpi/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,35 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
return AE_OK;
}

static int __acpi_dev_get_resources(struct acpi_device *adev,
struct list_head *list,
int (*preproc)(struct acpi_resource *, void *),
void *preproc_data, char *method)
{
struct res_proc_context c;
acpi_status status;

if (!adev || !adev->handle || !list_empty(list))
return -EINVAL;

if (!acpi_has_method(adev->handle, method))
return 0;

c.list = list;
c.preproc = preproc;
c.preproc_data = preproc_data;
c.count = 0;
c.error = 0;
status = acpi_walk_resources(adev->handle, method,
acpi_dev_process_resource, &c);
if (ACPI_FAILURE(status)) {
acpi_dev_free_resource_list(list);
return c.error ? c.error : -EIO;
}

return c.count;
}

/**
* acpi_dev_get_resources - Get current resources of a device.
* @adev: ACPI device node to get the resources for.
Expand Down Expand Up @@ -601,30 +630,45 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
int (*preproc)(struct acpi_resource *, void *),
void *preproc_data)
{
struct res_proc_context c;
acpi_status status;
return __acpi_dev_get_resources(adev, list, preproc, preproc_data,
METHOD_NAME__CRS);
}
EXPORT_SYMBOL_GPL(acpi_dev_get_resources);

if (!adev || !adev->handle || !list_empty(list))
return -EINVAL;
static int is_memory(struct acpi_resource *ares, void *not_used)
{
struct resource_win win;
struct resource *res = &win.res;

if (!acpi_has_method(adev->handle, METHOD_NAME__CRS))
return 0;
memset(&win, 0, sizeof(win));

c.list = list;
c.preproc = preproc;
c.preproc_data = preproc_data;
c.count = 0;
c.error = 0;
status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
acpi_dev_process_resource, &c);
if (ACPI_FAILURE(status)) {
acpi_dev_free_resource_list(list);
return c.error ? c.error : -EIO;
}
return !(acpi_dev_resource_memory(ares, res)
|| acpi_dev_resource_address_space(ares, &win)
|| acpi_dev_resource_ext_address_space(ares, &win));
}

return c.count;
/**
* acpi_dev_get_dma_resources - Get current DMA resources of a device.
* @adev: ACPI device node to get the resources for.
* @list: Head of the resultant list of resources (must be empty).
*
* Evaluate the _DMA method for the given device node and process its
* output.
*
* The resultant struct resource objects are put on the list pointed to
* by @list, that must be empty initially, as members of struct
* resource_entry objects. Callers of this routine should use
* %acpi_dev_free_resource_list() to free that list.
*
* The number of resources in the output list is returned on success,
* an error code reflecting the error condition is returned otherwise.
*/
int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)
{
return __acpi_dev_get_resources(adev, list, is_memory, NULL,
METHOD_NAME__DMA);
}
EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);

/**
* acpi_dev_filter_resource_type - Filter ACPI resource according to resource
Expand Down
Loading

0 comments on commit f928a49

Please sign in to comment.