mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 16:48:38 -04:00
Merge commit 'linus' into next
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
# drivers/Kconfig
|
||||
|
||||
menu "Device Drivers"
|
||||
|
||||
source "drivers/base/Kconfig"
|
||||
|
||||
@@ -19,6 +19,7 @@ obj-y += acpi.o \
|
||||
|
||||
# All the builtin files are in the "acpi." module_param namespace.
|
||||
acpi-y += osl.o utils.o reboot.o
|
||||
acpi-y += hest.o
|
||||
|
||||
# sleep related files
|
||||
acpi-y += wakeup.o
|
||||
|
||||
@@ -537,7 +537,7 @@ static int __init acpi_memory_device_init(void)
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
acpi_memory_register_notify_handler,
|
||||
acpi_memory_register_notify_handler, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@@ -561,7 +561,7 @@ static void __exit acpi_memory_device_exit(void)
|
||||
*/
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
acpi_memory_deregister_notify_handler,
|
||||
acpi_memory_deregister_notify_handler, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
|
||||
@@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
|
||||
acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
|
||||
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
|
||||
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
|
||||
nsparse.o nspredef.o nsrepair.o
|
||||
nsparse.o nspredef.o nsrepair.o nsrepair2.o
|
||||
|
||||
acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
|
||||
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
|
||||
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
|
||||
#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist
|
||||
#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist
|
||||
|
||||
#else
|
||||
|
||||
@@ -349,6 +350,8 @@
|
||||
#define ACPI_ERROR_NAMESPACE(s, e)
|
||||
#define ACPI_ERROR_METHOD(s, n, p, e)
|
||||
#define ACPI_WARN_PREDEFINED(plist)
|
||||
#define ACPI_INFO_PREDEFINED(plist)
|
||||
|
||||
#endif /* ACPI_NO_ERROR_MESSAGES */
|
||||
|
||||
/*
|
||||
|
||||
@@ -104,7 +104,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
|
||||
acpi_handle start_object,
|
||||
u32 max_depth,
|
||||
u32 flags,
|
||||
acpi_walk_callback user_function,
|
||||
acpi_walk_callback pre_order_visit,
|
||||
acpi_walk_callback post_order_visit,
|
||||
void *context, void **return_value);
|
||||
|
||||
struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
|
||||
@@ -272,7 +273,8 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node,
|
||||
acpi_object_handler handler, void **data);
|
||||
|
||||
/*
|
||||
* nsrepair - return object repair for predefined methods/objects
|
||||
* nsrepair - General return object repair for all
|
||||
* predefined methods/objects
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ns_repair_object(struct acpi_predefined_data *data,
|
||||
@@ -284,6 +286,16 @@ acpi_status
|
||||
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **obj_desc_ptr);
|
||||
|
||||
/*
|
||||
* nsrepair2 - Return object repair for specific
|
||||
* predefined methods/objects
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ns_complex_repairs(struct acpi_predefined_data *data,
|
||||
struct acpi_namespace_node *node,
|
||||
acpi_status validate_status,
|
||||
union acpi_operand_object **return_object_ptr);
|
||||
|
||||
/*
|
||||
* nssearch - Namespace searching and entry
|
||||
*/
|
||||
|
||||
@@ -386,6 +386,8 @@ u8 acpi_ut_valid_internal_object(void *object);
|
||||
|
||||
union acpi_operand_object *acpi_ut_create_package_object(u32 count);
|
||||
|
||||
union acpi_operand_object *acpi_ut_create_integer_object(u64 value);
|
||||
|
||||
union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
|
||||
|
||||
union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
|
||||
@@ -481,6 +483,11 @@ acpi_ut_predefined_warning(const char *module_name,
|
||||
char *pathname,
|
||||
u8 node_flags, const char *format, ...);
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_predefined_info(const char *module_name,
|
||||
u32 line_number,
|
||||
char *pathname, u8 node_flags, const char *format, ...);
|
||||
|
||||
/* Values for Base above (16=Hex, 10=Decimal) */
|
||||
|
||||
#define ACPI_ANY_BASE 0
|
||||
|
||||
@@ -192,7 +192,7 @@ acpi_ds_initialize_objects(u32 table_index,
|
||||
status =
|
||||
acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
|
||||
ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object,
|
||||
&info, NULL);
|
||||
NULL, &info, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
|
||||
}
|
||||
|
||||
@@ -409,13 +409,11 @@ acpi_ds_method_data_get_value(u8 type,
|
||||
/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
|
||||
|
||||
if (acpi_gbl_enable_interpreter_slack) {
|
||||
object =
|
||||
acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
object = acpi_ut_create_integer_object((u64) 0);
|
||||
if (!object) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
object->integer.value = 0;
|
||||
node->object = object;
|
||||
}
|
||||
|
||||
|
||||
@@ -486,7 +486,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
*
|
||||
* Note: technically, this is an error, from ACPI spec: "It is an error
|
||||
* for NumElements to be less than the number of elements in the
|
||||
* PackageList". However, we just print an error message and
|
||||
* PackageList". However, we just print a message and
|
||||
* no exception is returned. This provides Windows compatibility. Some
|
||||
* BIOSs will alter the num_elements on the fly, creating this type
|
||||
* of ill-formed package object.
|
||||
@@ -510,9 +510,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Package List length (0x%X) larger than NumElements count (0x%X), truncated\n",
|
||||
i, element_count));
|
||||
ACPI_INFO((AE_INFO,
|
||||
"Actual Package length (0x%X) is larger than NumElements field (0x%X), truncated\n",
|
||||
i, element_count));
|
||||
} else if (i < element_count) {
|
||||
/*
|
||||
* Arg list (elements) was exhausted, but we did not reach num_elements count.
|
||||
|
||||
@@ -639,26 +639,42 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
|
||||
break;
|
||||
|
||||
case AML_SCOPE_OP:
|
||||
/*
|
||||
* The Path is an object reference to an existing object.
|
||||
* Don't enter the name into the namespace, but look it up
|
||||
* for use later.
|
||||
*/
|
||||
status =
|
||||
acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
|
||||
object_type, ACPI_IMODE_EXECUTE,
|
||||
ACPI_NS_SEARCH_PARENT, walk_state, &(node));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
#ifdef ACPI_ASL_COMPILER
|
||||
if (status == AE_NOT_FOUND) {
|
||||
status = AE_OK;
|
||||
} else {
|
||||
ACPI_ERROR_NAMESPACE(buffer_ptr, status);
|
||||
|
||||
/* Special case for Scope(\) -> refers to the Root node */
|
||||
|
||||
if (op && (op->named.node == acpi_gbl_root_node)) {
|
||||
node = op->named.node;
|
||||
|
||||
status =
|
||||
acpi_ds_scope_stack_push(node, object_type,
|
||||
walk_state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* The Path is an object reference to an existing object.
|
||||
* Don't enter the name into the namespace, but look it up
|
||||
* for use later.
|
||||
*/
|
||||
status =
|
||||
acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
|
||||
object_type, ACPI_IMODE_EXECUTE,
|
||||
ACPI_NS_SEARCH_PARENT, walk_state,
|
||||
&(node));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
#ifdef ACPI_ASL_COMPILER
|
||||
if (status == AE_NOT_FOUND) {
|
||||
status = AE_OK;
|
||||
} else {
|
||||
ACPI_ERROR_NAMESPACE(buffer_ptr,
|
||||
status);
|
||||
}
|
||||
#else
|
||||
ACPI_ERROR_NAMESPACE(buffer_ptr, status);
|
||||
ACPI_ERROR_NAMESPACE(buffer_ptr, status);
|
||||
#endif
|
||||
return_ACPI_STATUS(status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -945,8 +945,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
|
||||
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
|
||||
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
|
||||
acpi_ev_save_method_info, gpe_block,
|
||||
NULL);
|
||||
acpi_ev_save_method_info, NULL,
|
||||
gpe_block, NULL);
|
||||
|
||||
/* Return the new block */
|
||||
|
||||
@@ -1022,8 +1022,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
||||
status =
|
||||
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
|
||||
acpi_ev_match_prw_and_gpe, &gpe_info,
|
||||
NULL);
|
||||
acpi_ev_match_prw_and_gpe, NULL,
|
||||
&gpe_info, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
ACPI_MODULE_NAME("evregion")
|
||||
|
||||
/* Local prototypes */
|
||||
static u8
|
||||
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
|
||||
acpi_adr_space_type space_id);
|
||||
|
||||
static acpi_status
|
||||
acpi_ev_reg_run(acpi_handle obj_handle,
|
||||
u32 level, void *context, void **return_value);
|
||||
@@ -140,6 +144,50 @@ acpi_status acpi_ev_install_region_handlers(void)
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_has_default_handler
|
||||
*
|
||||
* PARAMETERS: Node - Namespace node for the device
|
||||
* space_id - The address space ID
|
||||
*
|
||||
* RETURN: TRUE if default handler is installed, FALSE otherwise
|
||||
*
|
||||
* DESCRIPTION: Check if the default handler is installed for the requested
|
||||
* space ID.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u8
|
||||
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
|
||||
acpi_adr_space_type space_id)
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
union acpi_operand_object *handler_obj;
|
||||
|
||||
/* Must have an existing internal object */
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
if (obj_desc) {
|
||||
handler_obj = obj_desc->device.handler;
|
||||
|
||||
/* Walk the linked list of handlers for this object */
|
||||
|
||||
while (handler_obj) {
|
||||
if (handler_obj->address_space.space_id == space_id) {
|
||||
if (handler_obj->address_space.handler_flags &
|
||||
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
handler_obj = handler_obj->address_space.next;
|
||||
}
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_initialize_op_regions
|
||||
@@ -169,12 +217,18 @@ acpi_status acpi_ev_initialize_op_regions(void)
|
||||
|
||||
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
|
||||
/*
|
||||
* TBD: Make sure handler is the DEFAULT handler, otherwise
|
||||
* _REG will have already been run.
|
||||
* Make sure the installed handler is the DEFAULT handler. If not the
|
||||
* default, the _REG methods will have already been run (when the
|
||||
* handler was installed)
|
||||
*/
|
||||
status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
|
||||
acpi_gbl_default_address_spaces
|
||||
[i]);
|
||||
if (acpi_ev_has_default_handler(acpi_gbl_root_node,
|
||||
acpi_gbl_default_address_spaces
|
||||
[i])) {
|
||||
status =
|
||||
acpi_ev_execute_reg_methods(acpi_gbl_root_node,
|
||||
acpi_gbl_default_address_spaces
|
||||
[i]);
|
||||
}
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
@@ -235,23 +289,20 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
|
||||
* connection status 1 for connecting the handler, 0 for disconnecting
|
||||
* the handler (Passed as a parameter)
|
||||
*/
|
||||
args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
args[0] =
|
||||
acpi_ut_create_integer_object((u64) region_obj->region.space_id);
|
||||
if (!args[0]) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup1;
|
||||
}
|
||||
|
||||
args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
args[1] = acpi_ut_create_integer_object((u64) function);
|
||||
if (!args[1]) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup2;
|
||||
}
|
||||
|
||||
/* Setup the parameter objects */
|
||||
|
||||
args[0]->integer.value = region_obj->region.space_id;
|
||||
args[1]->integer.value = function;
|
||||
args[2] = NULL;
|
||||
args[2] = NULL; /* Terminate list */
|
||||
|
||||
/* Execute the method, no return value */
|
||||
|
||||
@@ -971,8 +1022,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
|
||||
*/
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
|
||||
ACPI_NS_WALK_UNLOCK,
|
||||
acpi_ev_install_handler, handler_obj,
|
||||
NULL);
|
||||
acpi_ev_install_handler, NULL,
|
||||
handler_obj, NULL);
|
||||
|
||||
unlock_and_exit:
|
||||
return_ACPI_STATUS(status);
|
||||
@@ -1008,7 +1059,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
|
||||
*/
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
|
||||
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
|
||||
&space_id, NULL);
|
||||
NULL, &space_id, NULL);
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
@@ -170,14 +170,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* Table not found, return an Integer=0 and AE_OK */
|
||||
|
||||
ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
ddb_handle = acpi_ut_create_integer_object((u64) 0);
|
||||
if (!ddb_handle) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ddb_handle->integer.value = 0;
|
||||
*return_desc = ddb_handle;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
|
||||
|
||||
/* Create a new integer */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
return_desc = acpi_ut_create_integer_object(result);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
@@ -177,7 +177,6 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
|
||||
|
||||
/* Save the Result */
|
||||
|
||||
return_desc->integer.value = result;
|
||||
acpi_ex_truncate_for32bit_table(return_desc);
|
||||
*result_desc = return_desc;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
@@ -162,13 +162,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
||||
} else {
|
||||
/* Field will fit within an Integer (normal case) */
|
||||
|
||||
buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
buffer_desc = acpi_ut_create_integer_object((u64) 0);
|
||||
if (!buffer_desc) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
length = acpi_gbl_integer_byte_width;
|
||||
buffer_desc->integer.value = 0;
|
||||
buffer = &buffer_desc->integer.value;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,12 +100,12 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
|
||||
|
||||
/* Create a return object of type Integer */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
return_desc =
|
||||
acpi_ut_create_integer_object(acpi_os_get_timer());
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
return_desc->integer.value = acpi_os_get_timer();
|
||||
break;
|
||||
|
||||
default: /* Unknown opcode */
|
||||
@@ -599,7 +599,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
||||
switch (walk_state->opcode) {
|
||||
case AML_LNOT_OP: /* LNot (Operand) */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
return_desc = acpi_ut_create_integer_object((u64) 0);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
@@ -702,13 +702,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
||||
|
||||
/* Allocate a descriptor to hold the type. */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
return_desc = acpi_ut_create_integer_object((u64) type);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc->integer.value = type;
|
||||
break;
|
||||
|
||||
case AML_SIZE_OF_OP: /* size_of (source_object) */
|
||||
@@ -777,13 +775,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
||||
* Now that we have the size of the object, create a result
|
||||
* object to hold the value
|
||||
*/
|
||||
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
return_desc = acpi_ut_create_integer_object(value);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc->integer.value = value;
|
||||
break;
|
||||
|
||||
case AML_REF_OF_OP: /* ref_of (source_object) */
|
||||
@@ -946,24 +942,24 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
|
||||
* NOTE: index into a buffer is NOT a pointer to a
|
||||
* sub-buffer of the main buffer, it is only a pointer to a
|
||||
* single element (byte) of the buffer!
|
||||
*/
|
||||
return_desc =
|
||||
acpi_ut_create_internal_object
|
||||
(ACPI_TYPE_INTEGER);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Since we are returning the value of the buffer at the
|
||||
* indexed location, we don't need to add an additional
|
||||
* reference to the buffer itself.
|
||||
*/
|
||||
return_desc->integer.value =
|
||||
temp_desc->buffer.
|
||||
pointer[operand[0]->reference.
|
||||
value];
|
||||
return_desc =
|
||||
acpi_ut_create_integer_object((u64)
|
||||
temp_desc->
|
||||
buffer.
|
||||
pointer
|
||||
[operand
|
||||
[0]->
|
||||
reference.
|
||||
value]);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
@@ -253,18 +253,15 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
|
||||
}
|
||||
|
||||
/* Create an integer for the return value */
|
||||
/* Default return value is ACPI_INTEGER_MAX if no match found */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
return_desc = acpi_ut_create_integer_object(ACPI_INTEGER_MAX);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
|
||||
}
|
||||
|
||||
/* Default return value if no match found */
|
||||
|
||||
return_desc->integer.value = ACPI_INTEGER_MAX;
|
||||
|
||||
/*
|
||||
* Examine each element until a match is found. Both match conditions
|
||||
* must be satisfied for a match to occur. Within the loop,
|
||||
|
||||
@@ -634,8 +634,8 @@ acpi_ns_dump_objects(acpi_object_type type,
|
||||
(void)acpi_ns_walk_namespace(type, start_handle, max_depth,
|
||||
ACPI_NS_WALK_NO_UNLOCK |
|
||||
ACPI_NS_WALK_TEMP_NODES,
|
||||
acpi_ns_dump_one_object, (void *)&info,
|
||||
NULL);
|
||||
acpi_ns_dump_one_object, NULL,
|
||||
(void *)&info, NULL);
|
||||
}
|
||||
#endif /* ACPI_FUTURE_USAGE */
|
||||
|
||||
|
||||
@@ -131,7 +131,8 @@ void acpi_ns_dump_root_devices(void)
|
||||
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle,
|
||||
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
|
||||
acpi_ns_dump_one_device, NULL, NULL);
|
||||
acpi_ns_dump_one_device, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -366,33 +366,49 @@ static void
|
||||
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
|
||||
struct acpi_evaluate_info *info)
|
||||
{
|
||||
union acpi_operand_object *root_obj;
|
||||
union acpi_operand_object *parent_obj;
|
||||
struct acpi_namespace_node *parent_node;
|
||||
acpi_object_type type;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_exec_module_code);
|
||||
|
||||
/*
|
||||
* Get the parent node. We cheat by using the next_object field
|
||||
* of the method object descriptor.
|
||||
*/
|
||||
parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||
method_obj->method.next_object);
|
||||
type = acpi_ns_get_type(parent_node);
|
||||
|
||||
/* Must clear next_object (acpi_ns_attach_object needs the field) */
|
||||
|
||||
method_obj->method.next_object = NULL;
|
||||
|
||||
/* Initialize the evaluation information block */
|
||||
|
||||
ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
|
||||
info->prefix_node = acpi_gbl_root_node;
|
||||
info->prefix_node = parent_node;
|
||||
|
||||
/*
|
||||
* Get the currently attached root object. Add a reference, because the
|
||||
* Get the currently attached parent object. Add a reference, because the
|
||||
* ref count will be decreased when the method object is installed to
|
||||
* the root node.
|
||||
* the parent node.
|
||||
*/
|
||||
root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
|
||||
acpi_ut_add_reference(root_obj);
|
||||
parent_obj = acpi_ns_get_attached_object(parent_node);
|
||||
if (parent_obj) {
|
||||
acpi_ut_add_reference(parent_obj);
|
||||
}
|
||||
|
||||
/* Install the method (module-level code) in the root node */
|
||||
/* Install the method (module-level code) in the parent node */
|
||||
|
||||
status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
|
||||
status = acpi_ns_attach_object(parent_node, method_obj,
|
||||
ACPI_TYPE_METHOD);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Execute the root node as a control method */
|
||||
/* Execute the parent node as a control method */
|
||||
|
||||
status = acpi_ns_evaluate(info);
|
||||
|
||||
@@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
|
||||
|
||||
/* Detach the temporary method object */
|
||||
|
||||
acpi_ns_detach_object(acpi_gbl_root_node);
|
||||
acpi_ns_detach_object(parent_node);
|
||||
|
||||
/* Restore the original root object */
|
||||
/* Restore the original parent object */
|
||||
|
||||
status =
|
||||
acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
|
||||
ACPI_TYPE_DEVICE);
|
||||
if (parent_obj) {
|
||||
status = acpi_ns_attach_object(parent_node, parent_obj, type);
|
||||
} else {
|
||||
parent_node->type = (u8)type;
|
||||
}
|
||||
|
||||
exit:
|
||||
acpi_ut_remove_reference(root_obj);
|
||||
if (parent_obj) {
|
||||
acpi_ut_remove_reference(parent_obj);
|
||||
}
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ acpi_status acpi_ns_initialize_objects(void)
|
||||
/* Walk entire namespace from the supplied root */
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, acpi_ns_init_one_object,
|
||||
ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL,
|
||||
&info, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
|
||||
@@ -156,7 +156,8 @@ acpi_status acpi_ns_initialize_devices(void)
|
||||
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, FALSE,
|
||||
acpi_ns_find_ini_methods, &info, NULL);
|
||||
acpi_ns_find_ini_methods, NULL, &info,
|
||||
NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto error_exit;
|
||||
}
|
||||
@@ -189,7 +190,8 @@ acpi_status acpi_ns_initialize_devices(void)
|
||||
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, FALSE,
|
||||
acpi_ns_init_one_device, &info, NULL);
|
||||
acpi_ns_init_one_device, NULL, &info,
|
||||
NULL);
|
||||
|
||||
ACPI_FREE(info.evaluate_info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
@@ -232,6 +232,12 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
||||
status = acpi_ns_check_package(data, return_object_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform additional, more complicated repairs on a per-name
|
||||
* basis.
|
||||
*/
|
||||
status = acpi_ns_complex_repairs(data, node, status, return_object_ptr);
|
||||
|
||||
check_validation_status:
|
||||
/*
|
||||
* If the object validation failed or if we successfully repaired one
|
||||
@@ -601,7 +607,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
|
||||
* there is only one entry). We may be able to repair this by
|
||||
* wrapping the returned Package with a new outer Package.
|
||||
*/
|
||||
if ((*elements)->common.type != ACPI_TYPE_PACKAGE) {
|
||||
if (*elements
|
||||
&& ((*elements)->common.type != ACPI_TYPE_PACKAGE)) {
|
||||
|
||||
/* Create the new outer package and populate it */
|
||||
|
||||
@@ -673,6 +680,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object *sub_package;
|
||||
union acpi_operand_object **sub_elements;
|
||||
acpi_status status;
|
||||
u8 non_trailing_null = FALSE;
|
||||
u32 expected_count;
|
||||
u32 i;
|
||||
u32 j;
|
||||
@@ -680,6 +688,45 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
|
||||
/* Validate each sub-Package in the parent Package */
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/*
|
||||
* Handling for NULL package elements. For now, we will simply allow
|
||||
* a parent package with trailing NULL elements. This can happen if
|
||||
* the package was defined to be longer than the initializer list.
|
||||
* This is legal as per the ACPI specification. It is often used
|
||||
* to allow for dynamic initialization of a Package.
|
||||
*
|
||||
* A future enhancement may be to simply truncate the package to
|
||||
* remove the trailing NULL elements.
|
||||
*/
|
||||
if (!(*elements)) {
|
||||
if (!non_trailing_null) {
|
||||
|
||||
/* Ensure the remaining elements are all NULL */
|
||||
|
||||
for (j = 1; j < (count - i + 1); j++) {
|
||||
if (elements[j]) {
|
||||
non_trailing_null = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!non_trailing_null) {
|
||||
|
||||
/* Ignore the trailing NULL elements */
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* There are trailing non-null elements, issue warning */
|
||||
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
|
||||
data->node_flags,
|
||||
"Found NULL element at package index %u",
|
||||
i));
|
||||
elements++;
|
||||
continue;
|
||||
}
|
||||
|
||||
sub_package = *elements;
|
||||
sub_elements = sub_package->package.elements;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
#include "acpredef.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
@@ -76,7 +77,13 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
union acpi_operand_object *new_object;
|
||||
acpi_size length;
|
||||
acpi_status status;
|
||||
|
||||
/*
|
||||
* At this point, we know that the type of the returned object was not
|
||||
* one of the expected types for this predefined name. Attempt to
|
||||
* repair the object. Only a limited number of repairs are possible.
|
||||
*/
|
||||
switch (return_object->common.type) {
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
@@ -111,43 +118,94 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
|
||||
*/
|
||||
ACPI_MEMCPY(new_object->string.pointer,
|
||||
return_object->buffer.pointer, length);
|
||||
break;
|
||||
|
||||
/*
|
||||
* If the original object is a package element, we need to:
|
||||
* 1. Set the reference count of the new object to match the
|
||||
* reference count of the old object.
|
||||
* 2. Decrement the reference count of the original object.
|
||||
*/
|
||||
if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
|
||||
new_object->common.reference_count =
|
||||
return_object->common.reference_count;
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
if (return_object->common.reference_count > 1) {
|
||||
return_object->common.reference_count--;
|
||||
/* 1) Does the method/object legally return a buffer? */
|
||||
|
||||
if (expected_btypes & ACPI_RTYPE_BUFFER) {
|
||||
/*
|
||||
* Convert the Integer to a packed-byte buffer. _MAT needs
|
||||
* this sometimes, if a read has been performed on a Field
|
||||
* object that is less than or equal to the global integer
|
||||
* size (32 or 64 bits).
|
||||
*/
|
||||
status =
|
||||
acpi_ex_convert_to_buffer(return_object,
|
||||
&new_object);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
|
||||
data->node_flags,
|
||||
"Converted Buffer to expected String at index %u",
|
||||
package_index));
|
||||
} else {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
|
||||
data->node_flags,
|
||||
"Converted Buffer to expected String"));
|
||||
}
|
||||
|
||||
/* Delete old object, install the new return object */
|
||||
/* 2) Does the method/object legally return a string? */
|
||||
|
||||
acpi_ut_remove_reference(return_object);
|
||||
*return_object_ptr = new_object;
|
||||
data->flags |= ACPI_OBJECT_REPAIRED;
|
||||
return (AE_OK);
|
||||
else if (expected_btypes & ACPI_RTYPE_STRING) {
|
||||
/*
|
||||
* The only supported Integer-to-String conversion is to convert
|
||||
* an integer of value 0 to a NULL string. The last element of
|
||||
* _BIF and _BIX packages occasionally need this fix.
|
||||
*/
|
||||
if (return_object->integer.value != 0) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Allocate a new NULL string object */
|
||||
|
||||
new_object = acpi_ut_create_string_object(0);
|
||||
if (!new_object) {
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
} else {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
/* We cannot repair this object */
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
/* Object was successfully repaired */
|
||||
|
||||
/*
|
||||
* If the original object is a package element, we need to:
|
||||
* 1. Set the reference count of the new object to match the
|
||||
* reference count of the old object.
|
||||
* 2. Decrement the reference count of the original object.
|
||||
*/
|
||||
if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
|
||||
new_object->common.reference_count =
|
||||
return_object->common.reference_count;
|
||||
|
||||
if (return_object->common.reference_count > 1) {
|
||||
return_object->common.reference_count--;
|
||||
}
|
||||
|
||||
ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"Converted %s to expected %s at index %u",
|
||||
acpi_ut_get_object_type_name
|
||||
(return_object),
|
||||
acpi_ut_get_object_type_name(new_object),
|
||||
package_index));
|
||||
} else {
|
||||
ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"Converted %s to expected %s",
|
||||
acpi_ut_get_object_type_name
|
||||
(return_object),
|
||||
acpi_ut_get_object_type_name
|
||||
(new_object)));
|
||||
}
|
||||
|
||||
/* Delete old object, install the new return object */
|
||||
|
||||
acpi_ut_remove_reference(return_object);
|
||||
*return_object_ptr = new_object;
|
||||
data->flags |= ACPI_OBJECT_REPAIRED;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -196,8 +254,8 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data,
|
||||
*obj_desc_ptr = pkg_obj_desc;
|
||||
data->flags |= ACPI_OBJECT_REPAIRED;
|
||||
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"Incorrectly formed Package, attempting repair"));
|
||||
ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"Repaired Incorrectly formed Package"));
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
540
drivers/acpi/acpica/nsrepair2.c
Normal file
540
drivers/acpi/acpica/nsrepair2.c
Normal file
@@ -0,0 +1,540 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: nsrepair2 - Repair for objects returned by specific
|
||||
* predefined methods
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2009, Intel Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("nsrepair2")
|
||||
|
||||
/*
|
||||
* Information structure and handler for ACPI predefined names that can
|
||||
* be repaired on a per-name basis.
|
||||
*/
|
||||
typedef
|
||||
acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr);
|
||||
|
||||
typedef struct acpi_repair_info {
|
||||
char name[ACPI_NAME_SIZE];
|
||||
acpi_repair_function repair_function;
|
||||
|
||||
} acpi_repair_info;
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
|
||||
acpi_namespace_node
|
||||
*node);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_ALR(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_PSS(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_TSS(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object *return_object,
|
||||
u32 expected_count,
|
||||
u32 sort_index,
|
||||
u8 sort_direction, char *sort_key_name);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_remove_null_elements(union acpi_operand_object *package);
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_sort_list(union acpi_operand_object **elements,
|
||||
u32 count, u32 index, u8 sort_direction);
|
||||
|
||||
/* Values for sort_direction above */
|
||||
|
||||
#define ACPI_SORT_ASCENDING 0
|
||||
#define ACPI_SORT_DESCENDING 1
|
||||
|
||||
/*
|
||||
* This table contains the names of the predefined methods for which we can
|
||||
* perform more complex repairs.
|
||||
*
|
||||
* _ALR: Sort the list ascending by ambient_illuminance if necessary
|
||||
* _PSS: Sort the list descending by Power if necessary
|
||||
* _TSS: Sort the list descending by Power if necessary
|
||||
*/
|
||||
static const struct acpi_repair_info acpi_ns_repairable_names[] = {
|
||||
{"_ALR", acpi_ns_repair_ALR},
|
||||
{"_PSS", acpi_ns_repair_PSS},
|
||||
{"_TSS", acpi_ns_repair_TSS},
|
||||
{{0, 0, 0, 0}, NULL} /* Table terminator */
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_complex_repairs
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* Node - Namespace node for the method/object
|
||||
* validate_status - Original status of earlier validation
|
||||
* return_object_ptr - Pointer to the object returned from the
|
||||
* evaluation of a method or object
|
||||
*
|
||||
* RETURN: Status. AE_OK if repair was successful. If name is not
|
||||
* matched, validate_status is returned.
|
||||
*
|
||||
* DESCRIPTION: Attempt to repair/convert a return object of a type that was
|
||||
* not expected.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ns_complex_repairs(struct acpi_predefined_data *data,
|
||||
struct acpi_namespace_node *node,
|
||||
acpi_status validate_status,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
const struct acpi_repair_info *predefined;
|
||||
acpi_status status;
|
||||
|
||||
/* Check if this name is in the list of repairable names */
|
||||
|
||||
predefined = acpi_ns_match_repairable_name(node);
|
||||
if (!predefined) {
|
||||
return (validate_status);
|
||||
}
|
||||
|
||||
status = predefined->repair_function(data, return_object_ptr);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_match_repairable_name
|
||||
*
|
||||
* PARAMETERS: Node - Namespace node for the method/object
|
||||
*
|
||||
* RETURN: Pointer to entry in repair table. NULL indicates not found.
|
||||
*
|
||||
* DESCRIPTION: Check an object name against the repairable object list.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
|
||||
acpi_namespace_node
|
||||
*node)
|
||||
{
|
||||
const struct acpi_repair_info *this_name;
|
||||
|
||||
/* Search info table for a repairable predefined method/object name */
|
||||
|
||||
this_name = acpi_ns_repairable_names;
|
||||
while (this_name->repair_function) {
|
||||
if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
|
||||
return (this_name);
|
||||
}
|
||||
this_name++;
|
||||
}
|
||||
|
||||
return (NULL); /* Not found */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_repair_ALR
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* return_object_ptr - Pointer to the object returned from the
|
||||
* evaluation of a method or object
|
||||
*
|
||||
* RETURN: Status. AE_OK if object is OK or was repaired successfully
|
||||
*
|
||||
* DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
|
||||
* ascending by the ambient illuminance values.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_ALR(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_ns_check_sorted_list(data, return_object, 2, 1,
|
||||
ACPI_SORT_ASCENDING,
|
||||
"AmbientIlluminance");
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_repair_TSS
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* return_object_ptr - Pointer to the object returned from the
|
||||
* evaluation of a method or object
|
||||
*
|
||||
* RETURN: Status. AE_OK if object is OK or was repaired successfully
|
||||
*
|
||||
* DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
|
||||
* descending by the power dissipation values.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_TSS(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_ns_check_sorted_list(data, return_object, 5, 1,
|
||||
ACPI_SORT_DESCENDING,
|
||||
"PowerDissipation");
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_repair_PSS
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* return_object_ptr - Pointer to the object returned from the
|
||||
* evaluation of a method or object
|
||||
*
|
||||
* RETURN: Status. AE_OK if object is OK or was repaired successfully
|
||||
*
|
||||
* DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
|
||||
* by the CPU frequencies. Check that the power dissipation values
|
||||
* are all proportional to CPU frequency (i.e., sorting by
|
||||
* frequency should be the same as sorting by power.)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_repair_PSS(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
union acpi_operand_object **outer_elements;
|
||||
u32 outer_element_count;
|
||||
union acpi_operand_object **elements;
|
||||
union acpi_operand_object *obj_desc;
|
||||
u32 previous_value;
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
* Entries (sub-packages) in the _PSS Package must be sorted by power
|
||||
* dissipation, in descending order. If it appears that the list is
|
||||
* incorrectly sorted, sort it. We sort by cpu_frequency, since this
|
||||
* should be proportional to the power.
|
||||
*/
|
||||
status = acpi_ns_check_sorted_list(data, return_object, 6, 0,
|
||||
ACPI_SORT_DESCENDING,
|
||||
"CpuFrequency");
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* We now know the list is correctly sorted by CPU frequency. Check if
|
||||
* the power dissipation values are proportional.
|
||||
*/
|
||||
previous_value = ACPI_UINT32_MAX;
|
||||
outer_elements = return_object->package.elements;
|
||||
outer_element_count = return_object->package.count;
|
||||
|
||||
for (i = 0; i < outer_element_count; i++) {
|
||||
elements = (*outer_elements)->package.elements;
|
||||
obj_desc = elements[1]; /* Index1 = power_dissipation */
|
||||
|
||||
if ((u32) obj_desc->integer.value > previous_value) {
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
|
||||
data->node_flags,
|
||||
"SubPackage[%u,%u] - suspicious power dissipation values",
|
||||
i - 1, i));
|
||||
}
|
||||
|
||||
previous_value = (u32) obj_desc->integer.value;
|
||||
outer_elements++;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_check_sorted_list
|
||||
*
|
||||
* PARAMETERS: Data - Pointer to validation data structure
|
||||
* return_object - Pointer to the top-level returned object
|
||||
* expected_count - Minimum length of each sub-package
|
||||
* sort_index - Sub-package entry to sort on
|
||||
* sort_direction - Ascending or descending
|
||||
* sort_key_name - Name of the sort_index field
|
||||
*
|
||||
* RETURN: Status. AE_OK if the list is valid and is sorted correctly or
|
||||
* has been repaired by sorting the list.
|
||||
*
|
||||
* DESCRIPTION: Check if the package list is valid and sorted correctly by the
|
||||
* sort_index. If not, then sort the list.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
|
||||
union acpi_operand_object *return_object,
|
||||
u32 expected_count,
|
||||
u32 sort_index,
|
||||
u8 sort_direction, char *sort_key_name)
|
||||
{
|
||||
u32 outer_element_count;
|
||||
union acpi_operand_object **outer_elements;
|
||||
union acpi_operand_object **elements;
|
||||
union acpi_operand_object *obj_desc;
|
||||
u32 i;
|
||||
u32 previous_value;
|
||||
acpi_status status;
|
||||
|
||||
/* The top-level object must be a package */
|
||||
|
||||
if (return_object->common.type != ACPI_TYPE_PACKAGE) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect any NULL package elements and remove them from the
|
||||
* package.
|
||||
*
|
||||
* TBD: We may want to do this for all predefined names that
|
||||
* return a variable-length package of packages.
|
||||
*/
|
||||
status = acpi_ns_remove_null_elements(return_object);
|
||||
if (status == AE_NULL_ENTRY) {
|
||||
ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
|
||||
"NULL elements removed from package"));
|
||||
|
||||
/* Exit if package is now zero length */
|
||||
|
||||
if (!return_object->package.count) {
|
||||
return (AE_NULL_ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
outer_elements = return_object->package.elements;
|
||||
outer_element_count = return_object->package.count;
|
||||
if (!outer_element_count) {
|
||||
return (AE_AML_PACKAGE_LIMIT);
|
||||
}
|
||||
|
||||
previous_value = 0;
|
||||
if (sort_direction == ACPI_SORT_DESCENDING) {
|
||||
previous_value = ACPI_UINT32_MAX;
|
||||
}
|
||||
|
||||
/* Examine each subpackage */
|
||||
|
||||
for (i = 0; i < outer_element_count; i++) {
|
||||
|
||||
/* Each element of the top-level package must also be a package */
|
||||
|
||||
if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Each sub-package must have the minimum length */
|
||||
|
||||
if ((*outer_elements)->package.count < expected_count) {
|
||||
return (AE_AML_PACKAGE_LIMIT);
|
||||
}
|
||||
|
||||
elements = (*outer_elements)->package.elements;
|
||||
obj_desc = elements[sort_index];
|
||||
|
||||
if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The list must be sorted in the specified order. If we detect a
|
||||
* discrepancy, issue a warning and sort the entire list
|
||||
*/
|
||||
if (((sort_direction == ACPI_SORT_ASCENDING) &&
|
||||
(obj_desc->integer.value < previous_value)) ||
|
||||
((sort_direction == ACPI_SORT_DESCENDING) &&
|
||||
(obj_desc->integer.value > previous_value))) {
|
||||
status =
|
||||
acpi_ns_sort_list(return_object->package.elements,
|
||||
outer_element_count, sort_index,
|
||||
sort_direction);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
data->flags |= ACPI_OBJECT_REPAIRED;
|
||||
|
||||
ACPI_INFO_PREDEFINED((AE_INFO, data->pathname,
|
||||
data->node_flags,
|
||||
"Repaired unsorted list - now sorted by %s",
|
||||
sort_key_name));
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
previous_value = (u32) obj_desc->integer.value;
|
||||
outer_elements++;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_remove_null_elements
|
||||
*
|
||||
* PARAMETERS: obj_desc - A Package object
|
||||
*
|
||||
* RETURN: Status. AE_NULL_ENTRY means that one or more elements were
|
||||
* removed.
|
||||
*
|
||||
* DESCRIPTION: Remove all NULL package elements and update the package count.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
|
||||
{
|
||||
union acpi_operand_object **source;
|
||||
union acpi_operand_object **dest;
|
||||
acpi_status status = AE_OK;
|
||||
u32 count;
|
||||
u32 new_count;
|
||||
u32 i;
|
||||
|
||||
count = obj_desc->package.count;
|
||||
new_count = count;
|
||||
|
||||
source = obj_desc->package.elements;
|
||||
dest = source;
|
||||
|
||||
/* Examine all elements of the package object */
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!*source) {
|
||||
status = AE_NULL_ENTRY;
|
||||
new_count--;
|
||||
} else {
|
||||
*dest = *source;
|
||||
dest++;
|
||||
}
|
||||
source++;
|
||||
}
|
||||
|
||||
if (status == AE_NULL_ENTRY) {
|
||||
|
||||
/* NULL terminate list and update the package count */
|
||||
|
||||
*dest = NULL;
|
||||
obj_desc->package.count = new_count;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ns_sort_list
|
||||
*
|
||||
* PARAMETERS: Elements - Package object element list
|
||||
* Count - Element count for above
|
||||
* Index - Sort by which package element
|
||||
* sort_direction - Ascending or Descending sort
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Sort the objects that are in a package element list.
|
||||
*
|
||||
* NOTE: Assumes that all NULL elements have been removed from the package.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ns_sort_list(union acpi_operand_object **elements,
|
||||
u32 count, u32 index, u8 sort_direction)
|
||||
{
|
||||
union acpi_operand_object *obj_desc1;
|
||||
union acpi_operand_object *obj_desc2;
|
||||
union acpi_operand_object *temp_obj;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
/* Simple bubble sort */
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
for (j = (count - 1); j >= i; j--) {
|
||||
obj_desc1 = elements[j - 1]->package.elements[index];
|
||||
obj_desc2 = elements[j]->package.elements[index];
|
||||
|
||||
if (((sort_direction == ACPI_SORT_ASCENDING) &&
|
||||
(obj_desc1->integer.value >
|
||||
obj_desc2->integer.value))
|
||||
|| ((sort_direction == ACPI_SORT_DESCENDING)
|
||||
&& (obj_desc1->integer.value <
|
||||
obj_desc2->integer.value))) {
|
||||
temp_obj = elements[j - 1];
|
||||
elements[j - 1] = elements[j];
|
||||
elements[j] = temp_obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
@@ -165,24 +165,27 @@ struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type,
|
||||
* max_depth - Depth to which search is to reach
|
||||
* Flags - Whether to unlock the NS before invoking
|
||||
* the callback routine
|
||||
* user_function - Called when an object of "Type" is found
|
||||
* Context - Passed to user function
|
||||
* return_value - from the user_function if terminated early.
|
||||
* Otherwise, returns NULL.
|
||||
* pre_order_visit - Called during tree pre-order visit
|
||||
* when an object of "Type" is found
|
||||
* post_order_visit - Called during tree post-order visit
|
||||
* when an object of "Type" is found
|
||||
* Context - Passed to user function(s) above
|
||||
* return_value - from the user_function if terminated
|
||||
* early. Otherwise, returns NULL.
|
||||
* RETURNS: Status
|
||||
*
|
||||
* DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
|
||||
* starting (and ending) at the node specified by start_handle.
|
||||
* The user_function is called whenever a node that matches
|
||||
* the type parameter is found. If the user function returns
|
||||
* The callback function is called whenever a node that matches
|
||||
* the type parameter is found. If the callback function returns
|
||||
* a non-zero value, the search is terminated immediately and
|
||||
* this value is returned to the caller.
|
||||
*
|
||||
* The point of this procedure is to provide a generic namespace
|
||||
* walk routine that can be called from multiple places to
|
||||
* provide multiple services; the User Function can be tailored
|
||||
* to each task, whether it is a print function, a compare
|
||||
* function, etc.
|
||||
* provide multiple services; the callback function(s) can be
|
||||
* tailored to each task, whether it is a print function,
|
||||
* a compare function, etc.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@@ -191,7 +194,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
|
||||
acpi_handle start_node,
|
||||
u32 max_depth,
|
||||
u32 flags,
|
||||
acpi_walk_callback user_function,
|
||||
acpi_walk_callback pre_order_visit,
|
||||
acpi_walk_callback post_order_visit,
|
||||
void *context, void **return_value)
|
||||
{
|
||||
acpi_status status;
|
||||
@@ -200,6 +204,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
|
||||
struct acpi_namespace_node *parent_node;
|
||||
acpi_object_type child_type;
|
||||
u32 level;
|
||||
u8 node_previously_visited = FALSE;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_walk_namespace);
|
||||
|
||||
@@ -212,7 +217,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
|
||||
/* Null child means "get first node" */
|
||||
|
||||
parent_node = start_node;
|
||||
child_node = NULL;
|
||||
child_node = acpi_ns_get_next_node(parent_node, NULL);
|
||||
child_type = ACPI_TYPE_ANY;
|
||||
level = 1;
|
||||
|
||||
@@ -221,102 +226,129 @@ acpi_ns_walk_namespace(acpi_object_type type,
|
||||
* started. When Level is zero, the loop is done because we have
|
||||
* bubbled up to (and passed) the original parent handle (start_entry)
|
||||
*/
|
||||
while (level > 0) {
|
||||
|
||||
/* Get the next node in this scope. Null if not found */
|
||||
|
||||
while (level > 0 && child_node) {
|
||||
status = AE_OK;
|
||||
|
||||
/* Found next child, get the type if we are not searching for ANY */
|
||||
|
||||
if (type != ACPI_TYPE_ANY) {
|
||||
child_type = child_node->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore all temporary namespace nodes (created during control
|
||||
* method execution) unless told otherwise. These temporary nodes
|
||||
* can cause a race condition because they can be deleted during
|
||||
* the execution of the user function (if the namespace is
|
||||
* unlocked before invocation of the user function.) Only the
|
||||
* debugger namespace dump will examine the temporary nodes.
|
||||
*/
|
||||
if ((child_node->flags & ANOBJ_TEMPORARY) &&
|
||||
!(flags & ACPI_NS_WALK_TEMP_NODES)) {
|
||||
status = AE_CTRL_DEPTH;
|
||||
}
|
||||
|
||||
/* Type must match requested type */
|
||||
|
||||
else if (child_type == type) {
|
||||
/*
|
||||
* Found a matching node, invoke the user callback function.
|
||||
* Unlock the namespace if flag is set.
|
||||
*/
|
||||
if (flags & ACPI_NS_WALK_UNLOCK) {
|
||||
mutex_status =
|
||||
acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(mutex_status)) {
|
||||
return_ACPI_STATUS(mutex_status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke the user function, either pre-order or post-order
|
||||
* or both.
|
||||
*/
|
||||
if (!node_previously_visited) {
|
||||
if (pre_order_visit) {
|
||||
status =
|
||||
pre_order_visit(child_node, level,
|
||||
context,
|
||||
return_value);
|
||||
}
|
||||
} else {
|
||||
if (post_order_visit) {
|
||||
status =
|
||||
post_order_visit(child_node, level,
|
||||
context,
|
||||
return_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ACPI_NS_WALK_UNLOCK) {
|
||||
mutex_status =
|
||||
acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(mutex_status)) {
|
||||
return_ACPI_STATUS(mutex_status);
|
||||
}
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case AE_OK:
|
||||
case AE_CTRL_DEPTH:
|
||||
|
||||
/* Just keep going */
|
||||
break;
|
||||
|
||||
case AE_CTRL_TERMINATE:
|
||||
|
||||
/* Exit now, with OK status */
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
default:
|
||||
|
||||
/* All others are valid exceptions */
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Depth first search: Attempt to go down another level in the
|
||||
* namespace if we are allowed to. Don't go any further if we have
|
||||
* reached the caller specified maximum depth or if the user
|
||||
* function has specified that the maximum depth has been reached.
|
||||
*/
|
||||
if (!node_previously_visited &&
|
||||
(level < max_depth) && (status != AE_CTRL_DEPTH)) {
|
||||
if (child_node->child) {
|
||||
|
||||
/* There is at least one child of this node, visit it */
|
||||
|
||||
level++;
|
||||
parent_node = child_node;
|
||||
child_node =
|
||||
acpi_ns_get_next_node(parent_node, NULL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* No more children, re-visit this node */
|
||||
|
||||
if (!node_previously_visited) {
|
||||
node_previously_visited = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No more children, visit peers */
|
||||
|
||||
child_node = acpi_ns_get_next_node(parent_node, child_node);
|
||||
if (child_node) {
|
||||
node_previously_visited = FALSE;
|
||||
}
|
||||
|
||||
/* Found next child, get the type if we are not searching for ANY */
|
||||
/* No peers, re-visit parent */
|
||||
|
||||
if (type != ACPI_TYPE_ANY) {
|
||||
child_type = child_node->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore all temporary namespace nodes (created during control
|
||||
* method execution) unless told otherwise. These temporary nodes
|
||||
* can cause a race condition because they can be deleted during
|
||||
* the execution of the user function (if the namespace is
|
||||
* unlocked before invocation of the user function.) Only the
|
||||
* debugger namespace dump will examine the temporary nodes.
|
||||
*/
|
||||
if ((child_node->flags & ANOBJ_TEMPORARY) &&
|
||||
!(flags & ACPI_NS_WALK_TEMP_NODES)) {
|
||||
status = AE_CTRL_DEPTH;
|
||||
}
|
||||
|
||||
/* Type must match requested type */
|
||||
|
||||
else if (child_type == type) {
|
||||
/*
|
||||
* Found a matching node, invoke the user callback function.
|
||||
* Unlock the namespace if flag is set.
|
||||
*/
|
||||
if (flags & ACPI_NS_WALK_UNLOCK) {
|
||||
mutex_status =
|
||||
acpi_ut_release_mutex
|
||||
(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(mutex_status)) {
|
||||
return_ACPI_STATUS
|
||||
(mutex_status);
|
||||
}
|
||||
}
|
||||
|
||||
status =
|
||||
user_function(child_node, level, context,
|
||||
return_value);
|
||||
|
||||
if (flags & ACPI_NS_WALK_UNLOCK) {
|
||||
mutex_status =
|
||||
acpi_ut_acquire_mutex
|
||||
(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(mutex_status)) {
|
||||
return_ACPI_STATUS
|
||||
(mutex_status);
|
||||
}
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case AE_OK:
|
||||
case AE_CTRL_DEPTH:
|
||||
|
||||
/* Just keep going */
|
||||
break;
|
||||
|
||||
case AE_CTRL_TERMINATE:
|
||||
|
||||
/* Exit now, with OK status */
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
default:
|
||||
|
||||
/* All others are valid exceptions */
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Depth first search: Attempt to go down another level in the
|
||||
* namespace if we are allowed to. Don't go any further if we have
|
||||
* reached the caller specified maximum depth or if the user
|
||||
* function has specified that the maximum depth has been reached.
|
||||
*/
|
||||
if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
|
||||
if (child_node->child) {
|
||||
|
||||
/* There is at least one child of this node, visit it */
|
||||
|
||||
level++;
|
||||
parent_node = child_node;
|
||||
child_node = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
else {
|
||||
/*
|
||||
* No more children of this node (acpi_ns_get_next_node failed), go
|
||||
* back upwards in the namespace tree to the node's parent.
|
||||
@@ -324,6 +356,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
|
||||
level--;
|
||||
child_node = parent_node;
|
||||
parent_node = acpi_ns_get_parent_node(parent_node);
|
||||
|
||||
node_previously_visited = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -433,8 +433,11 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
|
||||
* PARAMETERS: Type - acpi_object_type to search for
|
||||
* start_object - Handle in namespace where search begins
|
||||
* max_depth - Depth to which search is to reach
|
||||
* user_function - Called when an object of "Type" is found
|
||||
* Context - Passed to user function
|
||||
* pre_order_visit - Called during tree pre-order visit
|
||||
* when an object of "Type" is found
|
||||
* post_order_visit - Called during tree post-order visit
|
||||
* when an object of "Type" is found
|
||||
* Context - Passed to user function(s) above
|
||||
* return_value - Location where return value of
|
||||
* user_function is put if terminated early
|
||||
*
|
||||
@@ -443,16 +446,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
|
||||
*
|
||||
* DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
|
||||
* starting (and ending) at the object specified by start_handle.
|
||||
* The user_function is called whenever an object that matches
|
||||
* the type parameter is found. If the user function returns
|
||||
* The callback function is called whenever an object that matches
|
||||
* the type parameter is found. If the callback function returns
|
||||
* a non-zero value, the search is terminated immediately and this
|
||||
* value is returned to the caller.
|
||||
*
|
||||
* The point of this procedure is to provide a generic namespace
|
||||
* walk routine that can be called from multiple places to
|
||||
* provide multiple services; the User Function can be tailored
|
||||
* to each task, whether it is a print function, a compare
|
||||
* function, etc.
|
||||
* provide multiple services; the callback function(s) can be
|
||||
* tailored to each task, whether it is a print function,
|
||||
* a compare function, etc.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@@ -460,7 +463,8 @@ acpi_status
|
||||
acpi_walk_namespace(acpi_object_type type,
|
||||
acpi_handle start_object,
|
||||
u32 max_depth,
|
||||
acpi_walk_callback user_function,
|
||||
acpi_walk_callback pre_order_visit,
|
||||
acpi_walk_callback post_order_visit,
|
||||
void *context, void **return_value)
|
||||
{
|
||||
acpi_status status;
|
||||
@@ -469,7 +473,8 @@ acpi_walk_namespace(acpi_object_type type,
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) {
|
||||
if ((type > ACPI_TYPE_LOCAL_MAX) ||
|
||||
(!max_depth) || (!pre_order_visit && !post_order_visit)) {
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -501,8 +506,9 @@ acpi_walk_namespace(acpi_object_type type,
|
||||
}
|
||||
|
||||
status = acpi_ns_walk_namespace(type, start_object, max_depth,
|
||||
ACPI_NS_WALK_UNLOCK, user_function,
|
||||
context, return_value);
|
||||
ACPI_NS_WALK_UNLOCK, pre_order_visit,
|
||||
post_order_visit, context,
|
||||
return_value);
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
@@ -681,8 +687,8 @@ acpi_get_devices(const char *HID,
|
||||
|
||||
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
|
||||
acpi_ns_get_device_callback, &info,
|
||||
return_value);
|
||||
acpi_ns_get_device_callback, NULL,
|
||||
&info, return_value);
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op, acpi_status status);
|
||||
|
||||
static void
|
||||
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
|
||||
acpi_ps_link_module_code(union acpi_parse_object *parent_op,
|
||||
u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
*/
|
||||
if (walk_state->pass_number ==
|
||||
ACPI_IMODE_LOAD_PASS1) {
|
||||
acpi_ps_link_module_code(aml_op_start,
|
||||
walk_state->
|
||||
acpi_ps_link_module_code(op->common.
|
||||
parent,
|
||||
aml_op_start,
|
||||
(u32)
|
||||
(walk_state->
|
||||
parser_state.
|
||||
pkg_end -
|
||||
aml_op_start,
|
||||
aml_op_start),
|
||||
walk_state->
|
||||
owner_id);
|
||||
}
|
||||
@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
*
|
||||
* FUNCTION: acpi_ps_link_module_code
|
||||
*
|
||||
* PARAMETERS: aml_start - Pointer to the AML
|
||||
* PARAMETERS: parent_op - Parent parser op
|
||||
* aml_start - Pointer to the AML
|
||||
* aml_length - Length of executable AML
|
||||
* owner_id - owner_id of module level code
|
||||
*
|
||||
@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
|
||||
acpi_ps_link_module_code(union acpi_parse_object *parent_op,
|
||||
u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
|
||||
{
|
||||
union acpi_operand_object *prev;
|
||||
union acpi_operand_object *next;
|
||||
union acpi_operand_object *method_obj;
|
||||
struct acpi_namespace_node *parent_node;
|
||||
|
||||
/* Get the tail of the list */
|
||||
|
||||
@@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent_op->common.node) {
|
||||
parent_node = parent_op->common.node;
|
||||
} else {
|
||||
parent_node = acpi_gbl_root_node;
|
||||
}
|
||||
|
||||
method_obj->method.aml_start = aml_start;
|
||||
method_obj->method.aml_length = aml_length;
|
||||
method_obj->method.owner_id = owner_id;
|
||||
method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
|
||||
|
||||
/*
|
||||
* Save the parent node in next_object. This is cheating, but we
|
||||
* don't want to expand the method object.
|
||||
*/
|
||||
method_obj->method.next_object =
|
||||
ACPI_CAST_PTR(union acpi_operand_object, parent_node);
|
||||
|
||||
if (!prev) {
|
||||
acpi_gbl_module_code_list = method_obj;
|
||||
} else {
|
||||
|
||||
@@ -610,17 +610,13 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
|
||||
implicit_return_obj) {
|
||||
previous_walk_state->
|
||||
implicit_return_obj =
|
||||
acpi_ut_create_internal_object
|
||||
(ACPI_TYPE_INTEGER);
|
||||
acpi_ut_create_integer_object
|
||||
((u64) 0);
|
||||
if (!previous_walk_state->
|
||||
implicit_return_obj) {
|
||||
return_ACPI_STATUS
|
||||
(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
previous_walk_state->
|
||||
implicit_return_obj->
|
||||
integer.value = 0;
|
||||
}
|
||||
|
||||
/* Restart the calling control method */
|
||||
|
||||
@@ -306,14 +306,12 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
|
||||
*/
|
||||
if (acpi_gbl_enable_interpreter_slack) {
|
||||
walk_state->implicit_return_obj =
|
||||
acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
acpi_ut_create_integer_object((u64) 0);
|
||||
if (!walk_state->implicit_return_obj) {
|
||||
status = AE_NO_MEMORY;
|
||||
acpi_ds_delete_walk_state(walk_state);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
walk_state->implicit_return_obj->integer.value = 0;
|
||||
}
|
||||
|
||||
/* Parse the AML */
|
||||
|
||||
@@ -1161,3 +1161,45 @@ acpi_ut_predefined_warning(const char *module_name,
|
||||
ACPI_COMMON_MSG_SUFFIX;
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_predefined_info
|
||||
*
|
||||
* PARAMETERS: module_name - Caller's module name (for error output)
|
||||
* line_number - Caller's line number (for error output)
|
||||
* Pathname - Full pathname to the node
|
||||
* node_flags - From Namespace node for the method/object
|
||||
* Format - Printf format string + additional args
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Info messages for the predefined validation module. Messages
|
||||
* are only emitted the first time a problem with a particular
|
||||
* method/object is detected. This prevents a flood of
|
||||
* messages for methods that are repeatedly evaluated.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void ACPI_INTERNAL_VAR_XFACE
|
||||
acpi_ut_predefined_info(const char *module_name,
|
||||
u32 line_number,
|
||||
char *pathname, u8 node_flags, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
/*
|
||||
* Warning messages for this method/object will be disabled after the
|
||||
* first time a validation fails or an object is successfully repaired.
|
||||
*/
|
||||
if (node_flags & ANOBJ_EVALUATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_os_printf("ACPI Info for %s: ", pathname);
|
||||
|
||||
va_start(args, format);
|
||||
acpi_os_vprintf(format, args);
|
||||
ACPI_COMMON_MSG_SUFFIX;
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -188,6 +188,35 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count)
|
||||
return_PTR(package_desc);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_create_integer_object
|
||||
*
|
||||
* PARAMETERS: initial_value - Initial value for the integer
|
||||
*
|
||||
* RETURN: Pointer to a new Integer object, null on failure
|
||||
*
|
||||
* DESCRIPTION: Create an initialized integer object
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
union acpi_operand_object *acpi_ut_create_integer_object(u64 initial_value)
|
||||
{
|
||||
union acpi_operand_object *integer_desc;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_create_integer_object);
|
||||
|
||||
/* Create and initialize a new integer object */
|
||||
|
||||
integer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
|
||||
if (!integer_desc) {
|
||||
return_PTR(NULL);
|
||||
}
|
||||
|
||||
integer_desc->integer.value = initial_value;
|
||||
return_PTR(integer_desc);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_create_buffer_object
|
||||
|
||||
@@ -258,7 +258,7 @@ static int __init acpi_container_init(void)
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
container_walk_namespace_cb, &action, NULL);
|
||||
container_walk_namespace_cb, NULL, &action, NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -271,7 +271,7 @@ static void __exit acpi_container_exit(void)
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
container_walk_namespace_cb, &action, NULL);
|
||||
container_walk_namespace_cb, NULL, &action, NULL);
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_container_driver);
|
||||
|
||||
|
||||
@@ -1030,8 +1030,8 @@ static int dock_add(acpi_handle handle)
|
||||
|
||||
/* Find dependent devices */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_dock_devices, dock_station,
|
||||
NULL);
|
||||
ACPI_UINT32_MAX, find_dock_devices, NULL,
|
||||
dock_station, NULL);
|
||||
|
||||
/* add the dock station as a device dependent on itself */
|
||||
dd = alloc_dock_dependent_device(handle);
|
||||
@@ -1127,11 +1127,11 @@ static int __init dock_init(void)
|
||||
|
||||
/* look for a dock station */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_dock, NULL, NULL);
|
||||
ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL);
|
||||
|
||||
/* look for bay */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_bay, NULL, NULL);
|
||||
ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL);
|
||||
if (!dock_station_count) {
|
||||
printk(KERN_INFO PREFIX "No dock devices found.\n");
|
||||
return 0;
|
||||
|
||||
@@ -820,7 +820,7 @@ static int acpi_ec_add(struct acpi_device *device)
|
||||
|
||||
/* Find and register all query methods */
|
||||
acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
|
||||
acpi_ec_register_query_methods, ec, NULL);
|
||||
acpi_ec_register_query_methods, NULL, ec, NULL);
|
||||
|
||||
if (!first_ec)
|
||||
first_ec = ec;
|
||||
|
||||
@@ -113,7 +113,7 @@ acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address)
|
||||
if (!parent)
|
||||
return NULL;
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, parent,
|
||||
1, do_acpi_find_child, &find, NULL);
|
||||
1, do_acpi_find_child, NULL, &find, NULL);
|
||||
return find.handle;
|
||||
}
|
||||
|
||||
|
||||
135
drivers/acpi/hest.c
Normal file
135
drivers/acpi/hest.c
Normal file
@@ -0,0 +1,135 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p)
|
||||
{
|
||||
return sizeof(*p) +
|
||||
(sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
|
||||
}
|
||||
|
||||
static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p)
|
||||
{
|
||||
return sizeof(*p) +
|
||||
(sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
|
||||
}
|
||||
|
||||
static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p)
|
||||
{
|
||||
return sizeof(*p);
|
||||
}
|
||||
|
||||
static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p)
|
||||
{
|
||||
return sizeof(*p);
|
||||
}
|
||||
|
||||
static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci)
|
||||
{
|
||||
return (0 == pci_domain_nr(pci->bus) &&
|
||||
p->bus == pci->bus->number &&
|
||||
p->device == PCI_SLOT(pci->devfn) &&
|
||||
p->function == PCI_FUNC(pci->devfn));
|
||||
}
|
||||
|
||||
static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first)
|
||||
{
|
||||
struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header);
|
||||
unsigned long rc=0;
|
||||
u8 pcie_type = 0;
|
||||
u8 bridge = 0;
|
||||
switch (type) {
|
||||
case ACPI_HEST_TYPE_AER_ROOT_PORT:
|
||||
rc = sizeof(struct acpi_hest_aer_root);
|
||||
pcie_type = PCI_EXP_TYPE_ROOT_PORT;
|
||||
break;
|
||||
case ACPI_HEST_TYPE_AER_ENDPOINT:
|
||||
rc = sizeof(struct acpi_hest_aer);
|
||||
pcie_type = PCI_EXP_TYPE_ENDPOINT;
|
||||
break;
|
||||
case ACPI_HEST_TYPE_AER_BRIDGE:
|
||||
rc = sizeof(struct acpi_hest_aer_bridge);
|
||||
if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE)
|
||||
bridge = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p->flags & ACPI_HEST_GLOBAL) {
|
||||
if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge)
|
||||
*firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
|
||||
}
|
||||
else
|
||||
if (hest_match_pci(p, pci))
|
||||
*firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci)
|
||||
{
|
||||
struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader;
|
||||
void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */
|
||||
struct acpi_hest_header *hdr = p;
|
||||
|
||||
int i;
|
||||
int firmware_first = 0;
|
||||
static unsigned char printed_unused = 0;
|
||||
static unsigned char printed_reserved = 0;
|
||||
|
||||
for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) {
|
||||
switch (hdr->type) {
|
||||
case ACPI_HEST_TYPE_IA32_CHECK:
|
||||
p += parse_acpi_hest_ia_machine_check(p);
|
||||
break;
|
||||
case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
|
||||
p += parse_acpi_hest_ia_corrected(p);
|
||||
break;
|
||||
case ACPI_HEST_TYPE_IA32_NMI:
|
||||
p += parse_acpi_hest_ia_nmi(p);
|
||||
break;
|
||||
/* These three should never appear */
|
||||
case ACPI_HEST_TYPE_NOT_USED3:
|
||||
case ACPI_HEST_TYPE_NOT_USED4:
|
||||
case ACPI_HEST_TYPE_NOT_USED5:
|
||||
if (!printed_unused) {
|
||||
printk(KERN_DEBUG PREFIX
|
||||
"HEST Error Source list contains an obsolete type (%d).\n", hdr->type);
|
||||
printed_unused = 1;
|
||||
}
|
||||
break;
|
||||
case ACPI_HEST_TYPE_AER_ROOT_PORT:
|
||||
case ACPI_HEST_TYPE_AER_ENDPOINT:
|
||||
case ACPI_HEST_TYPE_AER_BRIDGE:
|
||||
p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first);
|
||||
break;
|
||||
case ACPI_HEST_TYPE_GENERIC_ERROR:
|
||||
p += parse_acpi_hest_generic(p);
|
||||
break;
|
||||
/* These should never appear either */
|
||||
case ACPI_HEST_TYPE_RESERVED:
|
||||
default:
|
||||
if (!printed_reserved) {
|
||||
printk(KERN_DEBUG PREFIX
|
||||
"HEST Error Source list contains a reserved type (%d).\n", hdr->type);
|
||||
printed_reserved = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return firmware_first;
|
||||
}
|
||||
|
||||
int acpi_hest_firmware_first_pci(struct pci_dev *pci)
|
||||
{
|
||||
acpi_status status = AE_NOT_FOUND;
|
||||
struct acpi_table_header *hest = NULL;
|
||||
status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);
|
||||
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
if (acpi_hest_firmware_first(hest, pci)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci);
|
||||
@@ -283,22 +283,24 @@ acpi_table_parse_srat(enum acpi_srat_type id,
|
||||
|
||||
int __init acpi_numa_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* SRAT: Static Resource Affinity Table */
|
||||
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
|
||||
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
|
||||
acpi_parse_x2apic_affinity, NR_CPUS);
|
||||
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
|
||||
acpi_parse_processor_affinity, NR_CPUS);
|
||||
acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
|
||||
acpi_parse_memory_affinity,
|
||||
NR_NODE_MEMBLKS);
|
||||
ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
|
||||
acpi_parse_memory_affinity,
|
||||
NR_NODE_MEMBLKS);
|
||||
}
|
||||
|
||||
/* SLIT: System Locality Information Table */
|
||||
acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
|
||||
|
||||
acpi_numa_arch_fixup();
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int acpi_get_pxm(acpi_handle h)
|
||||
|
||||
@@ -219,12 +219,12 @@ walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
|
||||
dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number);
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
user_function, &child_context, NULL);
|
||||
user_function, NULL, &child_context, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
walk_p2p_bridge, &child_context, NULL);
|
||||
walk_p2p_bridge, NULL, &child_context, NULL);
|
||||
out:
|
||||
pci_dev_put(dev);
|
||||
return AE_OK;
|
||||
@@ -277,12 +277,12 @@ walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
|
||||
|
||||
dbg("root bridge walk, pci_bus = %x\n", pci_bus->number);
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
user_function, &context, NULL);
|
||||
user_function, NULL, &context, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
walk_p2p_bridge, &context, NULL);
|
||||
walk_p2p_bridge, NULL, &context, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
err("%s: walk_p2p_bridge failure - %d\n", __func__, status);
|
||||
|
||||
|
||||
@@ -1102,7 +1102,7 @@ void acpi_processor_install_hotplug_notify(void)
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
processor_walk_namespace_cb, &action, NULL);
|
||||
processor_walk_namespace_cb, NULL, &action, NULL);
|
||||
#endif
|
||||
register_hotcpu_notifier(&acpi_cpu_notifier);
|
||||
}
|
||||
@@ -1115,7 +1115,7 @@ void acpi_processor_uninstall_hotplug_notify(void)
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
|
||||
ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX,
|
||||
processor_walk_namespace_cb, &action, NULL);
|
||||
processor_walk_namespace_cb, NULL, &action, NULL);
|
||||
#endif
|
||||
unregister_hotcpu_notifier(&acpi_cpu_notifier);
|
||||
}
|
||||
|
||||
@@ -167,6 +167,19 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
|
||||
return cpufreq_update_policy(pr->id);
|
||||
}
|
||||
|
||||
int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
|
||||
{
|
||||
struct acpi_processor *pr;
|
||||
|
||||
pr = per_cpu(processors, cpu);
|
||||
if (!pr || !pr->performance || !pr->performance->state_count)
|
||||
return -ENODEV;
|
||||
*limit = pr->performance->states[pr->performance_platform_limit].
|
||||
core_frequency * 1000;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_processor_get_bios_limit);
|
||||
|
||||
void acpi_processor_ppc_init(void)
|
||||
{
|
||||
if (!cpufreq_register_notifier
|
||||
|
||||
@@ -1332,7 +1332,7 @@ static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
|
||||
status = acpi_bus_check_add(handle, 0, ops, &device);
|
||||
if (ACPI_SUCCESS(status))
|
||||
acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
|
||||
acpi_bus_check_add, ops, &device);
|
||||
acpi_bus_check_add, NULL, ops, &device);
|
||||
|
||||
if (child)
|
||||
*child = device;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* video_detect.c:
|
||||
* Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c
|
||||
* There a Linux specific (Spec does not provide a HID for video devices) is
|
||||
* assinged
|
||||
* assigned
|
||||
*
|
||||
* After PCI devices are glued with ACPI devices
|
||||
* acpi_get_pci_dev() can be called to identify ACPI graphics
|
||||
@@ -83,16 +83,16 @@ long acpi_is_video_device(struct acpi_device *device)
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
/* Does this device able to support video switching ? */
|
||||
/* Is this device able to support video switching ? */
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) ||
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
|
||||
video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
|
||||
|
||||
/* Does this device able to retrieve a video ROM ? */
|
||||
/* Is this device able to retrieve a video ROM ? */
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy)))
|
||||
video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
|
||||
|
||||
/* Does this device able to configure which video head to be POSTed ? */
|
||||
/* Is this device able to configure which video head to be POSTed ? */
|
||||
if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) &&
|
||||
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy)))
|
||||
@@ -101,7 +101,7 @@ long acpi_is_video_device(struct acpi_device *device)
|
||||
/* Only check for backlight functionality if one of the above hit. */
|
||||
if (video_caps)
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle,
|
||||
ACPI_UINT32_MAX, acpi_backlight_cap_match,
|
||||
ACPI_UINT32_MAX, acpi_backlight_cap_match, NULL,
|
||||
&video_caps, NULL);
|
||||
|
||||
return video_caps;
|
||||
@@ -137,7 +137,7 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
*
|
||||
* if NULL is passed as argument all ACPI devices are enumerated and
|
||||
* all graphics capabilities of physically present devices are
|
||||
* summerized and returned. This is cached and done only once.
|
||||
* summarized and returned. This is cached and done only once.
|
||||
*/
|
||||
long acpi_video_get_capabilities(acpi_handle graphics_handle)
|
||||
{
|
||||
@@ -151,7 +151,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
|
||||
if (!graphics_handle) {
|
||||
/* Only do the global walk through all graphics devices once */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_video,
|
||||
ACPI_UINT32_MAX, find_video, NULL,
|
||||
&caps, NULL);
|
||||
/* There might be boot param flags set already... */
|
||||
acpi_video_support |= caps;
|
||||
@@ -173,7 +173,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
|
||||
return 0;
|
||||
}
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle,
|
||||
ACPI_UINT32_MAX, find_video,
|
||||
ACPI_UINT32_MAX, find_video, NULL,
|
||||
&caps, NULL);
|
||||
}
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
menuconfig ATA
|
||||
tristate "Serial ATA (prod) and Parallel ATA (experimental) drivers"
|
||||
tristate "Serial ATA and Parallel ATA drivers"
|
||||
depends on HAS_IOMEM
|
||||
depends on BLOCK
|
||||
depends on !(M32R || M68K) || BROKEN
|
||||
@@ -374,8 +374,8 @@ config PATA_HPT366
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_HPT37X
|
||||
tristate "HPT 370/370A/371/372/374/302 PATA support (Experimental)"
|
||||
depends on PCI && EXPERIMENTAL
|
||||
tristate "HPT 370/370A/371/372/374/302 PATA support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for the majority of the later HPT
|
||||
PATA controllers via the new ATA layer.
|
||||
@@ -383,8 +383,8 @@ config PATA_HPT37X
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_HPT3X2N
|
||||
tristate "HPT 372N/302N PATA support (Experimental)"
|
||||
depends on PCI && EXPERIMENTAL
|
||||
tristate "HPT 372N/302N PATA support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for the N variant HPT PATA
|
||||
controllers via the new ATA layer
|
||||
@@ -401,7 +401,7 @@ config PATA_HPT3X3
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_HPT3X3_DMA
|
||||
bool "HPT 343/363 DMA support (Experimental)"
|
||||
bool "HPT 343/363 DMA support"
|
||||
depends on PATA_HPT3X3
|
||||
help
|
||||
This option enables DMA support for the HPT343/363
|
||||
@@ -510,8 +510,8 @@ config PATA_NETCELL
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_NINJA32
|
||||
tristate "Ninja32/Delkin Cardbus ATA support (Experimental)"
|
||||
depends on PCI && EXPERIMENTAL
|
||||
tristate "Ninja32/Delkin Cardbus ATA support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for the Ninja32, Delkin and
|
||||
possibly other brands of Cardbus ATA adapter
|
||||
@@ -573,6 +573,14 @@ config PATA_PCMCIA
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_PDC2027X
|
||||
tristate "Promise PATA 2027x support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for Promise PATA pdc20268 to pdc20277 host adapters.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_PDC_OLD
|
||||
tristate "Older Promise PATA controller support"
|
||||
depends on PCI
|
||||
@@ -643,14 +651,6 @@ config PATA_SERVERWORKS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_PDC2027X
|
||||
tristate "Promise PATA 2027x support"
|
||||
depends on PCI
|
||||
help
|
||||
This option enables support for Promise PATA pdc20268 to pdc20277 host adapters.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_SIL680
|
||||
tristate "CMD / Silicon Image 680 PATA support"
|
||||
depends on PCI
|
||||
@@ -667,6 +667,15 @@ config PATA_SIS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_TOSHIBA
|
||||
tristate "Toshiba Piccolo support (Experimental)"
|
||||
depends on PCI && EXPERIMENTAL
|
||||
help
|
||||
Support for the Toshiba Piccolo controllers. Currently only the
|
||||
primary channel is supported by this driver.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_VIA
|
||||
tristate "VIA PATA support"
|
||||
depends on PCI
|
||||
@@ -781,5 +790,15 @@ config PATA_BF54X
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_MACIO
|
||||
tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE"
|
||||
depends on PPC_PMAC
|
||||
help
|
||||
Most IDE capable PowerMacs have IDE busses driven by a variant
|
||||
of this controller which is part of the Apple chipset used on
|
||||
most PowerMac models. Some models have multiple busses using
|
||||
different chipsets, though generally, MacIO is one of them.
|
||||
|
||||
|
||||
endif # ATA_SFF
|
||||
endif # ATA
|
||||
|
||||
@@ -18,6 +18,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o
|
||||
obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
|
||||
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
|
||||
obj-$(CONFIG_SATA_FSL) += sata_fsl.o
|
||||
obj-$(CONFIG_PATA_MACIO) += pata_macio.o
|
||||
|
||||
obj-$(CONFIG_PATA_ALI) += pata_ali.o
|
||||
obj-$(CONFIG_PATA_AMD) += pata_amd.o
|
||||
@@ -63,6 +64,7 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
|
||||
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
|
||||
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
|
||||
obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
|
||||
obj-$(CONFIG_PATA_TOSHIBA) += pata_piccolo.o
|
||||
obj-$(CONFIG_PATA_VIA) += pata_via.o
|
||||
obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
|
||||
obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
|
||||
|
||||
@@ -113,6 +113,7 @@ enum {
|
||||
board_ahci_mcp65 = 6,
|
||||
board_ahci_nopmp = 7,
|
||||
board_ahci_yesncq = 8,
|
||||
board_ahci_nosntf = 9,
|
||||
|
||||
/* global controller registers */
|
||||
HOST_CAP = 0x00, /* host capabilities */
|
||||
@@ -235,6 +236,7 @@ enum {
|
||||
AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
|
||||
AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
|
||||
link offline */
|
||||
AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */
|
||||
|
||||
/* ap->flags bits */
|
||||
|
||||
@@ -508,7 +510,7 @@ static const struct ata_port_info ahci_port_info[] = {
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
/* board_ahci_yesncq */
|
||||
[board_ahci_yesncq] =
|
||||
{
|
||||
AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
|
||||
.flags = AHCI_FLAG_COMMON,
|
||||
@@ -516,6 +518,14 @@ static const struct ata_port_info ahci_port_info[] = {
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
[board_ahci_nosntf] =
|
||||
{
|
||||
AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF),
|
||||
.flags = AHCI_FLAG_COMMON,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
@@ -531,7 +541,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
|
||||
{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
|
||||
{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
|
||||
{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
|
||||
{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
|
||||
@@ -849,6 +859,12 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
|
||||
cap &= ~HOST_CAP_PMP;
|
||||
}
|
||||
|
||||
if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"controller can't do SNTF, turning off CAP_SNTF\n");
|
||||
cap &= ~HOST_CAP_SNTF;
|
||||
}
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
|
||||
port_map != 1) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
@@ -2988,6 +3004,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
|
||||
return -ENODEV;
|
||||
|
||||
/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
|
||||
* At the moment, we can only use the AHCI mode. Let the users know
|
||||
* that for SAS drives they're out of luck.
|
||||
*/
|
||||
if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
|
||||
dev_printk(KERN_INFO, &pdev->dev, "PDC42819 "
|
||||
"can only drive SATA devices with this driver\n");
|
||||
|
||||
/* acquire resources */
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
|
||||
@@ -168,9 +168,12 @@ static struct pci_device_id ata_generic[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
|
||||
#if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), },
|
||||
#endif
|
||||
/* Must come last. If you add entries adjust this table appropriately */
|
||||
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
|
||||
{ 0, },
|
||||
|
||||
@@ -599,7 +599,7 @@ static const struct ich_laptop ich_laptop[] = {
|
||||
{ 0x27DF, 0x1028, 0x02b0 }, /* ICH7 on unknown Dell */
|
||||
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
|
||||
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
|
||||
{ 0x27DF, 0x103C, 0x361a }, /* ICH7 on unkown HP */
|
||||
{ 0x27DF, 0x103C, 0x361a }, /* ICH7 on unknown HP */
|
||||
{ 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
|
||||
{ 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */
|
||||
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */
|
||||
@@ -869,10 +869,10 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
|
||||
(timings[pio][1] << 8);
|
||||
}
|
||||
|
||||
if (ap->udma_mask) {
|
||||
if (ap->udma_mask)
|
||||
udma_enable &= ~(1 << devid);
|
||||
pci_write_config_word(dev, master_port, master_data);
|
||||
}
|
||||
|
||||
pci_write_config_word(dev, master_port, master_data);
|
||||
}
|
||||
/* Don't scribble on 0x48 if the controller does not support UDMA */
|
||||
if (ap->udma_mask)
|
||||
|
||||
@@ -807,12 +807,11 @@ static int ata_acpi_exec_tfs(struct ata_device *dev, int *nr_executed)
|
||||
* EH context.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno on failure.
|
||||
* 0 on success, -ENOENT if _SDD doesn't exist, -errno on failure.
|
||||
*/
|
||||
static int ata_acpi_push_id(struct ata_device *dev)
|
||||
{
|
||||
struct ata_port *ap = dev->link->ap;
|
||||
int err;
|
||||
acpi_status status;
|
||||
struct acpi_object_list input;
|
||||
union acpi_object in_params[1];
|
||||
@@ -835,12 +834,16 @@ static int ata_acpi_push_id(struct ata_device *dev)
|
||||
status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);
|
||||
swap_buf_le16(dev->id, ATA_ID_WORDS);
|
||||
|
||||
err = ACPI_FAILURE(status) ? -EIO : 0;
|
||||
if (err < 0)
|
||||
if (status == AE_NOT_FOUND)
|
||||
return -ENOENT;
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ata_dev_printk(dev, KERN_WARNING,
|
||||
"ACPI _SDD failed (AE 0x%x)\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -971,7 +974,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
|
||||
/* do _SDD if SATA */
|
||||
if (acpi_sata) {
|
||||
rc = ata_acpi_push_id(dev);
|
||||
if (rc)
|
||||
if (rc && rc != -ENOENT)
|
||||
goto acpi_err;
|
||||
}
|
||||
|
||||
|
||||
@@ -6616,6 +6616,13 @@ static int __init ata_init(void)
|
||||
{
|
||||
ata_parse_force_param();
|
||||
|
||||
/*
|
||||
* FIXME: In UP case, there is only one workqueue thread and if you
|
||||
* have more than one PIO device, latency is bloody awful, with
|
||||
* occasional multi-second "hiccups" as one PIO device waits for
|
||||
* another. It's an ugly wart that users DO occasionally complain
|
||||
* about; luckily most users have at most one PIO polled device.
|
||||
*/
|
||||
ata_wq = create_workqueue("ata");
|
||||
if (!ata_wq)
|
||||
goto free_force_tbl;
|
||||
|
||||
@@ -110,6 +110,13 @@ static const unsigned long ata_eh_identify_timeouts[] = {
|
||||
ULONG_MAX,
|
||||
};
|
||||
|
||||
static const unsigned long ata_eh_flush_timeouts[] = {
|
||||
15000, /* be generous with flush */
|
||||
15000, /* ditto */
|
||||
30000, /* and even more generous */
|
||||
ULONG_MAX,
|
||||
};
|
||||
|
||||
static const unsigned long ata_eh_other_timeouts[] = {
|
||||
5000, /* same rationale as identify timeout */
|
||||
10000, /* ditto */
|
||||
@@ -147,6 +154,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
|
||||
.timeouts = ata_eh_other_timeouts, },
|
||||
{ .commands = CMDS(ATA_CMD_INIT_DEV_PARAMS),
|
||||
.timeouts = ata_eh_other_timeouts, },
|
||||
{ .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT),
|
||||
.timeouts = ata_eh_flush_timeouts },
|
||||
};
|
||||
#undef CMDS
|
||||
|
||||
@@ -3112,6 +3121,82 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_eh_maybe_retry_flush - Retry FLUSH if necessary
|
||||
* @dev: ATA device which may need FLUSH retry
|
||||
*
|
||||
* If @dev failed FLUSH, it needs to be reported upper layer
|
||||
* immediately as it means that @dev failed to remap and already
|
||||
* lost at least a sector and further FLUSH retrials won't make
|
||||
* any difference to the lost sector. However, if FLUSH failed
|
||||
* for other reasons, for example transmission error, FLUSH needs
|
||||
* to be retried.
|
||||
*
|
||||
* This function determines whether FLUSH failure retry is
|
||||
* necessary and performs it if so.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 if EH can continue, -errno if EH needs to be repeated.
|
||||
*/
|
||||
static int ata_eh_maybe_retry_flush(struct ata_device *dev)
|
||||
{
|
||||
struct ata_link *link = dev->link;
|
||||
struct ata_port *ap = link->ap;
|
||||
struct ata_queued_cmd *qc;
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
int rc = 0;
|
||||
|
||||
/* did flush fail for this device? */
|
||||
if (!ata_tag_valid(link->active_tag))
|
||||
return 0;
|
||||
|
||||
qc = __ata_qc_from_tag(ap, link->active_tag);
|
||||
if (qc->dev != dev || (qc->tf.command != ATA_CMD_FLUSH_EXT &&
|
||||
qc->tf.command != ATA_CMD_FLUSH))
|
||||
return 0;
|
||||
|
||||
/* if the device failed it, it should be reported to upper layers */
|
||||
if (qc->err_mask & AC_ERR_DEV)
|
||||
return 0;
|
||||
|
||||
/* flush failed for some other reason, give it another shot */
|
||||
ata_tf_init(dev, &tf);
|
||||
|
||||
tf.command = qc->tf.command;
|
||||
tf.flags |= ATA_TFLAG_DEVICE;
|
||||
tf.protocol = ATA_PROT_NODATA;
|
||||
|
||||
ata_dev_printk(dev, KERN_WARNING, "retrying FLUSH 0x%x Emask 0x%x\n",
|
||||
tf.command, qc->err_mask);
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (!err_mask) {
|
||||
/*
|
||||
* FLUSH is complete but there's no way to
|
||||
* successfully complete a failed command from EH.
|
||||
* Making sure retry is allowed at least once and
|
||||
* retrying it should do the trick - whatever was in
|
||||
* the cache is already on the platter and this won't
|
||||
* cause infinite loop.
|
||||
*/
|
||||
qc->scsicmd->allowed = max(qc->scsicmd->allowed, 1);
|
||||
} else {
|
||||
ata_dev_printk(dev, KERN_WARNING, "FLUSH failed Emask 0x%x\n",
|
||||
err_mask);
|
||||
rc = -EIO;
|
||||
|
||||
/* if device failed it, report it to upper layers */
|
||||
if (err_mask & AC_ERR_DEV) {
|
||||
qc->err_mask |= AC_ERR_DEV;
|
||||
qc->result_tf = tf;
|
||||
if (!(ap->pflags & ATA_PFLAG_FROZEN))
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ata_link_nr_enabled(struct ata_link *link)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
@@ -3455,6 +3540,15 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
||||
}
|
||||
}
|
||||
|
||||
/* retry flush if necessary */
|
||||
ata_for_each_dev(dev, link, ALL) {
|
||||
if (dev->class != ATA_DEV_ATA)
|
||||
continue;
|
||||
rc = ata_eh_maybe_retry_flush(dev);
|
||||
if (rc)
|
||||
goto dev_fail;
|
||||
}
|
||||
|
||||
/* configure link power saving */
|
||||
if (ehc->i.action & ATA_EH_LPM)
|
||||
ata_for_each_dev(dev, link, ALL)
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "libata.h"
|
||||
|
||||
@@ -154,8 +155,7 @@ static ssize_t ata_scsi_lpm_put(struct device *dev,
|
||||
*/
|
||||
for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
|
||||
const int len = strlen(link_pm_policy[i].name);
|
||||
if (strncmp(link_pm_policy[i].name, buf, len) == 0 &&
|
||||
buf[len] == '\n') {
|
||||
if (strncmp(link_pm_policy[i].name, buf, len) == 0) {
|
||||
policy = link_pm_policy[i].value;
|
||||
break;
|
||||
}
|
||||
@@ -1208,6 +1208,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
|
||||
* ata_scsi_change_queue_depth - SCSI callback for queue depth config
|
||||
* @sdev: SCSI device to configure queue depth for
|
||||
* @queue_depth: new queue depth
|
||||
* @reason: calling context
|
||||
*
|
||||
* This is libata standard hostt->change_queue_depth callback.
|
||||
* SCSI will call into this callback when user tries to set queue
|
||||
@@ -1219,12 +1220,16 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
|
||||
* RETURNS:
|
||||
* Newly configured queue depth.
|
||||
*/
|
||||
int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
|
||||
int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
|
||||
int reason)
|
||||
{
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth < 1 || queue_depth == sdev->queue_depth)
|
||||
return sdev->queue_depth;
|
||||
|
||||
@@ -1964,6 +1969,7 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
|
||||
0x80, /* page 0x80, unit serial no page */
|
||||
0x83, /* page 0x83, device ident page */
|
||||
0x89, /* page 0x89, ata info page */
|
||||
0xb0, /* page 0xb0, block limits page */
|
||||
0xb1, /* page 0xb1, block device characteristics page */
|
||||
};
|
||||
|
||||
@@ -2085,6 +2091,43 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
|
||||
{
|
||||
u32 min_io_sectors;
|
||||
|
||||
rbuf[1] = 0xb0;
|
||||
rbuf[3] = 0x3c; /* required VPD size with unmap support */
|
||||
|
||||
/*
|
||||
* Optimal transfer length granularity.
|
||||
*
|
||||
* This is always one physical block, but for disks with a smaller
|
||||
* logical than physical sector size we need to figure out what the
|
||||
* latter is.
|
||||
*/
|
||||
if (ata_id_has_large_logical_sectors(args->id))
|
||||
min_io_sectors = ata_id_logical_per_physical_sectors(args->id);
|
||||
else
|
||||
min_io_sectors = 1;
|
||||
put_unaligned_be16(min_io_sectors, &rbuf[6]);
|
||||
|
||||
/*
|
||||
* Optimal unmap granularity.
|
||||
*
|
||||
* The ATA spec doesn't even know about a granularity or alignment
|
||||
* for the TRIM command. We can leave away most of the unmap related
|
||||
* VPD page entries, but we have specifify a granularity to signal
|
||||
* that we support some form of unmap - in thise case via WRITE SAME
|
||||
* with the unmap bit set.
|
||||
*/
|
||||
if (ata_id_has_trim(args->id)) {
|
||||
put_unaligned_be32(65535 * 512 / 8, &rbuf[20]);
|
||||
put_unaligned_be32(1, &rbuf[28]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
|
||||
{
|
||||
int form_factor = ata_id_form_factor(args->id);
|
||||
@@ -2374,6 +2417,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
|
||||
rbuf[13] = log_per_phys;
|
||||
rbuf[14] = (lowest_aligned >> 8) & 0x3f;
|
||||
rbuf[15] = lowest_aligned;
|
||||
|
||||
if (ata_id_has_trim(args->id)) {
|
||||
rbuf[14] |= 0x80; /* TPE */
|
||||
|
||||
if (ata_id_has_zero_after_trim(args->id))
|
||||
rbuf[14] |= 0x40; /* TPRZ */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2896,6 +2946,58 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_taskfile *tf = &qc->tf;
|
||||
struct scsi_cmnd *scmd = qc->scsicmd;
|
||||
struct ata_device *dev = qc->dev;
|
||||
const u8 *cdb = scmd->cmnd;
|
||||
u64 block;
|
||||
u32 n_block;
|
||||
u32 size;
|
||||
void *buf;
|
||||
|
||||
/* we may not issue DMA commands if no DMA mode is set */
|
||||
if (unlikely(!dev->dma_mode))
|
||||
goto invalid_fld;
|
||||
|
||||
if (unlikely(scmd->cmd_len < 16))
|
||||
goto invalid_fld;
|
||||
scsi_16_lba_len(cdb, &block, &n_block);
|
||||
|
||||
/* for now we only support WRITE SAME with the unmap bit set */
|
||||
if (unlikely(!(cdb[1] & 0x8)))
|
||||
goto invalid_fld;
|
||||
|
||||
/*
|
||||
* WRITE SAME always has a sector sized buffer as payload, this
|
||||
* should never be a multiple entry S/G list.
|
||||
*/
|
||||
if (!scsi_sg_count(scmd))
|
||||
goto invalid_fld;
|
||||
|
||||
buf = page_address(sg_page(scsi_sglist(scmd)));
|
||||
size = ata_set_lba_range_entries(buf, 512, block, n_block);
|
||||
|
||||
tf->protocol = ATA_PROT_DMA;
|
||||
tf->hob_feature = 0;
|
||||
tf->feature = ATA_DSM_TRIM;
|
||||
tf->hob_nsect = (size / 512) >> 8;
|
||||
tf->nsect = size / 512;
|
||||
tf->command = ATA_CMD_DSM;
|
||||
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 |
|
||||
ATA_TFLAG_WRITE;
|
||||
|
||||
ata_qc_set_pc_nbytes(qc);
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_fld:
|
||||
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00);
|
||||
/* "Invalid field in cdb" */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_get_xlat_func - check if SCSI to ATA translation is possible
|
||||
* @dev: ATA device
|
||||
@@ -2920,6 +3022,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
|
||||
case WRITE_16:
|
||||
return ata_scsi_rw_xlat;
|
||||
|
||||
case 0x93 /*WRITE_SAME_16*/:
|
||||
return ata_scsi_write_same_xlat;
|
||||
|
||||
case SYNCHRONIZE_CACHE:
|
||||
if (ata_try_flush_cache(dev))
|
||||
return ata_scsi_flush_xlat;
|
||||
@@ -3109,6 +3214,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
|
||||
case 0x89:
|
||||
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
|
||||
break;
|
||||
case 0xb0:
|
||||
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b0);
|
||||
break;
|
||||
case 0xb1:
|
||||
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
|
||||
break;
|
||||
|
||||
@@ -736,7 +736,7 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
|
||||
|
||||
/*
|
||||
* Use io*16_rep() accessors here as well to avoid pointlessly
|
||||
* swapping bytes to and fro on the big endian machines...
|
||||
* swapping bytes to and from on the big endian machines...
|
||||
*/
|
||||
if (rw == READ) {
|
||||
ioread16_rep(data_addr, pad, 1);
|
||||
@@ -776,7 +776,7 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
|
||||
void __iomem *data_addr = ap->ioaddr.data_addr;
|
||||
unsigned int words = buflen >> 2;
|
||||
int slop = buflen & 3;
|
||||
|
||||
|
||||
if (!(ap->pflags & ATA_PFLAG_PIO32))
|
||||
return ata_sff_data_xfer(dev, buf, buflen, rw);
|
||||
|
||||
@@ -795,7 +795,7 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
|
||||
|
||||
/*
|
||||
* Use io*_rep() accessors here as well to avoid pointlessly
|
||||
* swapping bytes to and fro on the big endian machines...
|
||||
* swapping bytes to and from on the big endian machines...
|
||||
*/
|
||||
if (rw == READ) {
|
||||
if (slop < 3)
|
||||
@@ -2384,7 +2384,7 @@ void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||
ap->hsm_task_state = HSM_ST_IDLE;
|
||||
|
||||
if (ap->ioaddr.bmdma_addr)
|
||||
ata_bmdma_stop(qc);
|
||||
ap->ops->bmdma_stop(qc);
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
}
|
||||
|
||||
@@ -453,7 +453,9 @@ static void ali_init_chipset(struct pci_dev *pdev)
|
||||
/* Clear CD-ROM DMA write bit */
|
||||
tmp &= 0x7F;
|
||||
/* Cable and UDMA */
|
||||
pci_write_config_byte(pdev, 0x4B, tmp | 0x09);
|
||||
if (pdev->revision >= 0xc2)
|
||||
tmp |= 0x01;
|
||||
pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
|
||||
/*
|
||||
* CD_ROM DMA on (0x53 bit 0). Enable this even if we want
|
||||
* to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_cmd64x"
|
||||
#define DRV_VERSION "0.2.5"
|
||||
#define DRV_VERSION "0.3.1"
|
||||
|
||||
/*
|
||||
* CMD64x specific registers definition.
|
||||
@@ -254,17 +254,109 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
|
||||
}
|
||||
|
||||
/**
|
||||
* cmd646r1_dma_stop - DMA stop callback
|
||||
* cmd64x_bmdma_stop - DMA stop callback
|
||||
* @qc: Command in progress
|
||||
*
|
||||
* Stub for now while investigating the r1 quirk in the old driver.
|
||||
* Track the completion of live DMA commands and clear the
|
||||
* host->private_data DMA tracking flag as we do.
|
||||
*/
|
||||
|
||||
static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
|
||||
static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
ata_bmdma_stop(qc);
|
||||
WARN_ON(ap->host->private_data != ap);
|
||||
ap->host->private_data = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* cmd64x_qc_defer - Defer logic for chip limits
|
||||
* @qc: queued command
|
||||
*
|
||||
* Decide whether we can issue the command. Called under the host lock.
|
||||
*/
|
||||
|
||||
static int cmd64x_qc_defer(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_host *host = qc->ap->host;
|
||||
struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
|
||||
int rc;
|
||||
int dma = 0;
|
||||
|
||||
/* Apply the ATA rules first */
|
||||
rc = ata_std_qc_defer(qc);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (qc->tf.protocol == ATAPI_PROT_DMA ||
|
||||
qc->tf.protocol == ATA_PROT_DMA)
|
||||
dma = 1;
|
||||
|
||||
/* If the other port is not live then issue the command */
|
||||
if (alt == NULL || !alt->qc_active) {
|
||||
if (dma)
|
||||
host->private_data = qc->ap;
|
||||
return 0;
|
||||
}
|
||||
/* If there is a live DMA command then wait */
|
||||
if (host->private_data != NULL)
|
||||
return ATA_DEFER_PORT;
|
||||
if (dma)
|
||||
/* Cannot overlap our DMA command */
|
||||
return ATA_DEFER_PORT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cmd64x_interrupt - ATA host interrupt handler
|
||||
* @irq: irq line (unused)
|
||||
* @dev_instance: pointer to our ata_host information structure
|
||||
*
|
||||
* Our interrupt handler for PCI IDE devices. Calls
|
||||
* ata_sff_host_intr() for each port that is flagging an IRQ. We cannot
|
||||
* use the defaults as we need to avoid touching status/altstatus during
|
||||
* a DMA.
|
||||
*
|
||||
* LOCKING:
|
||||
* Obtains host lock during operation.
|
||||
*
|
||||
* RETURNS:
|
||||
* IRQ_NONE or IRQ_HANDLED.
|
||||
*/
|
||||
irqreturn_t cmd64x_interrupt(int irq, void *dev_instance)
|
||||
{
|
||||
struct ata_host *host = dev_instance;
|
||||
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||
unsigned int i;
|
||||
unsigned int handled = 0;
|
||||
unsigned long flags;
|
||||
static const u8 irq_reg[2] = { CFR, ARTTIM23 };
|
||||
static const u8 irq_mask[2] = { 1 << 2, 1 << 4 };
|
||||
|
||||
/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap;
|
||||
u8 reg;
|
||||
|
||||
pci_read_config_byte(pdev, irq_reg[i], ®);
|
||||
ap = host->ports[i];
|
||||
if (ap && (reg & irq_mask[i]) &&
|
||||
!(ap->flags & ATA_FLAG_DISABLED)) {
|
||||
struct ata_queued_cmd *qc;
|
||||
|
||||
qc = ata_qc_from_tag(ap, ap->link.active_tag);
|
||||
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
|
||||
(qc->flags & ATA_QCFLAG_ACTIVE))
|
||||
handled |= ata_sff_host_intr(ap, qc);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
static struct scsi_host_template cmd64x_sht = {
|
||||
ATA_BMDMA_SHT(DRV_NAME),
|
||||
};
|
||||
@@ -273,6 +365,8 @@ static const struct ata_port_operations cmd64x_base_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.set_piomode = cmd64x_set_piomode,
|
||||
.set_dmamode = cmd64x_set_dmamode,
|
||||
.bmdma_stop = cmd64x_bmdma_stop,
|
||||
.qc_defer = cmd64x_qc_defer,
|
||||
};
|
||||
|
||||
static struct ata_port_operations cmd64x_port_ops = {
|
||||
@@ -282,7 +376,6 @@ static struct ata_port_operations cmd64x_port_ops = {
|
||||
|
||||
static struct ata_port_operations cmd646r1_port_ops = {
|
||||
.inherits = &cmd64x_base_ops,
|
||||
.bmdma_stop = cmd646r1_bmdma_stop,
|
||||
.cable_detect = ata_cable_40wire,
|
||||
};
|
||||
|
||||
@@ -290,12 +383,11 @@ static struct ata_port_operations cmd648_port_ops = {
|
||||
.inherits = &cmd64x_base_ops,
|
||||
.bmdma_stop = cmd648_bmdma_stop,
|
||||
.cable_detect = cmd648_cable_detect,
|
||||
.qc_defer = ata_std_qc_defer
|
||||
};
|
||||
|
||||
static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
u32 class_rev;
|
||||
|
||||
static const struct ata_port_info cmd_info[6] = {
|
||||
{ /* CMD 643 - no UDMA */
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
@@ -340,40 +432,43 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
|
||||
u8 mrdmode;
|
||||
int rc;
|
||||
struct ata_host *host;
|
||||
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xFF;
|
||||
|
||||
if (id->driver_data == 0) /* 643 */
|
||||
ata_pci_bmdma_clear_simplex(pdev);
|
||||
|
||||
if (pdev->device == PCI_DEVICE_ID_CMD_646) {
|
||||
/* Does UDMA work ? */
|
||||
if (class_rev > 4)
|
||||
if (pdev->revision > 4)
|
||||
ppi[0] = &cmd_info[2];
|
||||
/* Early rev with other problems ? */
|
||||
else if (class_rev == 1)
|
||||
else if (pdev->revision == 1)
|
||||
ppi[0] = &cmd_info[3];
|
||||
}
|
||||
|
||||
|
||||
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
|
||||
pci_read_config_byte(pdev, MRDMODE, &mrdmode);
|
||||
mrdmode &= ~ 0x30; /* IRQ set up */
|
||||
mrdmode |= 0x02; /* Memory read line enable */
|
||||
pci_write_config_byte(pdev, MRDMODE, mrdmode);
|
||||
|
||||
/* Force PIO 0 here.. */
|
||||
|
||||
/* PPC specific fixup copied from old driver */
|
||||
#ifdef CONFIG_PPC
|
||||
pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
|
||||
#endif
|
||||
rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* We use this pointer to track the AP which has DMA running */
|
||||
host->private_data = NULL;
|
||||
|
||||
return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
|
||||
pci_set_master(pdev);
|
||||
return ata_pci_sff_activate_host(host, cmd64x_interrupt, &cmd64x_sht);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
@@ -89,49 +89,13 @@ static void cs5520_set_timings(struct ata_port *ap, struct ata_device *adev, int
|
||||
(cs5520_pio_clocks[pio].assert));
|
||||
}
|
||||
|
||||
/**
|
||||
* cs5520_enable_dma - turn on DMA bits
|
||||
*
|
||||
* Turn on the DMA bits for this disk. Needed because the BIOS probably
|
||||
* has not done the work for us. Belongs in the core SATA code.
|
||||
*/
|
||||
|
||||
static void cs5520_enable_dma(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
/* Set the DMA enable/disable flag */
|
||||
u8 reg = ioread8(ap->ioaddr.bmdma_addr + 0x02);
|
||||
reg |= 1<<(adev->devno + 5);
|
||||
iowrite8(reg, ap->ioaddr.bmdma_addr + 0x02);
|
||||
}
|
||||
|
||||
/**
|
||||
* cs5520_set_dmamode - program DMA timings
|
||||
* @ap: ATA port
|
||||
* @adev: ATA device
|
||||
*
|
||||
* Program the DMA mode timings for the controller according to the pio
|
||||
* clocking table. Note that this device sets the DMA timings to PIO
|
||||
* mode values. This may seem bizarre but the 5520 architecture talks
|
||||
* PIO mode to the disk and DMA mode to the controller so the underlying
|
||||
* transfers are PIO timed.
|
||||
*/
|
||||
|
||||
static void cs5520_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
static const int dma_xlate[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 };
|
||||
cs5520_set_timings(ap, adev, dma_xlate[adev->dma_mode]);
|
||||
cs5520_enable_dma(ap, adev);
|
||||
}
|
||||
|
||||
/**
|
||||
* cs5520_set_piomode - program PIO timings
|
||||
* @ap: ATA port
|
||||
* @adev: ATA device
|
||||
*
|
||||
* Program the PIO mode timings for the controller according to the pio
|
||||
* clocking table. We know pio_mode will equal dma_mode because of the
|
||||
* CS5520 architecture. At least once we turned DMA on and wrote a
|
||||
* mode setter.
|
||||
* clocking table.
|
||||
*/
|
||||
|
||||
static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
@@ -149,7 +113,6 @@ static struct ata_port_operations cs5520_port_ops = {
|
||||
.qc_prep = ata_sff_dumb_qc_prep,
|
||||
.cable_detect = ata_cable_40wire,
|
||||
.set_piomode = cs5520_set_piomode,
|
||||
.set_dmamode = cs5520_set_dmamode,
|
||||
};
|
||||
|
||||
static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||
*
|
||||
* based upon cs5535.c from AMD <Jens.Altmann@amd.com> as cleaned up and
|
||||
* made readable and Linux style by Wolfgang Zuleger <wolfgang.zuleger@gmx.de
|
||||
* made readable and Linux style by Wolfgang Zuleger <wolfgang.zuleger@gmx.de>
|
||||
* and Alexander Kiausch <alex.kiausch@t-online.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -224,7 +224,7 @@ static struct scsi_host_template cs5536_sht = {
|
||||
};
|
||||
|
||||
static struct ata_port_operations cs5536_port_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.inherits = &ata_bmdma32_port_ops,
|
||||
.cable_detect = cs5536_cable_detect,
|
||||
.set_piomode = cs5536_set_piomode,
|
||||
.set_dmamode = cs5536_set_dmamode,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* pata_efar.c - EFAR PIIX clone controller driver
|
||||
*
|
||||
* (C) 2005 Red Hat
|
||||
* (C) 2009 Bartlomiej Zolnierkiewicz
|
||||
*
|
||||
* Some parts based on ata_piix.c by Jeff Garzik and others.
|
||||
*
|
||||
@@ -118,12 +119,12 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)
|
||||
int shift = 4 * ap->port_no;
|
||||
u8 slave_data;
|
||||
|
||||
idetm_data &= 0xCC0F;
|
||||
idetm_data &= 0xFF0F;
|
||||
idetm_data |= (control << 4);
|
||||
|
||||
/* Slave timing in separate register */
|
||||
pci_read_config_byte(dev, 0x44, &slave_data);
|
||||
slave_data &= 0x0F << shift;
|
||||
slave_data &= ap->port_no ? 0x0F : 0xF0;
|
||||
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift;
|
||||
pci_write_config_byte(dev, 0x44, slave_data);
|
||||
}
|
||||
@@ -200,7 +201,7 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev)
|
||||
master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
|
||||
master_data |= control << 4;
|
||||
pci_read_config_byte(dev, 0x44, &slave_data);
|
||||
slave_data &= (0x0F + 0xE1 * ap->port_no);
|
||||
slave_data &= ap->port_no ? 0x0F : 0xF0;
|
||||
/* Load the matching timing */
|
||||
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
|
||||
pci_write_config_byte(dev, 0x44, slave_data);
|
||||
@@ -251,7 +252,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
static const struct ata_port_info info = {
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.mwdma_mask = ATA_MWDMA12_ONLY,
|
||||
.udma_mask = ATA_UDMA4,
|
||||
.port_ops = &efar_ops,
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt366"
|
||||
#define DRV_VERSION "0.6.2"
|
||||
#define DRV_VERSION "0.6.7"
|
||||
|
||||
struct hpt_clock {
|
||||
u8 xfer_mode;
|
||||
@@ -36,24 +36,22 @@ struct hpt_clock {
|
||||
|
||||
/* key for bus clock timings
|
||||
* bit
|
||||
* 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
|
||||
* DMA. cycles = value + 1
|
||||
* 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW
|
||||
* DMA. cycles = value + 1
|
||||
* 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file
|
||||
* 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
|
||||
* cycles = value + 1
|
||||
* 4:7 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
|
||||
* cycles = value + 1
|
||||
* 8:11 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
|
||||
* register access.
|
||||
* 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file
|
||||
* 12:15 cmd_low_time. Active time of DIOW_/DIOR_ during task file
|
||||
* register access.
|
||||
* 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer.
|
||||
* during task file register access.
|
||||
* 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA
|
||||
* xfer.
|
||||
* 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task
|
||||
* 16:18 udma_cycle_time. Clock cycles for UDMA xfer?
|
||||
* 19:21 pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer.
|
||||
* 22:24 cmd_pre_high_time. Time to initialize 1st PIO cycle for task file
|
||||
* register access.
|
||||
* 28 UDMA enable
|
||||
* 29 DMA enable
|
||||
* 30 PIO_MST enable. if set, the chip is in bus master mode during
|
||||
* PIO.
|
||||
* 28 UDMA enable.
|
||||
* 29 DMA enable.
|
||||
* 30 PIO_MST enable. If set, the chip is in bus master mode during
|
||||
* PIO xfer.
|
||||
* 31 FIFO enable.
|
||||
*/
|
||||
|
||||
@@ -344,7 +342,6 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
|
||||
|
||||
void *hpriv = NULL;
|
||||
u32 class_rev;
|
||||
u32 reg1;
|
||||
int rc;
|
||||
|
||||
@@ -352,13 +349,10 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xFF;
|
||||
|
||||
/* May be a later chip in disguise. Check */
|
||||
/* Newer chips are not in the HPT36x driver. Ignore them */
|
||||
if (class_rev > 2)
|
||||
return -ENODEV;
|
||||
if (dev->revision > 2)
|
||||
return -ENODEV;
|
||||
|
||||
hpt36x_init_chipset(dev);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt37x"
|
||||
#define DRV_VERSION "0.6.12"
|
||||
#define DRV_VERSION "0.6.14"
|
||||
|
||||
struct hpt_clock {
|
||||
u8 xfer_speed;
|
||||
@@ -303,72 +303,79 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
|
||||
}
|
||||
|
||||
/**
|
||||
* hpt37x_pre_reset - reset the hpt37x bus
|
||||
* @link: ATA link to reset
|
||||
* @deadline: deadline jiffies for the operation
|
||||
* hpt37x_cable_detect - Detect the cable type
|
||||
* @ap: ATA port to detect on
|
||||
*
|
||||
* Perform the initial reset handling for the 370/372 and 374 func 0
|
||||
* Return the cable type attached to this port
|
||||
*/
|
||||
|
||||
static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
|
||||
static int hpt37x_cable_detect(struct ata_port *ap)
|
||||
{
|
||||
u8 scr2, ata66;
|
||||
struct ata_port *ap = link->ap;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
static const struct pci_bits hpt37x_enable_bits[] = {
|
||||
{ 0x50, 1, 0x04, 0x04 },
|
||||
{ 0x54, 1, 0x04, 0x04 }
|
||||
};
|
||||
if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
|
||||
return -ENOENT;
|
||||
u8 scr2, ata66;
|
||||
|
||||
pci_read_config_byte(pdev, 0x5B, &scr2);
|
||||
pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
|
||||
|
||||
udelay(10); /* debounce */
|
||||
|
||||
/* Cable register now active */
|
||||
pci_read_config_byte(pdev, 0x5A, &ata66);
|
||||
/* Restore state */
|
||||
pci_write_config_byte(pdev, 0x5B, scr2);
|
||||
|
||||
if (ata66 & (2 >> ap->port_no))
|
||||
ap->cbl = ATA_CBL_PATA40;
|
||||
return ATA_CBL_PATA40;
|
||||
else
|
||||
ap->cbl = ATA_CBL_PATA80;
|
||||
|
||||
/* Reset the state machine */
|
||||
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
|
||||
udelay(100);
|
||||
|
||||
return ata_sff_prereset(link, deadline);
|
||||
return ATA_CBL_PATA80;
|
||||
}
|
||||
|
||||
static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline)
|
||||
/**
|
||||
* hpt374_fn1_cable_detect - Detect the cable type
|
||||
* @ap: ATA port to detect on
|
||||
*
|
||||
* Return the cable type attached to this port
|
||||
*/
|
||||
|
||||
static int hpt374_fn1_cable_detect(struct ata_port *ap)
|
||||
{
|
||||
static const struct pci_bits hpt37x_enable_bits[] = {
|
||||
{ 0x50, 1, 0x04, 0x04 },
|
||||
{ 0x54, 1, 0x04, 0x04 }
|
||||
};
|
||||
u16 mcr3;
|
||||
u8 ata66;
|
||||
struct ata_port *ap = link->ap;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
unsigned int mcrbase = 0x50 + 4 * ap->port_no;
|
||||
|
||||
if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
|
||||
return -ENOENT;
|
||||
u16 mcr3;
|
||||
u8 ata66;
|
||||
|
||||
/* Do the extra channel work */
|
||||
pci_read_config_word(pdev, mcrbase + 2, &mcr3);
|
||||
/* Set bit 15 of 0x52 to enable TCBLID as input
|
||||
*/
|
||||
/* Set bit 15 of 0x52 to enable TCBLID as input */
|
||||
pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000);
|
||||
pci_read_config_byte(pdev, 0x5A, &ata66);
|
||||
/* Reset TCBLID/FCBLID to output */
|
||||
pci_write_config_word(pdev, mcrbase + 2, mcr3);
|
||||
|
||||
if (ata66 & (2 >> ap->port_no))
|
||||
ap->cbl = ATA_CBL_PATA40;
|
||||
return ATA_CBL_PATA40;
|
||||
else
|
||||
ap->cbl = ATA_CBL_PATA80;
|
||||
return ATA_CBL_PATA80;
|
||||
}
|
||||
|
||||
/**
|
||||
* hpt37x_pre_reset - reset the hpt37x bus
|
||||
* @link: ATA link to reset
|
||||
* @deadline: deadline jiffies for the operation
|
||||
*
|
||||
* Perform the initial reset handling for the HPT37x.
|
||||
*/
|
||||
|
||||
static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
|
||||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
static const struct pci_bits hpt37x_enable_bits[] = {
|
||||
{ 0x50, 1, 0x04, 0x04 },
|
||||
{ 0x54, 1, 0x04, 0x04 }
|
||||
};
|
||||
if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
|
||||
return -ENOENT;
|
||||
|
||||
/* Reset the state machine */
|
||||
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
|
||||
@@ -404,9 +411,8 @@ static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
|
||||
pci_read_config_dword(pdev, addr1, ®);
|
||||
mode = hpt37x_find_mode(ap, adev->pio_mode);
|
||||
mode &= ~0x8000000; /* No FIFO in PIO */
|
||||
mode &= ~0x30070000; /* Leave config bits alone */
|
||||
reg &= 0x30070000; /* Strip timing bits */
|
||||
mode &= 0xCFC3FFFF; /* Leave DMA bits alone */
|
||||
reg &= ~0xCFC3FFFF; /* Strip timing bits */
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
@@ -423,8 +429,7 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 addr1, addr2;
|
||||
u32 reg;
|
||||
u32 mode;
|
||||
u32 reg, mode, mask;
|
||||
u8 fast;
|
||||
|
||||
addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
|
||||
@@ -436,11 +441,12 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
fast |= 0x01;
|
||||
pci_write_config_byte(pdev, addr2, fast);
|
||||
|
||||
mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
|
||||
|
||||
pci_read_config_dword(pdev, addr1, ®);
|
||||
mode = hpt37x_find_mode(ap, adev->dma_mode);
|
||||
mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
|
||||
mode &= ~0xC0000000; /* Leave config bits alone */
|
||||
reg &= 0xC0000000; /* Strip timing bits */
|
||||
mode &= mask;
|
||||
reg &= ~mask;
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
@@ -508,9 +514,8 @@ static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
mode = hpt37x_find_mode(ap, adev->pio_mode);
|
||||
|
||||
printk("Find mode for %d reports %X\n", adev->pio_mode, mode);
|
||||
mode &= ~0x80000000; /* No FIFO in PIO */
|
||||
mode &= ~0x30070000; /* Leave config bits alone */
|
||||
reg &= 0x30070000; /* Strip timing bits */
|
||||
mode &= 0xCFC3FFFF; /* Leave DMA bits alone */
|
||||
reg &= ~0xCFC3FFFF; /* Strip timing bits */
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
@@ -527,8 +532,7 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 addr1, addr2;
|
||||
u32 reg;
|
||||
u32 mode;
|
||||
u32 reg, mode, mask;
|
||||
u8 fast;
|
||||
|
||||
addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
|
||||
@@ -539,12 +543,13 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
fast &= ~0x07;
|
||||
pci_write_config_byte(pdev, addr2, fast);
|
||||
|
||||
mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
|
||||
|
||||
pci_read_config_dword(pdev, addr1, ®);
|
||||
mode = hpt37x_find_mode(ap, adev->dma_mode);
|
||||
printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode);
|
||||
mode &= ~0xC0000000; /* Leave config bits alone */
|
||||
mode |= 0x80000000; /* FIFO in MWDMA or UDMA */
|
||||
reg &= 0xC0000000; /* Strip timing bits */
|
||||
mode &= mask;
|
||||
reg &= ~mask;
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
@@ -584,6 +589,7 @@ static struct ata_port_operations hpt370_port_ops = {
|
||||
.bmdma_stop = hpt370_bmdma_stop,
|
||||
|
||||
.mode_filter = hpt370_filter,
|
||||
.cable_detect = hpt37x_cable_detect,
|
||||
.set_piomode = hpt370_set_piomode,
|
||||
.set_dmamode = hpt370_set_dmamode,
|
||||
.prereset = hpt37x_pre_reset,
|
||||
@@ -608,6 +614,7 @@ static struct ata_port_operations hpt372_port_ops = {
|
||||
|
||||
.bmdma_stop = hpt37x_bmdma_stop,
|
||||
|
||||
.cable_detect = hpt37x_cable_detect,
|
||||
.set_piomode = hpt372_set_piomode,
|
||||
.set_dmamode = hpt372_set_dmamode,
|
||||
.prereset = hpt37x_pre_reset,
|
||||
@@ -620,7 +627,8 @@ static struct ata_port_operations hpt372_port_ops = {
|
||||
|
||||
static struct ata_port_operations hpt374_fn1_port_ops = {
|
||||
.inherits = &hpt372_port_ops,
|
||||
.prereset = hpt374_fn1_pre_reset,
|
||||
.cable_detect = hpt374_fn1_cable_detect,
|
||||
.prereset = hpt37x_pre_reset,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -791,9 +799,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
static const int MHz[4] = { 33, 40, 50, 66 };
|
||||
void *private_data = NULL;
|
||||
const struct ata_port_info *ppi[] = { NULL, NULL };
|
||||
|
||||
u8 rev = dev->revision;
|
||||
u8 irqmask;
|
||||
u32 class_rev;
|
||||
u8 mcr1;
|
||||
u32 freq;
|
||||
int prefer_dpll = 1;
|
||||
@@ -808,19 +815,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xFF;
|
||||
|
||||
if (dev->device == PCI_DEVICE_ID_TTI_HPT366) {
|
||||
/* May be a later chip in disguise. Check */
|
||||
/* Older chips are in the HPT366 driver. Ignore them */
|
||||
if (class_rev < 3)
|
||||
if (rev < 3)
|
||||
return -ENODEV;
|
||||
/* N series chips have their own driver. Ignore */
|
||||
if (class_rev == 6)
|
||||
if (rev == 6)
|
||||
return -ENODEV;
|
||||
|
||||
switch(class_rev) {
|
||||
switch(rev) {
|
||||
case 3:
|
||||
ppi[0] = &info_hpt370;
|
||||
chip_table = &hpt370;
|
||||
@@ -836,28 +840,29 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
chip_table = &hpt372;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev);
|
||||
printk(KERN_ERR "pata_hpt37x: Unknown HPT366 "
|
||||
"subtype, please report (%d).\n", rev);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
switch(dev->device) {
|
||||
case PCI_DEVICE_ID_TTI_HPT372:
|
||||
/* 372N if rev >= 2*/
|
||||
if (class_rev >= 2)
|
||||
if (rev >= 2)
|
||||
return -ENODEV;
|
||||
ppi[0] = &info_hpt372;
|
||||
chip_table = &hpt372a;
|
||||
break;
|
||||
case PCI_DEVICE_ID_TTI_HPT302:
|
||||
/* 302N if rev > 1 */
|
||||
if (class_rev > 1)
|
||||
if (rev > 1)
|
||||
return -ENODEV;
|
||||
ppi[0] = &info_hpt372;
|
||||
/* Check this */
|
||||
chip_table = &hpt302;
|
||||
break;
|
||||
case PCI_DEVICE_ID_TTI_HPT371:
|
||||
if (class_rev > 1)
|
||||
if (rev > 1)
|
||||
return -ENODEV;
|
||||
ppi[0] = &info_hpt372;
|
||||
chip_table = &hpt371;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt3x2n"
|
||||
#define DRV_VERSION "0.3.4"
|
||||
#define DRV_VERSION "0.3.7"
|
||||
|
||||
enum {
|
||||
HPT_PCI_FAST = (1 << 31),
|
||||
@@ -80,14 +80,13 @@ static struct hpt_clock hpt3x2n_clocks[] = {
|
||||
|
||||
{ XFER_MW_DMA_2, 0x2c829c62 },
|
||||
{ XFER_MW_DMA_1, 0x2c829c66 },
|
||||
{ XFER_MW_DMA_0, 0x2c829d2c },
|
||||
{ XFER_MW_DMA_0, 0x2c829d2e },
|
||||
|
||||
{ XFER_PIO_4, 0x0c829c62 },
|
||||
{ XFER_PIO_3, 0x0c829c84 },
|
||||
{ XFER_PIO_2, 0x0c829ca6 },
|
||||
{ XFER_PIO_1, 0x0d029d26 },
|
||||
{ XFER_PIO_0, 0x0d029d5e },
|
||||
{ 0, 0x0d029d5e }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -128,12 +127,15 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
|
||||
|
||||
pci_read_config_byte(pdev, 0x5B, &scr2);
|
||||
pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
|
||||
|
||||
udelay(10); /* debounce */
|
||||
|
||||
/* Cable register now active */
|
||||
pci_read_config_byte(pdev, 0x5A, &ata66);
|
||||
/* Restore state */
|
||||
pci_write_config_byte(pdev, 0x5B, scr2);
|
||||
|
||||
if (ata66 & (1 << ap->port_no))
|
||||
if (ata66 & (2 >> ap->port_no))
|
||||
return ATA_CBL_PATA40;
|
||||
else
|
||||
return ATA_CBL_PATA80;
|
||||
@@ -185,9 +187,8 @@ static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
|
||||
pci_read_config_dword(pdev, addr1, ®);
|
||||
mode = hpt3x2n_find_mode(ap, adev->pio_mode);
|
||||
mode &= ~0x8000000; /* No FIFO in PIO */
|
||||
mode &= ~0x30070000; /* Leave config bits alone */
|
||||
reg &= 0x30070000; /* Strip timing bits */
|
||||
mode &= 0xCFC3FFFF; /* Leave DMA bits alone */
|
||||
reg &= ~0xCFC3FFFF; /* Strip timing bits */
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
@@ -204,8 +205,7 @@ static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 addr1, addr2;
|
||||
u32 reg;
|
||||
u32 mode;
|
||||
u32 reg, mode, mask;
|
||||
u8 fast;
|
||||
|
||||
addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
|
||||
@@ -216,11 +216,12 @@ static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
fast &= ~0x07;
|
||||
pci_write_config_byte(pdev, addr2, fast);
|
||||
|
||||
mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
|
||||
|
||||
pci_read_config_dword(pdev, addr1, ®);
|
||||
mode = hpt3x2n_find_mode(ap, adev->dma_mode);
|
||||
mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
|
||||
mode &= ~0xC0000000; /* Leave config bits alone */
|
||||
reg &= 0xC0000000; /* Strip timing bits */
|
||||
mode &= mask;
|
||||
reg &= ~mask;
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
@@ -447,10 +448,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
.port_ops = &hpt3x2n_port_ops
|
||||
};
|
||||
const struct ata_port_info *ppi[] = { &info, NULL };
|
||||
|
||||
u8 rev = dev->revision;
|
||||
u8 irqmask;
|
||||
u32 class_rev;
|
||||
|
||||
unsigned int pci_mhz;
|
||||
unsigned int f_low, f_high;
|
||||
int adjust;
|
||||
@@ -462,26 +461,23 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xFF;
|
||||
|
||||
switch(dev->device) {
|
||||
case PCI_DEVICE_ID_TTI_HPT366:
|
||||
if (class_rev < 6)
|
||||
if (rev < 6)
|
||||
return -ENODEV;
|
||||
break;
|
||||
case PCI_DEVICE_ID_TTI_HPT371:
|
||||
if (class_rev < 2)
|
||||
if (rev < 2)
|
||||
return -ENODEV;
|
||||
/* 371N if rev > 1 */
|
||||
break;
|
||||
case PCI_DEVICE_ID_TTI_HPT372:
|
||||
/* 372N if rev >= 2*/
|
||||
if (class_rev < 2)
|
||||
if (rev < 2)
|
||||
return -ENODEV;
|
||||
break;
|
||||
case PCI_DEVICE_ID_TTI_HPT302:
|
||||
if (class_rev < 2)
|
||||
if (rev < 2)
|
||||
return -ENODEV;
|
||||
break;
|
||||
case PCI_DEVICE_ID_TTI_HPT372N:
|
||||
|
||||
@@ -255,8 +255,17 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
#ifdef CONFIG_PM
|
||||
static int hpt3x3_reinit_one(struct pci_dev *dev)
|
||||
{
|
||||
struct ata_host *host = dev_get_drvdata(&dev->dev);
|
||||
int rc;
|
||||
|
||||
rc = ata_pci_device_do_resume(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
hpt3x3_init_chipset(dev);
|
||||
return ata_pci_device_resume(dev);
|
||||
|
||||
ata_host_resume(host);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define DRV_VERSION "0.0.3"
|
||||
|
||||
/**
|
||||
* it8213_pre_reset - check for 40/80 pin
|
||||
* it8213_pre_reset - probe begin
|
||||
* @link: link
|
||||
* @deadline: deadline jiffies for the operation
|
||||
*
|
||||
@@ -92,18 +92,17 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
|
||||
{ 2, 1 },
|
||||
{ 2, 3 }, };
|
||||
|
||||
if (pio > 2)
|
||||
control |= 1; /* TIME1 enable */
|
||||
if (pio > 1)
|
||||
control |= 1; /* TIME */
|
||||
if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */
|
||||
control |= 2; /* IORDY enable */
|
||||
control |= 2; /* IE */
|
||||
/* Bit 2 is set for ATAPI on the IT8213 - reverse of ICH/PIIX */
|
||||
if (adev->class != ATA_DEV_ATA)
|
||||
control |= 4;
|
||||
control |= 4; /* PPE */
|
||||
|
||||
pci_read_config_word(dev, idetm_port, &idetm_data);
|
||||
|
||||
/* Enable PPE, IE and TIME as appropriate */
|
||||
|
||||
/* Set PPE, IE, and TIME as appropriate */
|
||||
if (adev->devno == 0) {
|
||||
idetm_data &= 0xCCF0;
|
||||
idetm_data |= control;
|
||||
@@ -112,17 +111,17 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
|
||||
} else {
|
||||
u8 slave_data;
|
||||
|
||||
idetm_data &= 0xCC0F;
|
||||
idetm_data &= 0xFF0F;
|
||||
idetm_data |= (control << 4);
|
||||
|
||||
/* Slave timing in separate register */
|
||||
pci_read_config_byte(dev, 0x44, &slave_data);
|
||||
slave_data &= 0xF0;
|
||||
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << 4;
|
||||
slave_data |= (timings[pio][0] << 2) | timings[pio][1];
|
||||
pci_write_config_byte(dev, 0x44, slave_data);
|
||||
}
|
||||
|
||||
idetm_data |= 0x4000; /* Ensure SITRE is enabled */
|
||||
idetm_data |= 0x4000; /* Ensure SITRE is set */
|
||||
pci_write_config_word(dev, idetm_port, idetm_data);
|
||||
}
|
||||
|
||||
@@ -173,10 +172,10 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
|
||||
|
||||
udma_enable |= (1 << devid);
|
||||
|
||||
/* Load the UDMA mode number */
|
||||
/* Load the UDMA cycle time */
|
||||
pci_read_config_word(dev, 0x4A, &udma_timing);
|
||||
udma_timing &= ~(3 << (4 * devid));
|
||||
udma_timing |= (udma & 3) << (4 * devid);
|
||||
udma_timing |= u_speed << (4 * devid);
|
||||
pci_write_config_word(dev, 0x4A, udma_timing);
|
||||
|
||||
/* Load the clock selection */
|
||||
@@ -211,7 +210,7 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
|
||||
master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
|
||||
master_data |= control << 4;
|
||||
pci_read_config_byte(dev, 0x44, &slave_data);
|
||||
slave_data &= (0x0F + 0xE1 * ap->port_no);
|
||||
slave_data &= 0xF0;
|
||||
/* Load the matching timing */
|
||||
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
|
||||
pci_write_config_byte(dev, 0x44, slave_data);
|
||||
@@ -263,7 +262,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
|
||||
static const struct ata_port_info info = {
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.mwdma_mask = ATA_MWDMA12_ONLY,
|
||||
.udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */
|
||||
.port_ops = &it8213_ops,
|
||||
};
|
||||
|
||||
@@ -955,7 +955,7 @@ static int it821x_reinit_one(struct pci_dev *pdev)
|
||||
static const struct pci_device_id it821x[] = {
|
||||
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), },
|
||||
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), },
|
||||
{ PCI_VDEVICE(RDC, 0x1010), },
|
||||
{ PCI_VDEVICE(RDC, PCI_DEVICE_ID_RDC_D1010), },
|
||||
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
* http://www.ryston.cz/petr/vlb/pdc20230b.html
|
||||
* http://www.ryston.cz/petr/vlb/pdc20230c.html
|
||||
* http://www.ryston.cz/petr/vlb/pdc20630.html
|
||||
* QDI65x0:
|
||||
* http://www.ryston.cz/petr/vlb/qd6500.html
|
||||
* http://www.ryston.cz/petr/vlb/qd6580.html
|
||||
*
|
||||
* QDI65x0 probe code based on drivers/ide/legacy/qd65xx.c
|
||||
* Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
|
||||
* Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
*
|
||||
* Unsupported but docs exist:
|
||||
* Appian/Adaptec AIC25VL01/Cirrus Logic PD7220
|
||||
@@ -35,7 +42,7 @@
|
||||
* the MPIIX where the tuning is PCI side but the IDE is "ISA side".
|
||||
*
|
||||
* Specific support is included for the ht6560a/ht6560b/opti82c611a/
|
||||
* opti82c465mv/promise 20230c/20630/winbond83759A
|
||||
* opti82c465mv/promise 20230c/20630/qdi65x0/winbond83759A
|
||||
*
|
||||
* Use the autospeed and pio_mask options with:
|
||||
* Appian ADI/2 aka CLPD7220 or AIC25VL01.
|
||||
@@ -672,7 +679,7 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
outb(timing, ld_qdi->timing + 2 * ap->port_no);
|
||||
/* Clear the FIFO */
|
||||
if (adev->class != ATA_DEV_ATA)
|
||||
outb(0x5F, ld_qdi->timing + 3);
|
||||
outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -707,7 +714,7 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
outb(timing, ld_qdi->timing + 2 * adev->devno);
|
||||
/* Clear the FIFO */
|
||||
if (adev->class != ATA_DEV_ATA)
|
||||
outb(0x5F, ld_qdi->timing + 3);
|
||||
outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -787,6 +794,7 @@ static struct ata_port_operations qdi6580_port_ops = {
|
||||
static struct ata_port_operations qdi6580dp_port_ops = {
|
||||
.inherits = &legacy_base_port_ops,
|
||||
.set_piomode = qdi6580dp_set_piomode,
|
||||
.qc_issue = qdi_qc_issue,
|
||||
.sff_data_xfer = vlb32_data_xfer,
|
||||
};
|
||||
|
||||
|
||||
1427
drivers/ata/pata_macio.c
Normal file
1427
drivers/ata/pata_macio.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -58,7 +58,7 @@ static int marvell_pata_active(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
/**
|
||||
* marvell_pre_reset - check for 40/80 pin
|
||||
* marvell_pre_reset - probe begin
|
||||
* @link: link
|
||||
* @deadline: deadline jiffies for the operation
|
||||
*
|
||||
|
||||
@@ -325,6 +325,13 @@ static struct scsi_host_template ns87415_sht = {
|
||||
ATA_BMDMA_SHT(DRV_NAME),
|
||||
};
|
||||
|
||||
static void ns87415_fixup(struct pci_dev *pdev)
|
||||
{
|
||||
/* Select 512 byte sectors */
|
||||
pci_write_config_byte(pdev, 0x55, 0xEE);
|
||||
/* Select PIO0 8bit clocking */
|
||||
pci_write_config_byte(pdev, 0x54, 0xB7);
|
||||
}
|
||||
|
||||
/**
|
||||
* ns87415_init_one - Register 87415 ATA PCI device with kernel services
|
||||
@@ -371,10 +378,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Select 512 byte sectors */
|
||||
pci_write_config_byte(pdev, 0x55, 0xEE);
|
||||
/* Select PIO0 8bit clocking */
|
||||
pci_write_config_byte(pdev, 0x54, 0xB7);
|
||||
ns87415_fixup(pdev);
|
||||
|
||||
return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL);
|
||||
}
|
||||
|
||||
@@ -384,6 +389,23 @@ static const struct pci_device_id ns87415_pci_tbl[] = {
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ns87415_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||
int rc;
|
||||
|
||||
rc = ata_pci_device_do_resume(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ns87415_fixup(pdev);
|
||||
|
||||
ata_host_resume(host);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pci_driver ns87415_pci_driver = {
|
||||
.name = DRV_NAME,
|
||||
.id_table = ns87415_pci_tbl,
|
||||
@@ -391,7 +413,7 @@ static struct pci_driver ns87415_pci_driver = {
|
||||
.remove = ata_pci_remove_one,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
.resume = ns87415_reinit_one,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
||||
static const struct ata_port_info info = {
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.mwdma_mask = ATA_MWDMA12_ONLY,
|
||||
.port_ops = &oldpiix_pata_ops,
|
||||
};
|
||||
const struct ata_port_info *ppi[] = { &info, NULL };
|
||||
|
||||
@@ -177,9 +177,6 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
|
||||
.drain_fifo = pcmcia_8bit_drain_fifo,
|
||||
};
|
||||
|
||||
#define CS_CHECK(fn, ret) \
|
||||
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
||||
|
||||
|
||||
struct pcmcia_config_check {
|
||||
unsigned long ctl_base;
|
||||
@@ -252,7 +249,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
|
||||
struct ata_port *ap;
|
||||
struct ata_pcmcia_info *info;
|
||||
struct pcmcia_config_check *stk = NULL;
|
||||
int last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
|
||||
int is_kme = 0, ret = -ENOMEM, p;
|
||||
unsigned long io_base, ctl_base;
|
||||
void __iomem *io_addr, *ctl_addr;
|
||||
int n_ports = 1;
|
||||
@@ -271,7 +268,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
|
||||
pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
|
||||
pdev->io.IOAddrLines = 3;
|
||||
pdev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
|
||||
pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
pdev->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
pdev->conf.IntType = INT_MEMORY_AND_IO;
|
||||
|
||||
@@ -296,8 +292,13 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
|
||||
}
|
||||
io_base = pdev->io.BasePort1;
|
||||
ctl_base = stk->ctl_base;
|
||||
CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
|
||||
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
|
||||
ret = pcmcia_request_irq(pdev, &pdev->irq);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
ret = pcmcia_request_configuration(pdev, &pdev->conf);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
/* iomap */
|
||||
ret = -ENOMEM;
|
||||
@@ -351,8 +352,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
|
||||
kfree(stk);
|
||||
return 0;
|
||||
|
||||
cs_failed:
|
||||
cs_error(pdev, last_fn, last_ret);
|
||||
failed:
|
||||
kfree(stk);
|
||||
info->ndev = 0;
|
||||
|
||||
140
drivers/ata/pata_piccolo.c
Normal file
140
drivers/ata/pata_piccolo.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* pata_piccolo.c - Toshiba Piccolo PATA/SATA controller driver.
|
||||
*
|
||||
* This is basically an update to ata_generic.c to add Toshiba Piccolo support
|
||||
* then split out to keep ata_generic "clean".
|
||||
*
|
||||
* Copyright 2005 Red Hat Inc, all rights reserved.
|
||||
*
|
||||
* Elements from ide/pci/generic.c
|
||||
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
|
||||
* Portions (C) Copyright 2002 Red Hat Inc <alan@redhat.com>
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public License
|
||||
*
|
||||
* The timing data tables/programming info are courtesy of the NetBSD driver
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_piccolo"
|
||||
#define DRV_VERSION "0.0.1"
|
||||
|
||||
|
||||
|
||||
static void tosh_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
static const u16 pio[6] = { /* For reg 0x50 low word & E088 */
|
||||
0x0566, 0x0433, 0x0311, 0x0201, 0x0200, 0x0100
|
||||
};
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u16 conf;
|
||||
pci_read_config_word(pdev, 0x50, &conf);
|
||||
conf &= 0xE088;
|
||||
conf |= pio[adev->pio_mode - XFER_PIO_0];
|
||||
pci_write_config_word(pdev, 0x50, conf);
|
||||
}
|
||||
|
||||
static void tosh_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
u32 conf;
|
||||
pci_read_config_dword(pdev, 0x5C, &conf);
|
||||
conf &= 0x78FFE088; /* Keep the other bits */
|
||||
if (adev->dma_mode >= XFER_UDMA_0) {
|
||||
int udma = adev->dma_mode - XFER_UDMA_0;
|
||||
conf |= 0x80000000;
|
||||
conf |= (udma + 2) << 28;
|
||||
conf |= (2 - udma) * 0x111; /* spread into three nibbles */
|
||||
} else {
|
||||
static const u32 mwdma[4] = {
|
||||
0x0655, 0x0200, 0x0200, 0x0100
|
||||
};
|
||||
conf |= mwdma[adev->dma_mode - XFER_MW_DMA_0];
|
||||
}
|
||||
pci_write_config_dword(pdev, 0x5C, conf);
|
||||
}
|
||||
|
||||
|
||||
static struct scsi_host_template tosh_sht = {
|
||||
ATA_BMDMA_SHT(DRV_NAME),
|
||||
};
|
||||
|
||||
static struct ata_port_operations tosh_port_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
.cable_detect = ata_cable_unknown,
|
||||
.set_piomode = tosh_set_piomode,
|
||||
.set_dmamode = tosh_set_dmamode
|
||||
};
|
||||
|
||||
/**
|
||||
* ata_tosh_init - attach generic IDE
|
||||
* @dev: PCI device found
|
||||
* @id: match entry
|
||||
*
|
||||
* Called each time a matching IDE interface is found. We check if the
|
||||
* interface is one we wish to claim and if so we perform any chip
|
||||
* specific hacks then let the ATA layer do the heavy lifting.
|
||||
*/
|
||||
|
||||
static int ata_tosh_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
static const struct ata_port_info info = {
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = ATA_PIO5,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA2,
|
||||
.port_ops = &tosh_port_ops
|
||||
};
|
||||
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
|
||||
/* Just one port for the moment */
|
||||
return ata_pci_sff_init_one(dev, ppi, &tosh_sht, NULL);
|
||||
}
|
||||
|
||||
static struct pci_device_id ata_tosh[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), },
|
||||
{ 0, },
|
||||
};
|
||||
|
||||
static struct pci_driver ata_tosh_pci_driver = {
|
||||
.name = DRV_NAME,
|
||||
.id_table = ata_tosh,
|
||||
.probe = ata_tosh_init_one,
|
||||
.remove = ata_pci_remove_one,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init ata_tosh_init(void)
|
||||
{
|
||||
return pci_register_driver(&ata_tosh_pci_driver);
|
||||
}
|
||||
|
||||
|
||||
static void __exit ata_tosh_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&ata_tosh_pci_driver);
|
||||
}
|
||||
|
||||
|
||||
MODULE_AUTHOR("Alan Cox");
|
||||
MODULE_DESCRIPTION("Low level driver for Toshiba Piccolo ATA");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(pci, ata_tosh);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
module_init(ata_tosh_init);
|
||||
module_exit(ata_tosh_exit);
|
||||
|
||||
@@ -139,9 +139,9 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
|
||||
pci_read_config_byte(dev, 0x4A, &udma_mode);
|
||||
|
||||
if (adev->xfer_mode == XFER_UDMA_2)
|
||||
udma_mode &= ~ (1 << adev->devno);
|
||||
udma_mode &= ~(2 << (adev->devno * 4));
|
||||
else /* UDMA 4 */
|
||||
udma_mode |= (1 << adev->devno);
|
||||
udma_mode |= (2 << (adev->devno * 4));
|
||||
|
||||
pci_write_config_byte(dev, 0x4A, udma_mode);
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ static struct ata_port_info rdc_port_info = {
|
||||
|
||||
.flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.mwdma_mask = ATA_MWDMA12_ONLY,
|
||||
.udma_mask = ATA_UDMA5,
|
||||
.port_ops = &rdc_pata_ops,
|
||||
};
|
||||
|
||||
@@ -105,11 +105,20 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
|
||||
#ifdef CONFIG_PM
|
||||
static int rz1000_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||
int rc;
|
||||
|
||||
rc = ata_pci_device_do_resume(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* If this fails on resume (which is a "cant happen" case), we
|
||||
must stop as any progress risks data loss */
|
||||
if (rz1000_fifo_disable(pdev))
|
||||
panic("rz1000 fifo");
|
||||
return ata_pci_device_resume(pdev);
|
||||
|
||||
ata_host_resume(host);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -212,13 +212,11 @@ static struct ata_port_operations sil680_port_ops = {
|
||||
|
||||
static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
|
||||
{
|
||||
u32 class_rev = 0;
|
||||
u8 tmpbyte = 0;
|
||||
|
||||
pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xff;
|
||||
/* FIXME: double check */
|
||||
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255);
|
||||
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
|
||||
pdev->revision ? 1 : 255);
|
||||
|
||||
pci_write_config_byte(pdev, 0x80, 0x00);
|
||||
pci_write_config_byte(pdev, 0x84, 0x00);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* pata_sis.c - SiS ATA driver
|
||||
*
|
||||
* (C) 2005 Red Hat
|
||||
* (C) 2007 Bartlomiej Zolnierkiewicz
|
||||
* (C) 2007,2009 Bartlomiej Zolnierkiewicz
|
||||
*
|
||||
* Based upon linux/drivers/ide/pci/sis5513.c
|
||||
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
|
||||
@@ -829,6 +829,23 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int sis_reinit_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||
int rc;
|
||||
|
||||
rc = ata_pci_device_do_resume(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
sis_fixup(pdev, host->private_data);
|
||||
|
||||
ata_host_resume(host);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct pci_device_id sis_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(SI, 0x5513), }, /* SiS 5513 */
|
||||
{ PCI_VDEVICE(SI, 0x5518), }, /* SiS 5518 */
|
||||
@@ -844,7 +861,7 @@ static struct pci_driver sis_pci_driver = {
|
||||
.remove = ata_pci_remove_one,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ata_pci_device_suspend,
|
||||
.resume = ata_pci_device_resume,
|
||||
.resume = sis_reinit_one,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -303,14 +303,21 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mo
|
||||
}
|
||||
|
||||
/* Set UDMA unless device is not UDMA capable */
|
||||
if (udma_type && t.udma) {
|
||||
u8 cable80_status;
|
||||
if (udma_type) {
|
||||
u8 udma_etc;
|
||||
|
||||
/* Get 80-wire cable detection bit */
|
||||
pci_read_config_byte(pdev, 0x50 + offset, &cable80_status);
|
||||
cable80_status &= 0x10;
|
||||
pci_read_config_byte(pdev, 0x50 + offset, &udma_etc);
|
||||
|
||||
pci_write_config_byte(pdev, 0x50 + offset, ut | cable80_status);
|
||||
/* clear transfer mode bit */
|
||||
udma_etc &= ~0x20;
|
||||
|
||||
if (t.udma) {
|
||||
/* preserve 80-wire cable detection bit */
|
||||
udma_etc &= 0x10;
|
||||
udma_etc |= ut;
|
||||
}
|
||||
|
||||
pci_write_config_byte(pdev, 0x50 + offset, udma_etc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +343,32 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]);
|
||||
}
|
||||
|
||||
/**
|
||||
* via_mode_filter - filter buggy device/mode pairs
|
||||
* @dev: ATA device
|
||||
* @mask: Mode bitmask
|
||||
*
|
||||
* We need to apply some minimal filtering for old controllers and at least
|
||||
* one breed of Transcend SSD. Return the updated mask.
|
||||
*/
|
||||
|
||||
static unsigned long via_mode_filter(struct ata_device *dev, unsigned long mask)
|
||||
{
|
||||
struct ata_host *host = dev->link->ap->host;
|
||||
const struct via_isa_bridge *config = host->private_data;
|
||||
unsigned char model_num[ATA_ID_PROD_LEN + 1];
|
||||
|
||||
if (config->id == PCI_DEVICE_ID_VIA_82C586_0) {
|
||||
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
|
||||
if (strcmp(model_num, "TS64GSSD25-M") == 0) {
|
||||
ata_dev_printk(dev, KERN_WARNING,
|
||||
"disabling UDMA mode due to reported lockups with this device.\n");
|
||||
mask &= ~ ATA_MASK_UDMA;
|
||||
}
|
||||
}
|
||||
return ata_bmdma_mode_filter(dev, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* via_tf_load - send taskfile registers to host controller
|
||||
* @ap: Port to which output is sent
|
||||
@@ -427,6 +460,7 @@ static struct ata_port_operations via_port_ops = {
|
||||
.prereset = via_pre_reset,
|
||||
.sff_tf_load = via_tf_load,
|
||||
.port_start = via_port_start,
|
||||
.mode_filter = via_mode_filter,
|
||||
};
|
||||
|
||||
static struct ata_port_operations via_port_ops_noirq = {
|
||||
@@ -526,7 +560,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
.port_ops = &via_port_ops
|
||||
};
|
||||
const struct ata_port_info *ppi[] = { NULL, NULL };
|
||||
struct pci_dev *isa = NULL;
|
||||
struct pci_dev *isa;
|
||||
const struct via_isa_bridge *config;
|
||||
static int printed_version;
|
||||
u8 enable;
|
||||
@@ -551,14 +585,12 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if ((isa = pci_get_device(PCI_VENDOR_ID_VIA +
|
||||
!!(config->flags & VIA_BAD_ID),
|
||||
config->id, NULL))) {
|
||||
|
||||
if (isa->revision >= config->rev_min &&
|
||||
isa->revision <= config->rev_max)
|
||||
break;
|
||||
u8 rev = isa->revision;
|
||||
pci_dev_put(isa);
|
||||
}
|
||||
|
||||
pci_dev_put(isa);
|
||||
if (rev >= config->rev_min && rev <= config->rev_max)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(config->flags & VIA_NO_ENABLES)) {
|
||||
/* 0x40 low bits indicate enabled channels */
|
||||
|
||||
@@ -34,7 +34,7 @@ enum {
|
||||
|
||||
SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
ATA_FLAG_PMP | ATA_FLAG_NCQ),
|
||||
ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN),
|
||||
|
||||
SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
|
||||
SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
|
||||
@@ -43,9 +43,9 @@ enum {
|
||||
/*
|
||||
* SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and
|
||||
* chained indirect PRDEs upto a max count of 63.
|
||||
* We are allocating an array of 63 PRDEs contigiously, but PRDE#15 will
|
||||
* We are allocating an array of 63 PRDEs contiguously, but PRDE#15 will
|
||||
* be setup as an indirect descriptor, pointing to it's next
|
||||
* (contigious) PRDE. Though chained indirect PRDE arrays are
|
||||
* (contiguous) PRDE. Though chained indirect PRDE arrays are
|
||||
* supported,it will be more efficient to use a direct PRDT and
|
||||
* a single chain/link to indirect PRDE array/PRDT.
|
||||
*/
|
||||
@@ -132,7 +132,7 @@ enum {
|
||||
INT_ON_SINGL_DEVICE_ERR = (1 << 1),
|
||||
INT_ON_CMD_COMPLETE = 1,
|
||||
|
||||
INT_ON_ERROR = INT_ON_FATAL_ERR |
|
||||
INT_ON_ERROR = INT_ON_FATAL_ERR | INT_ON_SNOTIFY_UPDATE |
|
||||
INT_ON_PHYRDY_CHG | INT_ON_SINGL_DEVICE_ERR,
|
||||
|
||||
/*
|
||||
@@ -153,7 +153,7 @@ enum {
|
||||
IE_ON_CMD_COMPLETE = 1,
|
||||
|
||||
DEFAULT_PORT_IRQ_ENABLE_MASK = IE_ON_FATAL_ERR | IE_ON_PHYRDY_CHG |
|
||||
IE_ON_SIGNATURE_UPDATE |
|
||||
IE_ON_SIGNATURE_UPDATE | IE_ON_SNOTIFY_UPDATE |
|
||||
IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE,
|
||||
|
||||
EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31),
|
||||
@@ -314,7 +314,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
|
||||
u32 ttl_dwords = 0;
|
||||
|
||||
/*
|
||||
* NOTE : direct & indirect prdt's are contigiously allocated
|
||||
* NOTE : direct & indirect prdt's are contiguously allocated
|
||||
*/
|
||||
struct prde *prd = (struct prde *)&((struct command_desc *)
|
||||
cmd_desc)->prdt;
|
||||
@@ -992,9 +992,8 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||
*/
|
||||
|
||||
sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
|
||||
if (unlikely(SError & 0xFFFF0000)) {
|
||||
if (unlikely(SError & 0xFFFF0000))
|
||||
sata_fsl_scr_write(&ap->link, SCR_ERROR, SError);
|
||||
}
|
||||
|
||||
DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
|
||||
hstatus, cereg, ioread32(hcr_base + DE), SError);
|
||||
@@ -1007,6 +1006,10 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||
freeze = 1;
|
||||
}
|
||||
|
||||
/* Handle SDB FIS receive & notify update */
|
||||
if (hstatus & INT_ON_SNOTIFY_UPDATE)
|
||||
sata_async_notification(ap);
|
||||
|
||||
/* Handle PHYRDY change notification */
|
||||
if (hstatus & INT_ON_PHYRDY_CHG) {
|
||||
DPRINTK("SATA FSL: PHYRDY change indication\n");
|
||||
@@ -1070,9 +1073,9 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||
}
|
||||
|
||||
/* record error info */
|
||||
if (qc) {
|
||||
if (qc)
|
||||
qc->err_mask |= err_mask;
|
||||
} else
|
||||
else
|
||||
ehi->err_mask |= err_mask;
|
||||
|
||||
ehi->action |= action;
|
||||
@@ -1103,7 +1106,6 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||
if (unlikely(SError & 0xFFFF0000)) {
|
||||
DPRINTK("serror @host_intr : 0x%x\n", SError);
|
||||
sata_fsl_error_intr(ap);
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(hstatus & INT_ON_ERROR)) {
|
||||
|
||||
@@ -2217,7 +2217,7 @@ static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc)
|
||||
int err = 0;
|
||||
|
||||
ata_tf_to_fis(&qc->tf, link->pmp, 1, (void *)fis);
|
||||
err = mv_send_fis(ap, fis, sizeof(fis) / sizeof(fis[0]));
|
||||
err = mv_send_fis(ap, fis, ARRAY_SIZE(fis));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -1975,7 +1975,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
|
||||
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
|
||||
|
||||
if (strncmp(model_num, "Maxtor", 6) == 0) {
|
||||
ata_scsi_change_queue_depth(sdev, 1);
|
||||
ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
|
||||
ata_dev_printk(dev, KERN_NOTICE,
|
||||
"Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
|
||||
}
|
||||
|
||||
@@ -417,6 +417,10 @@ static struct ata_port_operations sil24_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int sata_sil24_msi; /* Disable MSI */
|
||||
module_param_named(msi, sata_sil24_msi, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(msi, "Enable MSI (Default: false)");
|
||||
|
||||
/*
|
||||
* Use bits 30-31 of port_flags to encode available port numbers.
|
||||
* Current maxium is 4.
|
||||
@@ -1340,6 +1344,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
sil24_init_controller(host);
|
||||
|
||||
if (sata_sil24_msi && !pci_enable_msi(pdev)) {
|
||||
dev_printk(KERN_INFO, &pdev->dev, "Using MSI\n");
|
||||
pci_intx(pdev, 0);
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
return ata_host_activate(host, pdev->irq, sil24_interrupt, IRQF_SHARED,
|
||||
&sil24_sht);
|
||||
|
||||
@@ -2351,6 +2351,7 @@ static void __init amb_check_args (void) {
|
||||
MODULE_AUTHOR(maintainer_string);
|
||||
MODULE_DESCRIPTION(description_string);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("atmsar11.fw");
|
||||
module_param(debug, ushort, 0644);
|
||||
module_param(cmds, uint, 0);
|
||||
module_param(txs, uint, 0);
|
||||
|
||||
@@ -2906,8 +2906,8 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
|
||||
u32 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type));
|
||||
u32 oc3_index;
|
||||
|
||||
if ((media_index < 0) || (media_index > 4))
|
||||
media_index = 5;
|
||||
if (media_index > 4)
|
||||
media_index = 5;
|
||||
|
||||
switch (fore200e->loop_mode) {
|
||||
case ATM_LM_NONE: oc3_index = 0;
|
||||
|
||||
@@ -2505,7 +2505,7 @@ he_close(struct atm_vcc *vcc)
|
||||
* TBRQ, the host issues the close command to the adapter.
|
||||
*/
|
||||
|
||||
while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) &&
|
||||
while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
|
||||
(retry < MAX_RETRY)) {
|
||||
msleep(sleep);
|
||||
if (sleep < 250)
|
||||
@@ -2514,7 +2514,7 @@ he_close(struct atm_vcc *vcc)
|
||||
++retry;
|
||||
}
|
||||
|
||||
if (tx_inuse)
|
||||
if (tx_inuse > 1)
|
||||
hprintk("close tx cid 0x%x tx_inuse = %d\n", cid, tx_inuse);
|
||||
|
||||
/* 2.3.1.1 generic close operations with flush */
|
||||
@@ -2739,7 +2739,7 @@ he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg)
|
||||
spin_lock_irqsave(&he_dev->global_lock, flags);
|
||||
switch (reg.type) {
|
||||
case HE_REGTYPE_PCI:
|
||||
if (reg.addr < 0 || reg.addr >= HE_REGMAP_SIZE) {
|
||||
if (reg.addr >= HE_REGMAP_SIZE) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1132,7 +1132,7 @@ static int rx_pkt(struct atm_dev *dev)
|
||||
IF_ERR(printk(" cause: packet time out\n");)
|
||||
}
|
||||
else {
|
||||
IF_ERR(printk(" cause: buffer over flow\n");)
|
||||
IF_ERR(printk(" cause: buffer overflow\n");)
|
||||
}
|
||||
goto out_free_desc;
|
||||
}
|
||||
|
||||
@@ -142,6 +142,9 @@ MODULE_AUTHOR("Traverse Technologies <support@traverse.com.au>");
|
||||
MODULE_DESCRIPTION("Solos PCI driver");
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("solos-FPGA.bin");
|
||||
MODULE_FIRMWARE("solos-Firmware.bin");
|
||||
MODULE_FIRMWARE("solos-db-FPGA.bin");
|
||||
MODULE_PARM_DESC(reset, "Reset Solos chips on startup");
|
||||
MODULE_PARM_DESC(atmdebug, "Print ATM data");
|
||||
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
|
||||
@@ -528,34 +531,37 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||
int numblocks = 0;
|
||||
int offset;
|
||||
|
||||
if (chip == 0) {
|
||||
switch (chip) {
|
||||
case 0:
|
||||
fw_name = "solos-FPGA.bin";
|
||||
blocksize = FPGA_BLOCK;
|
||||
}
|
||||
|
||||
if (chip == 1) {
|
||||
break;
|
||||
case 1:
|
||||
fw_name = "solos-Firmware.bin";
|
||||
blocksize = SOLOS_BLOCK;
|
||||
}
|
||||
|
||||
if (chip == 2){
|
||||
break;
|
||||
case 2:
|
||||
if (card->fpga_version > LEGACY_BUFFERS){
|
||||
fw_name = "solos-db-FPGA.bin";
|
||||
blocksize = FPGA_BLOCK;
|
||||
} else {
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support"
|
||||
" daughter board upgrades\n");
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
if (chip == 3){
|
||||
break;
|
||||
case 3:
|
||||
if (card->fpga_version > LEGACY_BUFFERS){
|
||||
fw_name = "solos-Firmware.bin";
|
||||
blocksize = SOLOS_BLOCK;
|
||||
} else {
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
|
||||
return -EPERM;
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support"
|
||||
" daughter board upgrades\n");
|
||||
return -EPERM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (request_firmware(&fw, fw_name, &card->dev->dev))
|
||||
|
||||
@@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev)
|
||||
*/
|
||||
const char *dev_driver_string(const struct device *dev)
|
||||
{
|
||||
return dev->driver ? dev->driver->name :
|
||||
struct device_driver *drv;
|
||||
|
||||
/* dev->driver can change to NULL underneath us because of unbinding,
|
||||
* so be careful about accessing it. dev->bus and dev->class should
|
||||
* never change once they are set, so they don't need special care.
|
||||
*/
|
||||
drv = ACCESS_ONCE(dev->driver);
|
||||
return drv ? drv->name :
|
||||
(dev->bus ? dev->bus->name :
|
||||
(dev->class ? dev->class->name : ""));
|
||||
}
|
||||
@@ -986,6 +993,8 @@ int device_add(struct device *dev)
|
||||
AttrsError:
|
||||
device_remove_class_symlinks(dev);
|
||||
SymlinkError:
|
||||
if (MAJOR(dev->devt))
|
||||
devtmpfs_delete_node(dev);
|
||||
if (MAJOR(dev->devt))
|
||||
device_remove_sys_dev_entry(dev);
|
||||
devtattrError:
|
||||
@@ -1728,8 +1737,5 @@ void device_shutdown(void)
|
||||
dev->driver->shutdown(dev);
|
||||
}
|
||||
}
|
||||
kobject_put(sysfs_dev_char_kobj);
|
||||
kobject_put(sysfs_dev_block_kobj);
|
||||
kobject_put(dev_kobj);
|
||||
async_synchronize_full();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut
|
||||
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
||||
ssize_t ret;
|
||||
|
||||
cpu_hotplug_driver_lock();
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
ret = cpu_down(cpu->sysdev.id);
|
||||
@@ -49,6 +50,7 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
cpu_hotplug_driver_unlock();
|
||||
|
||||
if (ret >= 0)
|
||||
ret = count;
|
||||
@@ -72,6 +74,38 @@ void unregister_cpu(struct cpu *cpu)
|
||||
per_cpu(cpu_sys_devices, logical_cpu) = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
static ssize_t cpu_probe_store(struct class *class, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return arch_cpu_probe(buf, count);
|
||||
}
|
||||
|
||||
static ssize_t cpu_release_store(struct class *class, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return arch_cpu_release(buf, count);
|
||||
}
|
||||
|
||||
static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
|
||||
static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
|
||||
|
||||
int __init cpu_probe_release_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
|
||||
&class_attr_probe.attr);
|
||||
if (!rc)
|
||||
rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
|
||||
&class_attr_release.attr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
device_initcall(cpu_probe_release_init);
|
||||
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
|
||||
|
||||
#else /* ... !CONFIG_HOTPLUG_CPU */
|
||||
static inline void register_cpu_control(struct cpu *cpu)
|
||||
{
|
||||
@@ -97,7 +131,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute
|
||||
* boot up and this data does not change there after. Hence this
|
||||
* operation should be safe. No locking required.
|
||||
*/
|
||||
addr = __pa(per_cpu_ptr(crash_notes, cpunum));
|
||||
addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));
|
||||
rc = sprintf(buf, "%Lx\n", addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
|
||||
* @dev: device to try to bind to the driver
|
||||
*
|
||||
* This function returns -ENODEV if the device is not registered,
|
||||
* 1 if the device is bound sucessfully and 0 otherwise.
|
||||
* 1 if the device is bound successfully and 0 otherwise.
|
||||
*
|
||||
* This function must be called with @dev->sem held. When called for a
|
||||
* USB interface, @dev->parent->sem must be held as well.
|
||||
|
||||
@@ -32,6 +32,8 @@ static int dev_mount = 1;
|
||||
static int dev_mount;
|
||||
#endif
|
||||
|
||||
static rwlock_t dirlock;
|
||||
|
||||
static int __init mount_param(char *str)
|
||||
{
|
||||
dev_mount = simple_strtoul(str, NULL, 0);
|
||||
@@ -74,47 +76,35 @@ static int dev_mkdir(const char *name, mode_t mode)
|
||||
dentry = lookup_create(&nd, 1);
|
||||
if (!IS_ERR(dentry)) {
|
||||
err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
|
||||
if (!err)
|
||||
/* mark as kernel-created inode */
|
||||
dentry->d_inode->i_private = &dev_mnt;
|
||||
dput(dentry);
|
||||
} else {
|
||||
err = PTR_ERR(dentry);
|
||||
}
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
path_put(&nd.path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int create_path(const char *nodepath)
|
||||
{
|
||||
char *path;
|
||||
struct nameidata nd;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
path = kstrdup(nodepath, GFP_KERNEL);
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
|
||||
path, LOOKUP_PARENT, &nd);
|
||||
if (err == 0) {
|
||||
struct dentry *dentry;
|
||||
|
||||
/* create directory right away */
|
||||
dentry = lookup_create(&nd, 1);
|
||||
if (!IS_ERR(dentry)) {
|
||||
err = vfs_mkdir(nd.path.dentry->d_inode,
|
||||
dentry, 0755);
|
||||
dput(dentry);
|
||||
}
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
|
||||
path_put(&nd.path);
|
||||
} else if (err == -ENOENT) {
|
||||
read_lock(&dirlock);
|
||||
err = dev_mkdir(nodepath, 0755);
|
||||
if (err == -ENOENT) {
|
||||
char *path;
|
||||
char *s;
|
||||
|
||||
/* parent directories do not exist, create them */
|
||||
path = kstrdup(nodepath, GFP_KERNEL);
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
s = path;
|
||||
while (1) {
|
||||
for (;;) {
|
||||
s = strchr(s, '/');
|
||||
if (!s)
|
||||
break;
|
||||
@@ -125,9 +115,9 @@ static int create_path(const char *nodepath)
|
||||
s[0] = '/';
|
||||
s++;
|
||||
}
|
||||
kfree(path);
|
||||
}
|
||||
|
||||
kfree(path);
|
||||
read_unlock(&dirlock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -156,34 +146,40 @@ int devtmpfs_create_node(struct device *dev)
|
||||
mode |= S_IFCHR;
|
||||
|
||||
curr_cred = override_creds(&init_cred);
|
||||
|
||||
err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
|
||||
nodename, LOOKUP_PARENT, &nd);
|
||||
if (err == -ENOENT) {
|
||||
/* create missing parent directories */
|
||||
create_path(nodename);
|
||||
err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
|
||||
nodename, LOOKUP_PARENT, &nd);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
dentry = lookup_create(&nd, 0);
|
||||
if (!IS_ERR(dentry)) {
|
||||
int umask;
|
||||
|
||||
umask = sys_umask(0000);
|
||||
err = vfs_mknod(nd.path.dentry->d_inode,
|
||||
dentry, mode, dev->devt);
|
||||
sys_umask(umask);
|
||||
/* mark as kernel created inode */
|
||||
if (!err)
|
||||
if (!err) {
|
||||
struct iattr newattrs;
|
||||
|
||||
/* fixup possibly umasked mode */
|
||||
newattrs.ia_mode = mode;
|
||||
newattrs.ia_valid = ATTR_MODE;
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
notify_change(dentry, &newattrs);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
|
||||
/* mark as kernel-created inode */
|
||||
dentry->d_inode->i_private = &dev_mnt;
|
||||
}
|
||||
dput(dentry);
|
||||
} else {
|
||||
err = PTR_ERR(dentry);
|
||||
}
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
path_put(&nd.path);
|
||||
out:
|
||||
kfree(tmp);
|
||||
@@ -205,16 +201,21 @@ static int dev_rmdir(const char *name)
|
||||
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
|
||||
if (!IS_ERR(dentry)) {
|
||||
if (dentry->d_inode)
|
||||
err = vfs_rmdir(nd.path.dentry->d_inode, dentry);
|
||||
else
|
||||
if (dentry->d_inode) {
|
||||
if (dentry->d_inode->i_private == &dev_mnt)
|
||||
err = vfs_rmdir(nd.path.dentry->d_inode,
|
||||
dentry);
|
||||
else
|
||||
err = -EPERM;
|
||||
} else {
|
||||
err = -ENOENT;
|
||||
}
|
||||
dput(dentry);
|
||||
} else {
|
||||
err = PTR_ERR(dentry);
|
||||
}
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
path_put(&nd.path);
|
||||
return err;
|
||||
}
|
||||
@@ -228,7 +229,8 @@ static int delete_path(const char *nodepath)
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
while (1) {
|
||||
write_lock(&dirlock);
|
||||
for (;;) {
|
||||
char *base;
|
||||
|
||||
base = strrchr(path, '/');
|
||||
@@ -239,6 +241,7 @@ static int delete_path(const char *nodepath)
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
write_unlock(&dirlock);
|
||||
|
||||
kfree(path);
|
||||
return err;
|
||||
@@ -322,9 +325,8 @@ int devtmpfs_delete_node(struct device *dev)
|
||||
* If configured, or requested by the commandline, devtmpfs will be
|
||||
* auto-mounted after the kernel mounted the root filesystem.
|
||||
*/
|
||||
int devtmpfs_mount(const char *mountpoint)
|
||||
int devtmpfs_mount(const char *mntdir)
|
||||
{
|
||||
struct path path;
|
||||
int err;
|
||||
|
||||
if (!dev_mount)
|
||||
@@ -333,15 +335,11 @@ int devtmpfs_mount(const char *mountpoint)
|
||||
if (!dev_mnt)
|
||||
return 0;
|
||||
|
||||
err = kern_path(mountpoint, LOOKUP_FOLLOW, &path);
|
||||
if (err)
|
||||
return err;
|
||||
err = do_add_mount(dev_mnt, &path, 0, NULL);
|
||||
err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
|
||||
if (err)
|
||||
printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
|
||||
else
|
||||
printk(KERN_INFO "devtmpfs: mounted\n");
|
||||
path_put(&path);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -354,6 +352,8 @@ int __init devtmpfs_init(void)
|
||||
int err;
|
||||
struct vfsmount *mnt;
|
||||
|
||||
rwlock_init(&dirlock);
|
||||
|
||||
err = register_filesystem(&dev_fs_type);
|
||||
if (err) {
|
||||
printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
|
||||
@@ -361,7 +361,7 @@ int __init devtmpfs_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
mnt = kern_mount(&dev_fs_type);
|
||||
mnt = kern_mount_data(&dev_fs_type, "mode=0755");
|
||||
if (IS_ERR(mnt)) {
|
||||
err = PTR_ERR(mnt);
|
||||
printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
|
||||
|
||||
@@ -601,12 +601,9 @@ request_firmware_work_func(void *arg)
|
||||
}
|
||||
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
|
||||
fw_work->uevent);
|
||||
if (ret < 0)
|
||||
fw_work->cont(NULL, fw_work->context);
|
||||
else {
|
||||
fw_work->cont(fw, fw_work->context);
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
fw_work->cont(fw, fw_work->context);
|
||||
|
||||
module_put(fw_work->module);
|
||||
kfree(fw_work);
|
||||
return ret;
|
||||
@@ -619,6 +616,7 @@ request_firmware_work_func(void *arg)
|
||||
* is non-zero else the firmware copy must be done manually.
|
||||
* @name: name of firmware file
|
||||
* @device: device for which firmware is being loaded
|
||||
* @gfp: allocation flags
|
||||
* @context: will be passed over to @cont, and
|
||||
* @fw may be %NULL if firmware request fails.
|
||||
* @cont: function will be called asynchronously when the firmware
|
||||
@@ -631,12 +629,12 @@ request_firmware_work_func(void *arg)
|
||||
int
|
||||
request_firmware_nowait(
|
||||
struct module *module, int uevent,
|
||||
const char *name, struct device *device, void *context,
|
||||
const char *name, struct device *device, gfp_t gfp, void *context,
|
||||
void (*cont)(const struct firmware *fw, void *context))
|
||||
{
|
||||
struct task_struct *task;
|
||||
struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
|
||||
GFP_ATOMIC);
|
||||
gfp);
|
||||
|
||||
if (!fw_work)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1000,7 +1000,7 @@ static __initdata LIST_HEAD(early_platform_device_list);
|
||||
int __init early_platform_driver_register(struct early_platform_driver *epdrv,
|
||||
char *buf)
|
||||
{
|
||||
unsigned long index;
|
||||
char *tmp;
|
||||
int n;
|
||||
|
||||
/* Simply add the driver to the end of the global list.
|
||||
@@ -1019,13 +1019,28 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
|
||||
if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
|
||||
list_move(&epdrv->list, &early_platform_driver_list);
|
||||
|
||||
if (!strcmp(buf, epdrv->pdrv->driver.name))
|
||||
/* Allow passing parameters after device name */
|
||||
if (buf[n] == '\0' || buf[n] == ',')
|
||||
epdrv->requested_id = -1;
|
||||
else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
|
||||
&index) == 0)
|
||||
epdrv->requested_id = index;
|
||||
else
|
||||
epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
|
||||
else {
|
||||
epdrv->requested_id = simple_strtoul(&buf[n + 1],
|
||||
&tmp, 10);
|
||||
|
||||
if (buf[n] != '.' || (tmp == &buf[n + 1])) {
|
||||
epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
|
||||
n = 0;
|
||||
} else
|
||||
n += strcspn(&buf[n + 1], ",") + 1;
|
||||
}
|
||||
|
||||
if (buf[n] == ',')
|
||||
n++;
|
||||
|
||||
if (epdrv->bufsize) {
|
||||
memcpy(epdrv->buffer, &buf[n],
|
||||
min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
|
||||
epdrv->buffer[epdrv->bufsize - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -185,6 +185,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
|
||||
}
|
||||
|
||||
dev->power.runtime_status = RPM_SUSPENDING;
|
||||
dev->power.deferred_resume = false;
|
||||
|
||||
if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
@@ -200,7 +201,6 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
|
||||
if (retval) {
|
||||
dev->power.runtime_status = RPM_ACTIVE;
|
||||
pm_runtime_cancel_pending(dev);
|
||||
dev->power.deferred_resume = false;
|
||||
|
||||
if (retval == -EAGAIN || retval == -EBUSY) {
|
||||
notify = true;
|
||||
@@ -217,7 +217,6 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
|
||||
wake_up_all(&dev->power.wait_queue);
|
||||
|
||||
if (dev->power.deferred_resume) {
|
||||
dev->power.deferred_resume = false;
|
||||
__pm_runtime_resume(dev, false);
|
||||
retval = -EAGAIN;
|
||||
goto out;
|
||||
@@ -626,6 +625,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
|
||||
goto out;
|
||||
|
||||
dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
|
||||
if (!dev->power.timer_expires)
|
||||
dev->power.timer_expires = 1;
|
||||
mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
|
||||
|
||||
out:
|
||||
@@ -659,13 +660,17 @@ static int __pm_request_resume(struct device *dev)
|
||||
|
||||
pm_runtime_deactivate_timer(dev);
|
||||
|
||||
if (dev->power.runtime_status == RPM_SUSPENDING) {
|
||||
dev->power.deferred_resume = true;
|
||||
return retval;
|
||||
}
|
||||
if (dev->power.request_pending) {
|
||||
/* If non-resume request is pending, we can overtake it. */
|
||||
dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
|
||||
return retval;
|
||||
} else if (retval) {
|
||||
return retval;
|
||||
}
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
dev->power.request = RPM_REQ_RESUME;
|
||||
dev->power.request_pending = true;
|
||||
@@ -777,7 +782,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
spin_lock(&parent->power.lock);
|
||||
spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING);
|
||||
|
||||
/*
|
||||
* It is invalid to put an active child under a parent that is
|
||||
@@ -786,12 +791,10 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
|
||||
*/
|
||||
if (!parent->power.disable_depth
|
||||
&& !parent->power.ignore_children
|
||||
&& parent->power.runtime_status != RPM_ACTIVE) {
|
||||
&& parent->power.runtime_status != RPM_ACTIVE)
|
||||
error = -EBUSY;
|
||||
} else {
|
||||
if (dev->power.runtime_status == RPM_SUSPENDED)
|
||||
atomic_inc(&parent->power.child_count);
|
||||
}
|
||||
else if (dev->power.runtime_status == RPM_SUSPENDED)
|
||||
atomic_inc(&parent->power.child_count);
|
||||
|
||||
spin_unlock(&parent->power.lock);
|
||||
|
||||
|
||||
@@ -271,6 +271,8 @@ config BLK_DEV_CRYPTOLOOP
|
||||
instead, which can be configured to be on-disk compatible with the
|
||||
cryptoloop device.
|
||||
|
||||
source "drivers/block/drbd/Kconfig"
|
||||
|
||||
config BLK_DEV_NBD
|
||||
tristate "Network block device support"
|
||||
depends on NET
|
||||
|
||||
@@ -36,5 +36,6 @@ obj-$(CONFIG_BLK_DEV_UB) += ub.o
|
||||
obj-$(CONFIG_BLK_DEV_HD) += hd.o
|
||||
|
||||
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
|
||||
obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
|
||||
|
||||
swim_mod-objs := swim.o swim_asm.o
|
||||
|
||||
@@ -1478,10 +1478,7 @@ void do_fd_request(struct request_queue * q)
|
||||
stdma_lock(floppy_irq, NULL);
|
||||
|
||||
atari_disable_irq( IRQ_MFP_FDC );
|
||||
local_save_flags(flags); /* The request function is called with ints
|
||||
local_irq_disable(); * disabled... so must save the IPL for later */
|
||||
redo_fd_request();
|
||||
local_irq_restore(flags);
|
||||
atari_enable_irq( IRQ_MFP_FDC );
|
||||
}
|
||||
|
||||
|
||||
@@ -179,19 +179,17 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time, int via_ioctl);
|
||||
static int deregister_disk(ctlr_info_t *h, int drv_index,
|
||||
int clear_all, int via_ioctl);
|
||||
|
||||
static void cciss_read_capacity(int ctlr, int logvol, int withirq,
|
||||
static void cciss_read_capacity(int ctlr, int logvol,
|
||||
sector_t *total_size, unsigned int *block_size);
|
||||
static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
|
||||
static void cciss_read_capacity_16(int ctlr, int logvol,
|
||||
sector_t *total_size, unsigned int *block_size);
|
||||
static void cciss_geometry_inquiry(int ctlr, int logvol,
|
||||
int withirq, sector_t total_size,
|
||||
sector_t total_size,
|
||||
unsigned int block_size, InquiryData_struct *inq_buff,
|
||||
drive_info_struct *drv);
|
||||
static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
|
||||
__u32);
|
||||
static void start_io(ctlr_info_t *h);
|
||||
static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
|
||||
__u8 page_code, unsigned char *scsi3addr, int cmd_type);
|
||||
static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
|
||||
__u8 page_code, unsigned char scsi3addr[],
|
||||
int cmd_type);
|
||||
@@ -424,12 +422,9 @@ cciss_proc_write(struct file *file, const char __user *buf,
|
||||
if (strncmp(ENGAGE_SCSI, buffer, sizeof ENGAGE_SCSI - 1) == 0) {
|
||||
struct seq_file *seq = file->private_data;
|
||||
ctlr_info_t *h = seq->private;
|
||||
int rc;
|
||||
|
||||
rc = cciss_engage_scsi(h->ctlr);
|
||||
if (rc != 0)
|
||||
err = -rc;
|
||||
else
|
||||
err = cciss_engage_scsi(h->ctlr);
|
||||
if (err == 0)
|
||||
err = length;
|
||||
} else
|
||||
#endif /* CONFIG_CISS_SCSI_TAPE */
|
||||
@@ -1657,9 +1652,11 @@ static void cciss_softirq_done(struct request *rq)
|
||||
{
|
||||
CommandList_struct *cmd = rq->completion_data;
|
||||
ctlr_info_t *h = hba[cmd->ctlr];
|
||||
SGDescriptor_struct *curr_sg = cmd->SG;
|
||||
unsigned long flags;
|
||||
u64bit temp64;
|
||||
int i, ddir;
|
||||
int sg_index = 0;
|
||||
|
||||
if (cmd->Request.Type.Direction == XFER_READ)
|
||||
ddir = PCI_DMA_FROMDEVICE;
|
||||
@@ -1669,9 +1666,22 @@ static void cciss_softirq_done(struct request *rq)
|
||||
/* command did not need to be retried */
|
||||
/* unmap the DMA mapping for all the scatter gather elements */
|
||||
for (i = 0; i < cmd->Header.SGList; i++) {
|
||||
temp64.val32.lower = cmd->SG[i].Addr.lower;
|
||||
temp64.val32.upper = cmd->SG[i].Addr.upper;
|
||||
pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
|
||||
if (curr_sg[sg_index].Ext == CCISS_SG_CHAIN) {
|
||||
temp64.val32.lower = cmd->SG[i].Addr.lower;
|
||||
temp64.val32.upper = cmd->SG[i].Addr.upper;
|
||||
pci_dma_sync_single_for_cpu(h->pdev, temp64.val,
|
||||
cmd->SG[i].Len, ddir);
|
||||
pci_unmap_single(h->pdev, temp64.val,
|
||||
cmd->SG[i].Len, ddir);
|
||||
/* Point to the next block */
|
||||
curr_sg = h->cmd_sg_list[cmd->cmdindex]->sgchain;
|
||||
sg_index = 0;
|
||||
}
|
||||
temp64.val32.lower = curr_sg[sg_index].Addr.lower;
|
||||
temp64.val32.upper = curr_sg[sg_index].Addr.upper;
|
||||
pci_unmap_page(h->pdev, temp64.val, curr_sg[sg_index].Len,
|
||||
ddir);
|
||||
++sg_index;
|
||||
}
|
||||
|
||||
#ifdef CCISS_DEBUG
|
||||
@@ -1701,7 +1711,7 @@ static inline void log_unit_to_scsi3addr(ctlr_info_t *h,
|
||||
* via the inquiry page 0. Model, vendor, and rev are set to empty strings if
|
||||
* they cannot be read.
|
||||
*/
|
||||
static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
|
||||
static void cciss_get_device_descr(int ctlr, int logvol,
|
||||
char *vendor, char *model, char *rev)
|
||||
{
|
||||
int rc;
|
||||
@@ -1717,14 +1727,8 @@ static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
|
||||
return;
|
||||
|
||||
log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
|
||||
if (withirq)
|
||||
rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf,
|
||||
sizeof(InquiryData_struct), 0,
|
||||
scsi3addr, TYPE_CMD);
|
||||
else
|
||||
rc = sendcmd(CISS_INQUIRY, ctlr, inq_buf,
|
||||
sizeof(InquiryData_struct), 0,
|
||||
scsi3addr, TYPE_CMD);
|
||||
rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf, sizeof(*inq_buf), 0,
|
||||
scsi3addr, TYPE_CMD);
|
||||
if (rc == IO_OK) {
|
||||
memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN);
|
||||
vendor[VENDOR_LEN] = '\0';
|
||||
@@ -1743,7 +1747,7 @@ static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
|
||||
* number cannot be had, for whatever reason, 16 bytes of 0xff
|
||||
* are returned instead.
|
||||
*/
|
||||
static void cciss_get_serial_no(int ctlr, int logvol, int withirq,
|
||||
static void cciss_get_serial_no(int ctlr, int logvol,
|
||||
unsigned char *serial_no, int buflen)
|
||||
{
|
||||
#define PAGE_83_INQ_BYTES 64
|
||||
@@ -1759,12 +1763,8 @@ static void cciss_get_serial_no(int ctlr, int logvol, int withirq,
|
||||
return;
|
||||
memset(serial_no, 0, buflen);
|
||||
log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
|
||||
if (withirq)
|
||||
rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf,
|
||||
PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
|
||||
else
|
||||
rc = sendcmd(CISS_INQUIRY, ctlr, buf,
|
||||
PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
|
||||
rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf,
|
||||
PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
|
||||
if (rc == IO_OK)
|
||||
memcpy(serial_no, &buf[8], buflen);
|
||||
kfree(buf);
|
||||
@@ -1793,10 +1793,10 @@ static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
|
||||
blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
|
||||
|
||||
/* This is a hardware imposed limit. */
|
||||
blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
|
||||
blk_queue_max_hw_segments(disk->queue, h->maxsgentries);
|
||||
|
||||
/* This is a limit in the driver and could be eliminated. */
|
||||
blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
|
||||
blk_queue_max_phys_segments(disk->queue, h->maxsgentries);
|
||||
|
||||
blk_queue_max_sectors(disk->queue, h->cciss_max_sectors);
|
||||
|
||||
@@ -1852,18 +1852,16 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time,
|
||||
|
||||
/* testing to see if 16-byte CDBs are already being used */
|
||||
if (h->cciss_read == CCISS_READ_16) {
|
||||
cciss_read_capacity_16(h->ctlr, drv_index, 1,
|
||||
cciss_read_capacity_16(h->ctlr, drv_index,
|
||||
&total_size, &block_size);
|
||||
|
||||
} else {
|
||||
cciss_read_capacity(ctlr, drv_index, 1,
|
||||
&total_size, &block_size);
|
||||
|
||||
cciss_read_capacity(ctlr, drv_index, &total_size, &block_size);
|
||||
/* if read_capacity returns all F's this volume is >2TB */
|
||||
/* in size so we switch to 16-byte CDB's for all */
|
||||
/* read/write ops */
|
||||
if (total_size == 0xFFFFFFFFULL) {
|
||||
cciss_read_capacity_16(ctlr, drv_index, 1,
|
||||
cciss_read_capacity_16(ctlr, drv_index,
|
||||
&total_size, &block_size);
|
||||
h->cciss_read = CCISS_READ_16;
|
||||
h->cciss_write = CCISS_WRITE_16;
|
||||
@@ -1873,14 +1871,14 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time,
|
||||
}
|
||||
}
|
||||
|
||||
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
|
||||
cciss_geometry_inquiry(ctlr, drv_index, total_size, block_size,
|
||||
inq_buff, drvinfo);
|
||||
drvinfo->block_size = block_size;
|
||||
drvinfo->nr_blocks = total_size + 1;
|
||||
|
||||
cciss_get_device_descr(ctlr, drv_index, 1, drvinfo->vendor,
|
||||
cciss_get_device_descr(ctlr, drv_index, drvinfo->vendor,
|
||||
drvinfo->model, drvinfo->rev);
|
||||
cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no,
|
||||
cciss_get_serial_no(ctlr, drv_index, drvinfo->serial_no,
|
||||
sizeof(drvinfo->serial_no));
|
||||
/* Save the lunid in case we deregister the disk, below. */
|
||||
memcpy(drvinfo->LunID, h->drv[drv_index]->LunID,
|
||||
@@ -2531,6 +2529,8 @@ static int check_target_status(ctlr_info_t *h, CommandList_struct *c)
|
||||
case 0: return IO_OK; /* no sense */
|
||||
case 1: return IO_OK; /* recovered error */
|
||||
default:
|
||||
if (check_for_unit_attention(h, c))
|
||||
return IO_NEEDS_RETRY;
|
||||
printk(KERN_WARNING "cciss%d: cmd 0x%02x "
|
||||
"check condition, sense key = 0x%02x\n",
|
||||
h->ctlr, c->Request.CDB[0],
|
||||
@@ -2672,7 +2672,7 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
|
||||
}
|
||||
|
||||
static void cciss_geometry_inquiry(int ctlr, int logvol,
|
||||
int withirq, sector_t total_size,
|
||||
sector_t total_size,
|
||||
unsigned int block_size,
|
||||
InquiryData_struct *inq_buff,
|
||||
drive_info_struct *drv)
|
||||
@@ -2683,14 +2683,8 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
|
||||
|
||||
memset(inq_buff, 0, sizeof(InquiryData_struct));
|
||||
log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
|
||||
if (withirq)
|
||||
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
|
||||
inq_buff, sizeof(*inq_buff),
|
||||
0xC1, scsi3addr, TYPE_CMD);
|
||||
else
|
||||
return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
|
||||
sizeof(*inq_buff), 0xC1, scsi3addr,
|
||||
TYPE_CMD);
|
||||
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff,
|
||||
sizeof(*inq_buff), 0xC1, scsi3addr, TYPE_CMD);
|
||||
if (return_code == IO_OK) {
|
||||
if (inq_buff->data_byte[8] == 0xFF) {
|
||||
printk(KERN_WARNING
|
||||
@@ -2723,7 +2717,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
|
||||
}
|
||||
|
||||
static void
|
||||
cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
|
||||
cciss_read_capacity(int ctlr, int logvol, sector_t *total_size,
|
||||
unsigned int *block_size)
|
||||
{
|
||||
ReadCapdata_struct *buf;
|
||||
@@ -2737,14 +2731,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
|
||||
}
|
||||
|
||||
log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
|
||||
if (withirq)
|
||||
return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
|
||||
ctlr, buf, sizeof(ReadCapdata_struct),
|
||||
0, scsi3addr, TYPE_CMD);
|
||||
else
|
||||
return_code = sendcmd(CCISS_READ_CAPACITY,
|
||||
ctlr, buf, sizeof(ReadCapdata_struct),
|
||||
0, scsi3addr, TYPE_CMD);
|
||||
return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, buf,
|
||||
sizeof(ReadCapdata_struct), 0, scsi3addr, TYPE_CMD);
|
||||
if (return_code == IO_OK) {
|
||||
*total_size = be32_to_cpu(*(__be32 *) buf->total_size);
|
||||
*block_size = be32_to_cpu(*(__be32 *) buf->block_size);
|
||||
@@ -2756,8 +2744,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size)
|
||||
static void cciss_read_capacity_16(int ctlr, int logvol,
|
||||
sector_t *total_size, unsigned int *block_size)
|
||||
{
|
||||
ReadCapdata_struct_16 *buf;
|
||||
int return_code;
|
||||
@@ -2770,16 +2758,9 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
|
||||
}
|
||||
|
||||
log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
|
||||
if (withirq) {
|
||||
return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
|
||||
ctlr, buf, sizeof(ReadCapdata_struct_16),
|
||||
0, scsi3addr, TYPE_CMD);
|
||||
}
|
||||
else {
|
||||
return_code = sendcmd(CCISS_READ_CAPACITY_16,
|
||||
ctlr, buf, sizeof(ReadCapdata_struct_16),
|
||||
0, scsi3addr, TYPE_CMD);
|
||||
}
|
||||
return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
|
||||
ctlr, buf, sizeof(ReadCapdata_struct_16),
|
||||
0, scsi3addr, TYPE_CMD);
|
||||
if (return_code == IO_OK) {
|
||||
*total_size = be64_to_cpu(*(__be64 *) buf->total_size);
|
||||
*block_size = be32_to_cpu(*(__be32 *) buf->block_size);
|
||||
@@ -2820,13 +2801,13 @@ static int cciss_revalidate(struct gendisk *disk)
|
||||
return 1;
|
||||
}
|
||||
if (h->cciss_read == CCISS_READ_10) {
|
||||
cciss_read_capacity(h->ctlr, logvol, 1,
|
||||
cciss_read_capacity(h->ctlr, logvol,
|
||||
&total_size, &block_size);
|
||||
} else {
|
||||
cciss_read_capacity_16(h->ctlr, logvol, 1,
|
||||
cciss_read_capacity_16(h->ctlr, logvol,
|
||||
&total_size, &block_size);
|
||||
}
|
||||
cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
|
||||
cciss_geometry_inquiry(h->ctlr, logvol, total_size, block_size,
|
||||
inq_buff, drv);
|
||||
|
||||
blk_queue_logical_block_size(drv->queue, drv->block_size);
|
||||
@@ -2836,167 +2817,6 @@ static int cciss_revalidate(struct gendisk *disk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait polling for a command to complete.
|
||||
* The memory mapped FIFO is polled for the completion.
|
||||
* Used only at init time, interrupts from the HBA are disabled.
|
||||
*/
|
||||
static unsigned long pollcomplete(int ctlr)
|
||||
{
|
||||
unsigned long done;
|
||||
int i;
|
||||
|
||||
/* Wait (up to 20 seconds) for a command to complete */
|
||||
|
||||
for (i = 20 * HZ; i > 0; i--) {
|
||||
done = hba[ctlr]->access.command_completed(hba[ctlr]);
|
||||
if (done == FIFO_EMPTY)
|
||||
schedule_timeout_uninterruptible(1);
|
||||
else
|
||||
return done;
|
||||
}
|
||||
/* Invalid address to tell caller we ran out of time */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send command c to controller h and poll for it to complete.
|
||||
* Turns interrupts off on the board. Used at driver init time
|
||||
* and during SCSI error recovery.
|
||||
*/
|
||||
static int sendcmd_core(ctlr_info_t *h, CommandList_struct *c)
|
||||
{
|
||||
int i;
|
||||
unsigned long complete;
|
||||
int status = IO_ERROR;
|
||||
u64bit buff_dma_handle;
|
||||
|
||||
resend_cmd1:
|
||||
|
||||
/* Disable interrupt on the board. */
|
||||
h->access.set_intr_mask(h, CCISS_INTR_OFF);
|
||||
|
||||
/* Make sure there is room in the command FIFO */
|
||||
/* Actually it should be completely empty at this time */
|
||||
/* unless we are in here doing error handling for the scsi */
|
||||
/* tape side of the driver. */
|
||||
for (i = 200000; i > 0; i--) {
|
||||
/* if fifo isn't full go */
|
||||
if (!(h->access.fifo_full(h)))
|
||||
break;
|
||||
udelay(10);
|
||||
printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
|
||||
" waiting!\n", h->ctlr);
|
||||
}
|
||||
h->access.submit_command(h, c); /* Send the cmd */
|
||||
do {
|
||||
complete = pollcomplete(h->ctlr);
|
||||
|
||||
#ifdef CCISS_DEBUG
|
||||
printk(KERN_DEBUG "cciss: command completed\n");
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
if (complete == 1) {
|
||||
printk(KERN_WARNING
|
||||
"cciss cciss%d: SendCmd Timeout out, "
|
||||
"No command list address returned!\n", h->ctlr);
|
||||
status = IO_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure it's the command we're expecting. */
|
||||
if ((complete & ~CISS_ERROR_BIT) != c->busaddr) {
|
||||
printk(KERN_WARNING "cciss%d: Unexpected command "
|
||||
"completion.\n", h->ctlr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* It is our command. If no error, we're done. */
|
||||
if (!(complete & CISS_ERROR_BIT)) {
|
||||
status = IO_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* There is an error... */
|
||||
|
||||
/* if data overrun or underun on Report command ignore it */
|
||||
if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
|
||||
(c->Request.CDB[0] == CISS_REPORT_PHYS) ||
|
||||
(c->Request.CDB[0] == CISS_INQUIRY)) &&
|
||||
((c->err_info->CommandStatus == CMD_DATA_OVERRUN) ||
|
||||
(c->err_info->CommandStatus == CMD_DATA_UNDERRUN))) {
|
||||
complete = c->busaddr;
|
||||
status = IO_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c->err_info->CommandStatus == CMD_UNSOLICITED_ABORT) {
|
||||
printk(KERN_WARNING "cciss%d: unsolicited abort %p\n",
|
||||
h->ctlr, c);
|
||||
if (c->retry_count < MAX_CMD_RETRIES) {
|
||||
printk(KERN_WARNING "cciss%d: retrying %p\n",
|
||||
h->ctlr, c);
|
||||
c->retry_count++;
|
||||
/* erase the old error information */
|
||||
memset(c->err_info, 0, sizeof(c->err_info));
|
||||
goto resend_cmd1;
|
||||
}
|
||||
printk(KERN_WARNING "cciss%d: retried %p too many "
|
||||
"times\n", h->ctlr, c);
|
||||
status = IO_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
|
||||
printk(KERN_WARNING "cciss%d: command could not be "
|
||||
"aborted.\n", h->ctlr);
|
||||
status = IO_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c->err_info->CommandStatus == CMD_TARGET_STATUS) {
|
||||
status = check_target_status(h, c);
|
||||
break;
|
||||
}
|
||||
|
||||
printk(KERN_WARNING "cciss%d: sendcmd error\n", h->ctlr);
|
||||
printk(KERN_WARNING "cmd = 0x%02x, CommandStatus = 0x%02x\n",
|
||||
c->Request.CDB[0], c->err_info->CommandStatus);
|
||||
status = IO_ERROR;
|
||||
break;
|
||||
|
||||
} while (1);
|
||||
|
||||
/* unlock the data buffer from DMA */
|
||||
buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
|
||||
buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
|
||||
pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
|
||||
c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to the controller, and wait for it to complete.
|
||||
* Used at init time, and during SCSI error recovery.
|
||||
*/
|
||||
static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
|
||||
__u8 page_code, unsigned char *scsi3addr, int cmd_type)
|
||||
{
|
||||
CommandList_struct *c;
|
||||
int status;
|
||||
|
||||
c = cmd_alloc(hba[ctlr], 1);
|
||||
if (!c) {
|
||||
printk(KERN_WARNING "cciss: unable to get memory");
|
||||
return IO_ERROR;
|
||||
}
|
||||
status = fill_cmd(c, cmd, ctlr, buff, size, page_code,
|
||||
scsi3addr, cmd_type);
|
||||
if (status == IO_OK)
|
||||
status = sendcmd_core(hba[ctlr], c);
|
||||
cmd_free(hba[ctlr], c, 1);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map (physical) PCI mem into (virtual) kernel space
|
||||
*/
|
||||
@@ -3255,9 +3075,13 @@ static void do_cciss_request(struct request_queue *q)
|
||||
int seg;
|
||||
struct request *creq;
|
||||
u64bit temp64;
|
||||
struct scatterlist tmp_sg[MAXSGENTRIES];
|
||||
struct scatterlist *tmp_sg;
|
||||
SGDescriptor_struct *curr_sg;
|
||||
drive_info_struct *drv;
|
||||
int i, dir;
|
||||
int nseg = 0;
|
||||
int sg_index = 0;
|
||||
int chained = 0;
|
||||
|
||||
/* We call start_io here in case there is a command waiting on the
|
||||
* queue that has not been sent.
|
||||
@@ -3270,13 +3094,14 @@ static void do_cciss_request(struct request_queue *q)
|
||||
if (!creq)
|
||||
goto startio;
|
||||
|
||||
BUG_ON(creq->nr_phys_segments > MAXSGENTRIES);
|
||||
BUG_ON(creq->nr_phys_segments > h->maxsgentries);
|
||||
|
||||
if ((c = cmd_alloc(h, 1)) == NULL)
|
||||
goto full;
|
||||
|
||||
blk_start_request(creq);
|
||||
|
||||
tmp_sg = h->scatter_list[c->cmdindex];
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
|
||||
c->cmd_type = CMD_RWREQ;
|
||||
@@ -3305,7 +3130,7 @@ static void do_cciss_request(struct request_queue *q)
|
||||
(int)blk_rq_pos(creq), (int)blk_rq_sectors(creq));
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
sg_init_table(tmp_sg, MAXSGENTRIES);
|
||||
sg_init_table(tmp_sg, h->maxsgentries);
|
||||
seg = blk_rq_map_sg(q, creq, tmp_sg);
|
||||
|
||||
/* get the DMA records for the setup */
|
||||
@@ -3314,25 +3139,70 @@ static void do_cciss_request(struct request_queue *q)
|
||||
else
|
||||
dir = PCI_DMA_TODEVICE;
|
||||
|
||||
curr_sg = c->SG;
|
||||
sg_index = 0;
|
||||
chained = 0;
|
||||
|
||||
for (i = 0; i < seg; i++) {
|
||||
c->SG[i].Len = tmp_sg[i].length;
|
||||
if (((sg_index+1) == (h->max_cmd_sgentries)) &&
|
||||
!chained && ((seg - i) > 1)) {
|
||||
nseg = seg - i;
|
||||
curr_sg[sg_index].Len = (nseg) *
|
||||
sizeof(SGDescriptor_struct);
|
||||
curr_sg[sg_index].Ext = CCISS_SG_CHAIN;
|
||||
|
||||
/* Point to next chain block. */
|
||||
curr_sg = h->cmd_sg_list[c->cmdindex]->sgchain;
|
||||
sg_index = 0;
|
||||
chained = 1;
|
||||
}
|
||||
curr_sg[sg_index].Len = tmp_sg[i].length;
|
||||
temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]),
|
||||
tmp_sg[i].offset,
|
||||
tmp_sg[i].length, dir);
|
||||
c->SG[i].Addr.lower = temp64.val32.lower;
|
||||
c->SG[i].Addr.upper = temp64.val32.upper;
|
||||
c->SG[i].Ext = 0; // we are not chaining
|
||||
tmp_sg[i].offset,
|
||||
tmp_sg[i].length, dir);
|
||||
curr_sg[sg_index].Addr.lower = temp64.val32.lower;
|
||||
curr_sg[sg_index].Addr.upper = temp64.val32.upper;
|
||||
curr_sg[sg_index].Ext = 0; /* we are not chaining */
|
||||
|
||||
++sg_index;
|
||||
}
|
||||
|
||||
if (chained) {
|
||||
int len;
|
||||
curr_sg = c->SG;
|
||||
sg_index = h->max_cmd_sgentries - 1;
|
||||
len = curr_sg[sg_index].Len;
|
||||
/* Setup pointer to next chain block.
|
||||
* Fill out last element in current chain
|
||||
* block with address of next chain block.
|
||||
*/
|
||||
temp64.val = pci_map_single(h->pdev,
|
||||
h->cmd_sg_list[c->cmdindex]->sgchain,
|
||||
len, dir);
|
||||
|
||||
h->cmd_sg_list[c->cmdindex]->sg_chain_dma = temp64.val;
|
||||
curr_sg[sg_index].Addr.lower = temp64.val32.lower;
|
||||
curr_sg[sg_index].Addr.upper = temp64.val32.upper;
|
||||
|
||||
pci_dma_sync_single_for_device(h->pdev,
|
||||
h->cmd_sg_list[c->cmdindex]->sg_chain_dma,
|
||||
len, dir);
|
||||
}
|
||||
|
||||
/* track how many SG entries we are using */
|
||||
if (seg > h->maxSG)
|
||||
h->maxSG = seg;
|
||||
|
||||
#ifdef CCISS_DEBUG
|
||||
printk(KERN_DEBUG "cciss: Submitting %u sectors in %d segments\n",
|
||||
blk_rq_sectors(creq), seg);
|
||||
printk(KERN_DEBUG "cciss: Submitting %ld sectors in %d segments "
|
||||
"chained[%d]\n",
|
||||
blk_rq_sectors(creq), seg, chained);
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
c->Header.SGList = c->Header.SGTotal = seg;
|
||||
c->Header.SGList = c->Header.SGTotal = seg + chained;
|
||||
if (seg > h->max_cmd_sgentries)
|
||||
c->Header.SGList = h->max_cmd_sgentries;
|
||||
|
||||
if (likely(blk_fs_request(creq))) {
|
||||
if(h->cciss_read == CCISS_READ_10) {
|
||||
c->Request.CDB[1] = 0;
|
||||
@@ -3513,28 +3383,33 @@ static int add_to_scan_list(struct ctlr_info *h)
|
||||
* @h: Pointer to the controller.
|
||||
*
|
||||
* Removes the controller from the rescan queue if present. Blocks if
|
||||
* the controller is currently conducting a rescan.
|
||||
* the controller is currently conducting a rescan. The controller
|
||||
* can be in one of three states:
|
||||
* 1. Doesn't need a scan
|
||||
* 2. On the scan list, but not scanning yet (we remove it)
|
||||
* 3. Busy scanning (and not on the list). In this case we want to wait for
|
||||
* the scan to complete to make sure the scanning thread for this
|
||||
* controller is completely idle.
|
||||
**/
|
||||
static void remove_from_scan_list(struct ctlr_info *h)
|
||||
{
|
||||
struct ctlr_info *test_h, *tmp_h;
|
||||
int scanning = 0;
|
||||
|
||||
mutex_lock(&scan_mutex);
|
||||
list_for_each_entry_safe(test_h, tmp_h, &scan_q, scan_list) {
|
||||
if (test_h == h) {
|
||||
if (test_h == h) { /* state 2. */
|
||||
list_del(&h->scan_list);
|
||||
complete_all(&h->scan_wait);
|
||||
mutex_unlock(&scan_mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (&h->busy_scanning)
|
||||
scanning = 0;
|
||||
mutex_unlock(&scan_mutex);
|
||||
|
||||
if (scanning)
|
||||
if (h->busy_scanning) { /* state 3. */
|
||||
mutex_unlock(&scan_mutex);
|
||||
wait_for_completion(&h->scan_wait);
|
||||
} else { /* state 1, nothing to do. */
|
||||
mutex_unlock(&scan_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3573,13 +3448,11 @@ static int scan_thread(void *data)
|
||||
h->busy_scanning = 1;
|
||||
mutex_unlock(&scan_mutex);
|
||||
|
||||
if (h) {
|
||||
rebuild_lun_table(h, 0, 0);
|
||||
complete_all(&h->scan_wait);
|
||||
mutex_lock(&scan_mutex);
|
||||
h->busy_scanning = 0;
|
||||
mutex_unlock(&scan_mutex);
|
||||
}
|
||||
rebuild_lun_table(h, 0, 0);
|
||||
complete_all(&h->scan_wait);
|
||||
mutex_lock(&scan_mutex);
|
||||
h->busy_scanning = 0;
|
||||
mutex_unlock(&scan_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3605,8 +3478,22 @@ static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c)
|
||||
case REPORT_LUNS_CHANGED:
|
||||
printk(KERN_WARNING "cciss%d: report LUN data "
|
||||
"changed\n", h->ctlr);
|
||||
add_to_scan_list(h);
|
||||
wake_up_process(cciss_scan_thread);
|
||||
/*
|
||||
* Here, we could call add_to_scan_list and wake up the scan thread,
|
||||
* except that it's quite likely that we will get more than one
|
||||
* REPORT_LUNS_CHANGED condition in quick succession, which means
|
||||
* that those which occur after the first one will likely happen
|
||||
* *during* the scan_thread's rescan. And the rescan code is not
|
||||
* robust enough to restart in the middle, undoing what it has already
|
||||
* done, and it's not clear that it's even possible to do this, since
|
||||
* part of what it does is notify the block layer, which starts
|
||||
* doing it's own i/o to read partition tables and so on, and the
|
||||
* driver doesn't have visibility to know what might need undoing.
|
||||
* In any event, if possible, it is horribly complicated to get right
|
||||
* so we just don't do it for now.
|
||||
*
|
||||
* Note: this REPORT_LUNS_CHANGED condition only occurs on the MSA2012.
|
||||
*/
|
||||
return 1;
|
||||
break;
|
||||
case POWER_OR_RESET:
|
||||
@@ -3888,6 +3775,23 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
|
||||
* leave a little room for ioctl calls.
|
||||
*/
|
||||
c->max_commands = readl(&(c->cfgtable->CmdsOutMax));
|
||||
c->maxsgentries = readl(&(c->cfgtable->MaxSGElements));
|
||||
|
||||
/*
|
||||
* Limit native command to 32 s/g elements to save dma'able memory.
|
||||
* Howvever spec says if 0, use 31
|
||||
*/
|
||||
|
||||
c->max_cmd_sgentries = 31;
|
||||
if (c->maxsgentries > 512) {
|
||||
c->max_cmd_sgentries = 32;
|
||||
c->chainsize = c->maxsgentries - c->max_cmd_sgentries + 1;
|
||||
c->maxsgentries -= 1; /* account for chain pointer */
|
||||
} else {
|
||||
c->maxsgentries = 31; /* Default to traditional value */
|
||||
c->chainsize = 0; /* traditional */
|
||||
}
|
||||
|
||||
c->product_name = products[prod_index].product_name;
|
||||
c->access = *(products[prod_index].access);
|
||||
c->nr_cmds = c->max_commands - 4;
|
||||
@@ -4214,6 +4118,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int rc;
|
||||
int dac, return_code;
|
||||
InquiryData_struct *inq_buff;
|
||||
@@ -4317,6 +4222,53 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||
printk(KERN_ERR "cciss: out of memory");
|
||||
goto clean4;
|
||||
}
|
||||
|
||||
/* Need space for temp scatter list */
|
||||
hba[i]->scatter_list = kmalloc(hba[i]->max_commands *
|
||||
sizeof(struct scatterlist *),
|
||||
GFP_KERNEL);
|
||||
for (k = 0; k < hba[i]->nr_cmds; k++) {
|
||||
hba[i]->scatter_list[k] = kmalloc(sizeof(struct scatterlist) *
|
||||
hba[i]->maxsgentries,
|
||||
GFP_KERNEL);
|
||||
if (hba[i]->scatter_list[k] == NULL) {
|
||||
printk(KERN_ERR "cciss%d: could not allocate "
|
||||
"s/g lists\n", i);
|
||||
goto clean4;
|
||||
}
|
||||
}
|
||||
hba[i]->cmd_sg_list = kmalloc(sizeof(struct Cmd_sg_list *) *
|
||||
hba[i]->nr_cmds,
|
||||
GFP_KERNEL);
|
||||
if (!hba[i]->cmd_sg_list) {
|
||||
printk(KERN_ERR "cciss%d: Cannot get memory for "
|
||||
"s/g chaining.\n", i);
|
||||
goto clean4;
|
||||
}
|
||||
/* Build up chain blocks for each command */
|
||||
if (hba[i]->chainsize > 0) {
|
||||
for (j = 0; j < hba[i]->nr_cmds; j++) {
|
||||
hba[i]->cmd_sg_list[j] =
|
||||
kmalloc(sizeof(struct Cmd_sg_list),
|
||||
GFP_KERNEL);
|
||||
if (!hba[i]->cmd_sg_list[j]) {
|
||||
printk(KERN_ERR "cciss%d: Cannot get memory "
|
||||
"for chain block.\n", i);
|
||||
goto clean4;
|
||||
}
|
||||
/* Need a block of chainsized s/g elements. */
|
||||
hba[i]->cmd_sg_list[j]->sgchain =
|
||||
kmalloc((hba[i]->chainsize *
|
||||
sizeof(SGDescriptor_struct)),
|
||||
GFP_KERNEL);
|
||||
if (!hba[i]->cmd_sg_list[j]->sgchain) {
|
||||
printk(KERN_ERR "cciss%d: Cannot get memory "
|
||||
"for s/g chains\n", i);
|
||||
goto clean4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_init(&hba[i]->lock);
|
||||
|
||||
/* Initialize the pdev driver private data.
|
||||
@@ -4362,7 +4314,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||
|
||||
cciss_procinit(i);
|
||||
|
||||
hba[i]->cciss_max_sectors = 2048;
|
||||
hba[i]->cciss_max_sectors = 8192;
|
||||
|
||||
rebuild_lun_table(hba[i], 1, 0);
|
||||
hba[i]->busy_initializing = 0;
|
||||
@@ -4370,6 +4322,20 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||
|
||||
clean4:
|
||||
kfree(hba[i]->cmd_pool_bits);
|
||||
/* Free up sg elements */
|
||||
for (k = 0; k < hba[i]->nr_cmds; k++)
|
||||
kfree(hba[i]->scatter_list[k]);
|
||||
kfree(hba[i]->scatter_list);
|
||||
/* Only free up extra s/g lists if controller supports them */
|
||||
if (hba[i]->chainsize > 0) {
|
||||
for (j = 0; j < hba[i]->nr_cmds; j++) {
|
||||
if (hba[i]->cmd_sg_list[j]) {
|
||||
kfree(hba[i]->cmd_sg_list[j]->sgchain);
|
||||
kfree(hba[i]->cmd_sg_list[j]);
|
||||
}
|
||||
}
|
||||
kfree(hba[i]->cmd_sg_list);
|
||||
}
|
||||
if (hba[i]->cmd_pool)
|
||||
pci_free_consistent(hba[i]->pdev,
|
||||
hba[i]->nr_cmds * sizeof(CommandList_struct),
|
||||
@@ -4400,30 +4366,28 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||
|
||||
static void cciss_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
ctlr_info_t *tmp_ptr;
|
||||
int i;
|
||||
char flush_buf[4];
|
||||
ctlr_info_t *h;
|
||||
char *flush_buf;
|
||||
int return_code;
|
||||
|
||||
tmp_ptr = pci_get_drvdata(pdev);
|
||||
if (tmp_ptr == NULL)
|
||||
h = pci_get_drvdata(pdev);
|
||||
flush_buf = kzalloc(4, GFP_KERNEL);
|
||||
if (!flush_buf) {
|
||||
printk(KERN_WARNING
|
||||
"cciss:%d cache not flushed, out of memory.\n",
|
||||
h->ctlr);
|
||||
return;
|
||||
i = tmp_ptr->ctlr;
|
||||
if (hba[i] == NULL)
|
||||
return;
|
||||
|
||||
/* Turn board interrupts off and send the flush cache command */
|
||||
/* sendcmd will turn off interrupt, and send the flush...
|
||||
* To write all data in the battery backed cache to disks */
|
||||
memset(flush_buf, 0, 4);
|
||||
return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0,
|
||||
CTLR_LUNID, TYPE_CMD);
|
||||
if (return_code == IO_OK) {
|
||||
printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
|
||||
} else {
|
||||
printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
|
||||
}
|
||||
free_irq(hba[i]->intr[2], hba[i]);
|
||||
/* write all data in the battery backed cache to disk */
|
||||
memset(flush_buf, 0, 4);
|
||||
return_code = sendcmd_withirq(CCISS_CACHE_FLUSH, h->ctlr, flush_buf,
|
||||
4, 0, CTLR_LUNID, TYPE_CMD);
|
||||
kfree(flush_buf);
|
||||
if (return_code != IO_OK)
|
||||
printk(KERN_WARNING "cciss%d: Error flushing cache\n",
|
||||
h->ctlr);
|
||||
h->access.set_intr_mask(h, CCISS_INTR_OFF);
|
||||
free_irq(h->intr[2], h);
|
||||
}
|
||||
|
||||
static void __devexit cciss_remove_one(struct pci_dev *pdev)
|
||||
@@ -4485,6 +4449,20 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
|
||||
pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
|
||||
hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
|
||||
kfree(hba[i]->cmd_pool_bits);
|
||||
/* Free up sg elements */
|
||||
for (j = 0; j < hba[i]->nr_cmds; j++)
|
||||
kfree(hba[i]->scatter_list[j]);
|
||||
kfree(hba[i]->scatter_list);
|
||||
/* Only free up extra s/g lists if controller supports them */
|
||||
if (hba[i]->chainsize > 0) {
|
||||
for (j = 0; j < hba[i]->nr_cmds; j++) {
|
||||
if (hba[i]->cmd_sg_list[j]) {
|
||||
kfree(hba[i]->cmd_sg_list[j]->sgchain);
|
||||
kfree(hba[i]->cmd_sg_list[j]);
|
||||
}
|
||||
}
|
||||
kfree(hba[i]->cmd_sg_list);
|
||||
}
|
||||
/*
|
||||
* Deliberately omit pci_disable_device(): it does something nasty to
|
||||
* Smart Array controllers that pci_enable_device does not undo
|
||||
|
||||
@@ -55,7 +55,13 @@ typedef struct _drive_info_struct
|
||||
char device_initialized; /* indicates whether dev is initialized */
|
||||
} drive_info_struct;
|
||||
|
||||
struct ctlr_info
|
||||
struct Cmd_sg_list {
|
||||
SGDescriptor_struct *sgchain;
|
||||
dma_addr_t sg_chain_dma;
|
||||
int chain_block_size;
|
||||
};
|
||||
|
||||
struct ctlr_info
|
||||
{
|
||||
int ctlr;
|
||||
char devname[8];
|
||||
@@ -75,6 +81,16 @@ struct ctlr_info
|
||||
int num_luns;
|
||||
int highest_lun;
|
||||
int usage_count; /* number of opens all all minor devices */
|
||||
/* Need space for temp sg list
|
||||
* number of scatter/gathers supported
|
||||
* number of scatter/gathers in chained block
|
||||
*/
|
||||
struct scatterlist **scatter_list;
|
||||
int maxsgentries;
|
||||
int chainsize;
|
||||
int max_cmd_sgentries;
|
||||
struct Cmd_sg_list **cmd_sg_list;
|
||||
|
||||
# define DOORBELL_INT 0
|
||||
# define PERF_MODE_INT 1
|
||||
# define SIMPLE_MODE_INT 2
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
//###########################################################################
|
||||
#define CISS_VERSION "1.00"
|
||||
|
||||
//general boundary defintions
|
||||
//general boundary definitions
|
||||
#define SENSEINFOBYTES 32//note that this value may vary between host implementations
|
||||
#define MAXSGENTRIES 31
|
||||
#define MAXSGENTRIES 32
|
||||
#define CCISS_SG_CHAIN 0x80000000
|
||||
#define MAXREPLYQS 256
|
||||
|
||||
//Command Status value
|
||||
@@ -319,6 +320,10 @@ typedef struct _CfgTable_struct {
|
||||
BYTE ServerName[16];
|
||||
DWORD HeartBeat;
|
||||
DWORD SCSI_Prefetch;
|
||||
DWORD MaxSGElements;
|
||||
DWORD MaxLogicalUnits;
|
||||
DWORD MaxPhysicalDrives;
|
||||
DWORD MaxPhysicalDrivesPerLogicalUnit;
|
||||
} CfgTable_struct;
|
||||
#pragma pack()
|
||||
#endif // CCISS_CMD_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user