Le vendredi 10 avril 2009 à 09:53 +0200, Emmanuel Fleury a écrit : > Package: fglrx-kernel-src > Version: 1:9-3-1 > Severity: normal > > What did change in the 2.6.29 seems to be the following struct: > > - current->euid --> current->cred->euid > - current->uid --> current->cred->uid > - current->gid --> current->cred->gid
Way more things changed, especially with respect to the ACPI subsystem (specifically, the driver made use of a sizeable amount of private structures) The following patch kind of works for me; it seems DPMS is still bust and I get the occasional lock-up, but otherwise I've been happily compiz'ing and gaming with it for a couple weeks. As one of the comments mentions, some parts are still quite dirty and possibly not DFSG compliant (borderline, at least) The ACPI side almost works, after running it, I noticed I made the effort to keep track of fglrx-private data (which used to be stuffed within the acpi layer's own private data), but I forgot to rewire the actual notifications. Should be trivial now; might explain the DPMS troubles. Anyway, right now I'm pretty satisfied with the way my HD 4350 behaves with this driver... YMMV, HTH. -- Cyrille
Seulement dans fglrx.vanilla/: configure-stamp Seulement dans fglrx.vanilla/debian: control diff -ur fglrx.vanilla/firegl_public.c fglrx/firegl_public.c --- fglrx.vanilla/firegl_public.c 2009-03-29 21:08:16.000000000 +0200 +++ fglrx/firegl_public.c 2009-03-30 00:17:17.000000000 +0200 @@ -1402,7 +1402,7 @@ */ KCL_TYPE_Uid ATI_API_CALL KCL_GetEffectiveUid(void) { - return current->euid; + return current_euid(); } /** /brief Delay execution for the specified number of microseconds @@ -1774,15 +1774,19 @@ */ void ATI_API_CALL KCL_PosixSecurityCapSetIPCLock(unsigned int lock) { + struct cred *new; + new = prepare_creds(); + if (!new) return /* -ENOMEM */; + if (lock == 0 ) { - cap_lower(current->cap_effective, CAP_IPC_LOCK); + cap_raise(new->cap_effective, CAP_IPC_LOCK); } else { - cap_raise(current->cap_effective, CAP_IPC_LOCK); + cap_lower(new->cap_effective, CAP_IPC_LOCK); } - return; + commit_creds(new); } /** \brief Get number of available RAM pages @@ -2256,13 +2260,16 @@ * kernel < 2.6.27, on_each_cpu has 4 parameters. * kernel >= 2.6.27, on_each_cpu has 3 parameters (removed the "retry" parameter) */ -#if defined(__x86_64__) && defined(__SMP__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)) +#if defined(__x86_64__) && defined(__SMP__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) # if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)) on_each_cpu(KCL_flush_tlb_one, &va, 1, 1); # else on_each_cpu(KCL_flush_tlb_one, &va, 1); # endif +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) + on_each_cpu(KCL_flush_tlb_one, &va, 1); #else + /* old code */ flush_tlb_page(vma, va); #endif } diff -ur fglrx.vanilla/firegl_public.h fglrx/firegl_public.h --- fglrx.vanilla/firegl_public.h 2009-03-29 21:08:16.000000000 +0200 +++ fglrx/firegl_public.h 2009-03-30 00:11:20.000000000 +0200 @@ -161,7 +161,9 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) #define PMSG_EVENT(pmsg_state) (pmsg_state).event +#ifndef PM_EVENT_SUSPEND #define PM_EVENT_SUSPEND 2 +#endif #else #define PMSG_EVENT(pmsg_state) (pmsg_state) #define PM_EVENT_SUSPEND 3 @@ -591,6 +593,14 @@ #define cpu_has_pge test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) #endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28) +/* this is DIRTY but will circumvent the GPL-only restriction for now? */ +#undef pgprot_writecombine +#undef pgprot_noncached + +#endif + #ifndef pgprot_writecombine #define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~(_PAGE_PCD)) | _PAGE_PWT) #endif Seulement dans fglrx.vanilla/: .firegl_public.o.d diff -ur fglrx.vanilla/kcl_acpi.c fglrx/kcl_acpi.c --- fglrx.vanilla/kcl_acpi.c 2009-03-29 21:08:16.000000000 +0200 +++ fglrx/kcl_acpi.c 2009-03-30 00:13:41.000000000 +0200 @@ -12,6 +12,11 @@ * User License Agreement is included with this software and is also * * available by contacting ATI Technologies Inc. at http://www.ati.com * * * + * * + * ---- * + * blah, blah, blah. * + * I wanted to run this on kernel 2.6.29, had to do some dirty work to * + * get it limping. YMMV. Cyrille Chepelov <cyri...@chepelov.org> * ****************************************************************************/ #include <linux/version.h> @@ -62,6 +67,76 @@ return acpi_get_devices(NULL, (acpi_walk_callback)callback, context, NULL); } + +/* store the first child */ +struct kcl_acpi_find_child { + unsigned int type; + union acpi_object *obj; + struct acpi_object_list *input; + struct acpi_buffer *output; + char *name; + int found; +}; + +static acpi_status +try_find_node_in_child_namespace_cb(acpi_handle handle, u32 level, void *context, void **return_value) +{ + acpi_status status; + struct kcl_acpi_find_child *wb = context; + + struct acpi_buffer *output = wb->output; + switch(wb->type) + { + case ACPI_TYPE_INTEGER: + output->length = sizeof(union acpi_object); + output->pointer = wb->obj; + break; + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_PACKAGE: + output->length = ACPI_ALLOCATE_BUFFER; + output->pointer = NULL; + break; + default: + output->length = 0; + output->pointer = NULL; + break; + } + + status = acpi_evaluate_object(handle, wb->name, wb->input, wb->output); + if (ACPI_SUCCESS(status)) + { + wb->found = 1; + return AE_CTRL_TERMINATE; + } + return 0; +} + +static int +try_find_node_in_child_namespace(unsigned int type, + acpi_handle start_object, + char *name, + union acpi_object *obj, + struct acpi_object_list *input, + struct acpi_buffer *output) +{ + struct kcl_acpi_find_child wb; + wb.type = type; + wb.name = name; + wb.obj = obj; + wb.output = output; + wb.found = 0; + + acpi_walk_namespace(type, start_object, 1, + try_find_node_in_child_namespace_cb, + &wb, NULL); + if (!wb.found) + return -ENOENT; + + return 0; +} + + /** \brief evaluate acpi namespace object, handle or pathname must be valid * \param handle namespace object handle * \param info input/output arguments for the control method @@ -74,7 +149,6 @@ struct acpi_buffer output; union acpi_object *params = NULL; union acpi_object *obj = NULL; - struct acpi_namespace_node *parent_node, *node; char name[5] = {'\0'}; struct KCL_ACPI_MethodArgument *argument = NULL; unsigned int i, count; @@ -225,39 +299,8 @@ if (ACPI_FAILURE(status)) { /* if failed, try the child namespace node */ - parent_node = (struct acpi_namespace_node *)handle; - node = parent_node->child; - while ((node != NULL) && ( node != parent_node)) - { - switch(type) - { - case ACPI_TYPE_INTEGER: - output.length = sizeof(union acpi_object); - output.pointer = obj; - break; - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case ACPI_TYPE_PACKAGE: - output.length = ACPI_ALLOCATE_BUFFER; - output.pointer = NULL; - break; - default: - output.length = 0; - output.pointer = NULL; - break; - } - - status = acpi_evaluate_object((acpi_handle)node, name, &input, &output); - if (ACPI_SUCCESS(status)) - { - break; - } - node = node->peer; - } - if ((node == NULL) || (node == parent_node)) - { - goto error; - } + if (try_find_node_in_child_namespace(type, handle, name, obj, &input, &output) < 0) + goto error; } /* return the output info */ @@ -470,31 +513,56 @@ } } + +static DEFINE_SPINLOCK(kcl_cb_lock); +struct kcl_callback { + struct list_head cb_list; + KCL_ACPI_DevHandle dev_handle; + KCL_ACPI_CallbackHandle cb_handler; + KCL_ACPI_ContextHandle cb_context; +}; +static LIST_HEAD(kcl_cb); + +/* note: this structure is not efficient; it's meant to get me going +on 2.6.29, period. */ +struct kcl_callback* +find_kcl_callback_xxx(KCL_ACPI_DevHandle dev_handle) +{ + /* assuming kcl_cb_lock is held! */ + struct kcl_callback* cur; + + list_for_each_entry(cur, &kcl_cb, cb_list) + { + if (cur->dev_handle == dev_handle) + { + return cur; + } + } + return NULL; /* not found */ +} + + /** \brief get notify handler for the device notify operand object * \param handle acpi handle * \return pointer to notify handler */ KCL_ACPI_CallbackHandle ATI_API_CALL KCL_ACPI_GetNotifyHandler(KCL_ACPI_DevHandle handle) { - struct acpi_namespace_node *node = NULL; + struct kcl_callback* cbk; + KCL_ACPI_CallbackHandle result; + spin_lock(&kcl_cb_lock); + + cbk = find_kcl_callback_xxx(handle); + if (!cbk) goto error; /* unknown? */ + + result = cbk->cb_handler; + + spin_unlock(&kcl_cb_lock); + return result; - node = (struct acpi_namespace_node *)handle; - - if ((node != NULL) && (node->object != NULL)) - { - if (node->object->common_notify.device_notify != NULL) - { - return (KCL_ACPI_CallbackHandle)node->object->common_notify.device_notify->notify.handler; - } - else - { - return NULL; - } - } - else - { - return NULL; - } +error: + spin_unlock(&kcl_cb_lock); + return NULL; } /** \brief get notify context for the device notify operand object @@ -503,25 +571,46 @@ */ KCL_ACPI_ContextHandle ATI_API_CALL KCL_ACPI_GetNotifyContext(KCL_ACPI_DevHandle handle) { - struct acpi_namespace_node *node = NULL; - - node = (struct acpi_namespace_node *)handle; + struct kcl_callback* cbk; + KCL_ACPI_ContextHandle result; + spin_lock(&kcl_cb_lock); + + cbk = find_kcl_callback_xxx(handle); + if (!cbk) goto error; /* unknown? */ + + result = cbk->cb_context; + + spin_unlock(&kcl_cb_lock); + return result; +error: + spin_unlock(&kcl_cb_lock); + return NULL; +} - if ((node != NULL) && (node->object != NULL)) - { - if (node->object->common_notify.device_notify != NULL) - { - return (KCL_ACPI_ContextHandle)node->object->common_notify.device_notify->notify.context; - } - else - { - return NULL; - } - } - else - { - return NULL; +struct kcl_callback* +find_or_make_kcl_callback_xxx(KCL_ACPI_DevHandle handle) +{ + struct kcl_callback* cbk; + + cbk = find_kcl_callback_xxx(handle); + if (!cbk) + { + cbk = kzalloc(sizeof(struct kcl_callback), GFP_KERNEL); + if (!cbk) + { + printk(KERN_ERR "can't allocate memory\n"); + return NULL; + } + + INIT_LIST_HEAD(&cbk->cb_list); + cbk->dev_handle = handle; + list_add(&cbk->cb_list, &kcl_cb); + /* FIXME: we will never, ever remove things from this list + this is a bad leak. Unfortunately fglrx does not allow us + to be clean */ + } + return cbk; } /** \brief update notify handler for the device notify operand object @@ -531,15 +620,17 @@ */ void ATI_API_CALL KCL_ACPI_UpdateNotifyHandler(KCL_ACPI_DevHandle handle, KCL_ACPI_CallbackHandle handler) { - struct acpi_namespace_node *node = NULL; - - node = (struct acpi_namespace_node *)handle; - - if ((node != NULL) && (node->object != NULL) && (node->object->common_notify.device_notify != NULL)) - { - node->object->common_notify.device_notify->notify.handler = (acpi_notify_handler)handler; - } + struct kcl_callback* cbk; + spin_lock(&kcl_cb_lock); + cbk = find_or_make_kcl_callback_xxx(handle); + if (!cbk) goto error; /* out of memory? */ + cbk->cb_handler = handler; + + spin_unlock(&kcl_cb_lock); + return; +error: + spin_unlock(&kcl_cb_lock); return; } @@ -550,15 +641,17 @@ */ void ATI_API_CALL KCL_ACPI_UpdateNotifyContext(KCL_ACPI_DevHandle handle, KCL_ACPI_ContextHandle context) { - struct acpi_namespace_node *node = NULL; - - node = (struct acpi_namespace_node *)handle; - - if ((node != NULL) && (node->object != NULL) && (node->object->common_notify.device_notify != NULL)) - { - node->object->common_notify.device_notify->notify.context = context; - } + struct kcl_callback* cbk; + spin_lock(&kcl_cb_lock); + cbk = find_or_make_kcl_callback_xxx(handle); + if (!cbk) goto error; /* out of memory? */ + cbk->cb_context = context; + + spin_unlock(&kcl_cb_lock); + return; +error: + spin_unlock(&kcl_cb_lock); return; } Seulement dans fglrx: Module.markers Seulement dans fglrx: modules.order Seulement dans fglrx: Module.symvers Seulement dans fglrx.vanilla/: .tmp_versions