Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 30718
b: refs/heads/master
c: 9ac0239
h: refs/heads/master
v: v3
  • Loading branch information
KAMEZAWA Hiroyuki authored and Linus Torvalds committed Jun 28, 2006
1 parent f3275d7 commit 3baee88
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5c31f2738ab124ebc1f8948a5fc17dd7a08ed1ec
refs/heads/master: 9ac023989e6dd1b97140b47fb942a7940d0b2af2
112 changes: 77 additions & 35 deletions trunk/drivers/acpi/acpi_memhotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,45 +68,75 @@ static struct acpi_driver acpi_memory_device_driver = {
},
};

struct acpi_memory_info {
struct list_head list;
u64 start_addr; /* Memory Range start physical addr */
u64 length; /* Memory Range length */
unsigned short caching; /* memory cache attribute */
unsigned short write_protect; /* memory read/write attribute */
unsigned int enabled:1;
};

struct acpi_memory_device {
acpi_handle handle;
unsigned int state; /* State of the memory device */
unsigned short caching; /* memory cache attribute */
unsigned short write_protect; /* memory read/write attribute */
u64 start_addr; /* Memory Range start physical addr */
u64 length; /* Memory Range length */
struct list_head res_list;
};

static acpi_status
acpi_memory_get_resource(struct acpi_resource *resource, void *context)
{
struct acpi_memory_device *mem_device = context;
struct acpi_resource_address64 address64;
struct acpi_memory_info *info, *new;
acpi_status status;

status = acpi_resource_to_address64(resource, &address64);
if (ACPI_FAILURE(status) ||
(address64.resource_type != ACPI_MEMORY_RANGE))
return AE_OK;

list_for_each_entry(info, &mem_device->res_list, list) {
/* Can we combine the resource range information? */
if ((info->caching == address64.info.mem.caching) &&
(info->write_protect == address64.info.mem.write_protect) &&
(info->start_addr + info->length == address64.minimum)) {
info->length += address64.address_length;
return AE_OK;
}
}

new = kzalloc(sizeof(struct acpi_memory_info), GFP_KERNEL);
if (!new)
return AE_ERROR;

INIT_LIST_HEAD(&new->list);
new->caching = address64.info.mem.caching;
new->write_protect = address64.info.mem.write_protect;
new->start_addr = address64.minimum;
new->length = address64.address_length;
list_add_tail(&new->list, &mem_device->res_list);

return AE_OK;
}

static int
acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_resource *resource = NULL;
struct acpi_resource_address64 address64;
struct acpi_memory_info *info, *n;

ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources");

/* Get the range from the _CRS */
status = acpi_get_current_resources(mem_device->handle, &buffer);
if (ACPI_FAILURE(status))
return_VALUE(-EINVAL);

resource = (struct acpi_resource *)buffer.pointer;
status = acpi_resource_to_address64(resource, &address64);
if (ACPI_SUCCESS(status)) {
if (address64.resource_type == ACPI_MEMORY_RANGE) {
/* Populate the structure */
mem_device->caching = address64.info.mem.caching;
mem_device->write_protect =
address64.info.mem.write_protect;
mem_device->start_addr = address64.minimum;
mem_device->length = address64.address_length;
}
status = acpi_walk_resources(mem_device->handle, METHOD_NAME__CRS,
acpi_memory_get_resource, mem_device);
if (ACPI_FAILURE(status)) {
list_for_each_entry_safe(info, n, &mem_device->res_list, list)
kfree(info);
return -EINVAL;
}

acpi_os_free(buffer.pointer);
return_VALUE(0);
return 0;
}

static int
Expand Down Expand Up @@ -181,7 +211,8 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)

static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
{
int result;
int result, num_enabled = 0;
struct acpi_memory_info *info;

ACPI_FUNCTION_TRACE("acpi_memory_enable_device");

Expand All @@ -197,12 +228,20 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
/*
* Tell the VM there is more memory here...
* Note: Assume that this function returns zero on success
* We don't have memory-hot-add rollback function,now.
* (i.e. memory-hot-remove function)
*/
result = add_memory(mem_device->start_addr, mem_device->length);
if (result) {
list_for_each_entry(info, &mem_device->res_list, list) {
result = add_memory(info->start_addr, info->length);
if (result)
continue;
info->enabled = 1;
num_enabled++;
}
if (!num_enabled) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n"));
mem_device->state = MEMORY_INVALID_STATE;
return result;
return -EINVAL;
}

return result;
Expand Down Expand Up @@ -246,19 +285,21 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
{
int result;
u64 start = mem_device->start_addr;
u64 len = mem_device->length;
struct acpi_memory_info *info, *n;

ACPI_FUNCTION_TRACE("acpi_memory_disable_device");

/*
* Ask the VM to offline this memory range.
* Note: Assume that this function returns zero on success
*/
result = remove_memory(start, len);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
return_VALUE(result);
list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
if (info->enabled) {
result = remove_memory(info->start_addr, info->length);
if (result)
return result;
}
kfree(info);
}

/* Power-off and eject the device */
Expand Down Expand Up @@ -356,6 +397,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
return_VALUE(-ENOMEM);
memset(mem_device, 0, sizeof(struct acpi_memory_device));

INIT_LIST_HEAD(&mem_device->res_list);
mem_device->handle = device->handle;
sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
Expand Down

0 comments on commit 3baee88

Please sign in to comment.