Announcement

Collapse
No announcement yet.

Patch for ATI Catalyst 10.5 to work with CONFIG_PREEMPT_RT

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Patch for ATI Catalyst 10.5 to work with CONFIG_PREEMPT_RT

    Hi,

    I created the patch below to enable ATI Catalyst 10.5 to work with CONFIG_PREEMPT_RT enabled kernel. I also included the patch for 2.6.33.

    So far I have only performed the following test:

    Platform1: FortSumter 2.6.33.5rt22 (x86-64) custom kernel with Fedora 12 based root filesystem and ATI HD4650.

    Platform2: Custom hardware with Arrandale Core i7 same kernel and MXM96 (the same ATI chip).

    I have been able to run multiple instances of glx_gears and also running the OpenCL examples in ATI Stream SDK 2.1 with the exception of 'MonteCarloAsian' which freezes the system (this particular example freezes my system even with standard CentOS 5.4 distribution kernel and original Catalyst 10.5 driver).

    I would say the 3D acceleration performance is comparable between standard kernel and the custom PREEMPT_RT patch ( you may want to adjust the priority of the fglrx interrupt).

    I was wondering if any of you are working with CONFIG_PREEMPT_RT kernel and want to share some of your experience on making the Catalyst driver to work with your system.

    If anyone has any suggestions of where to post this patch to get more response please do so.

    Note: I don't work for AMD/ATI and the patch is only provided as is since their position is not to support PREEMPT_RT kernel at this time.

    -----------------------------------------------------------------------

    diff -Naur fglrx/build_mod/drmP.h fglrx_patched/build_mod/drmP.h
    --- fglrx/build_mod/drmP.h 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/drmP.h 2010-06-03 12:44:18.000000000 -0700
    @@ -42,7 +42,12 @@
    * can build the DRM (part of PI DRI). 4/21/2000 S + B */
    #include <asm/current.h>
    #endif /* __alpha__ */
    +#include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/miscdevice.h>
    @@ -51,7 +56,6 @@
    #include <linux/init.h>
    #include <linux/file.h>
    #include <linux/pci.h>
    -#include <linux/version.h>
    #include <linux/sched.h>
    #include <linux/smp_lock.h> /* For (un)lock_kernel */
    #include <linux/mm.h>
    diff -Naur fglrx/build_mod/firegl_public.c fglrx_patched/build_mod/firegl_public.c
    --- fglrx/build_mod/firegl_public.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/firegl_public.c 2010-06-03 12:44:18.000000000 -0700
    @@ -28,7 +28,11 @@
    #error Kernel versions older than 2.6.0 are no longer supported by this module.
    #endif

    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif

    #if !defined(CONFIG_X86)
    #if !defined(CONFIG_X86_PC)
    @@ -163,8 +167,12 @@

    // For 2.6.18 or higher, the UTS_RELEASE is defined in the linux/utsrelease.h.
    #ifndef UTS_RELEASE
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/utsrelease.h>
    +#else
    #include <linux/utsrelease.h>
    #endif
    +#endif

    #if defined(__i386__)
    #ifndef do_div
    @@ -209,6 +217,18 @@
    #define preempt_enable()
    #endif

    +// Function to check ownership of spinlocks.
    +#if defined(CONFIG_PREEMPT_RT)
    +#define RT_MUTEX_OWNER_MASKALL 3UL
    +
    +static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
    +{
    + return (struct task_struct *)
    + ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
    +}
    +#endif
    +
    +
    // ================================================== ==========
    /* globals */

    @@ -830,7 +850,11 @@
    * happen much less frequent then without this workaround.
    */
    if (state == PM_EVENT_SUSPEND)
    - acquire_console_sem();
    +#if defined(CONFIG_PREEMPT_RT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
    + acquire_console_mutex();
    +#else
    + acquire_console_sem();
    +#endif

    if (firegl_cail_powerdown(privdev, state))
    ret = -EIO;
    @@ -852,7 +876,11 @@
    }

    if (state == PM_EVENT_SUSPEND)
    - release_console_sem();
    +#if defined(CONFIG_PREEMPT_RT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
    + release_console_mutex();
    +#else
    + release_console_sem();
    +#endif

    KCL_DEBUG_TRACEOUT(FN_FIREGL_ACPI, ret, NULL);

    @@ -876,7 +904,11 @@
    if (PMSG_EVENT(pdev->dev.power.power_state) == 0) return 0;

    if (PMSG_EVENT(pdev->dev.power.power_state) == PM_EVENT_SUSPEND)
    - acquire_console_sem();
    +#if defined(CONFIG_PREEMPT_RT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
    + acquire_console_mutex();
    +#else
    + acquire_console_sem();
    +#endif

    #ifdef FIREGL_USWC_SUPPORT
    // Restore the PAT after resuming from S3 or S4.
    @@ -901,7 +933,11 @@
    firegl_cail_powerup(privdev);

    if (PMSG_EVENT(pdev->dev.power.power_state) == PM_EVENT_SUSPEND)
    - release_console_sem();
    +#if defined(CONFIG_PREEMPT_RT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
    + release_console_mutex();
    +#else
    + release_console_sem();
    +#endif

    PMSG_EVENT(pdev->dev.power.power_state) = 0;
    KCL_DEBUG_TRACEOUT(FN_FIREGL_ACPI, 0, NULL);
    @@ -1025,8 +1061,11 @@
    dev->pubdev.signature = FGL_DEVICE_SIGNATURE;

    for (i = 0; i < __KE_MAX_SPINLOCKS; i++)
    +#if defined(CONFIG_PREEMPT_RT)
    + spin_lock_init(&dev->spinlock[i]);
    +#else
    dev->spinlock[i] = SPIN_LOCK_UNLOCKED;
    -
    +#endif
    for (i=0; i < __KE_MAX_SEMAPHORES; i++)
    sema_init(&dev->struct_sem[i], 1);

    @@ -1470,7 +1509,16 @@
    #ifndef __HAVE_ARCH_CMPXCHG
    return __fgl_cmpxchg(ptr,old,new,size);
    #else
    - return __cmpxchg(ptr,old,new,size);
    + switch (size) {
    + case 1: { volatile u8 *_ptr = ptr; return cmpxchg(_ptr, old, new); }
    + case 2: { volatile u16 *_ptr = ptr; return cmpxchg(_ptr, old, new); }
    + case 4: { volatile u32 *_ptr = ptr; return cmpxchg(_ptr, old, new); }
    +#ifdef __x86_64__
    + case 8: { volatile u64 *_ptr = ptr; return cmpxchg(_ptr, old, new); }
    +#endif
    + default:
    + return old;
    + }
    #endif
    }

    @@ -4189,12 +4237,17 @@
    */
    static unsigned long kasSetExecutionLevel(unsigned long level)
    {
    - unsigned long orig_level;
    +#if defined(CONFIG_PREEMPT_RT)
    + /* do nothing just return */
    + return level;
    +#else
    + unsigned long orig_level;

    orig_level = __get_cpu_var(kasExecutionLevel);
    __get_cpu_var(kasExecutionLevel) = level;

    return orig_level;
    +#endif
    }

    /** \brief Internal helper to get execution level for the current processor
    @@ -4204,7 +4257,20 @@
    */
    static unsigned long kas_GetExecutionLevel(void)
    {
    - return __get_cpu_var(kasExecutionLevel);
    +#if defined(CONFIG_PREEMPT_RT)
    + /*Check what level we are in */
    + if (rt_mutex_owner(&kasContext.lock_ih.lock) == current) {
    + return kasContext.exec_level_ih;
    + }
    +
    + if (rt_mutex_owner(&kasContext.lock_idh.lock) == current) {
    + return kasContext.exec_level_idh;
    + }
    +
    + return kasContext.exec_level_regular;
    +#else
    + return __get_cpu_var(kasExecutionLevel);
    +#endif
    }

    /** \brief Type definition for kas_spin_lock() parameter */
    @@ -4357,12 +4423,14 @@

    KCL_DEBUG5(FN_FIREGL_KAS,"0x%08X, 0x%08X\n", ih_routine, ih_context);

    +#if !defined(CONFIG_PREEMPT_RT)
    //Prevent simultaneous entry on some SMP systems.
    if (test_and_set_bit(0, (void *)&(kasContext.in_interrupts[smp_processor_id()])))
    {
    KCL_DEBUG1(FN_FIREGL_KAS, "The processor is handling the interrupt\n");
    return IRQ_NONE;
    }
    +#endif

    spin_lock(&kasContext.lock_ih);
    orig_level = kasSetExecutionLevel(kasContext.exec_level_ih);
    @@ -4373,7 +4441,9 @@
    kasSetExecutionLevel(orig_level);
    spin_unlock(&kasContext.lock_ih);

    +#if !defined(CONFIG_PREEMPT_RT)
    clear_bit(0, (void *)&(kasContext.in_interrupts[smp_processor_id()]));
    +#endif
    KCL_DEBUG5(FN_FIREGL_KAS,"%d\n", ret);

    return ret;
    @@ -5057,7 +5127,11 @@
    unsigned int ATI_API_CALL KAS_Mutex_Initialize(void* hMutex)
    {
    kasMutex_t* mutex_obj = (kasMutex_t*)hMutex;
    +#if defined(CONFIG_PREEMPT_RT)
    + sema_init(&(mutex_obj->mutex),1);
    +#else
    init_MUTEX(&(mutex_obj->mutex));
    +#endif
    return 1;
    }

    diff -Naur fglrx/build_mod/kcl_acpi.c fglrx_patched/build_mod/kcl_acpi.c
    --- fglrx/build_mod/kcl_acpi.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_acpi.c 2010-06-03 12:44:18.000000000 -0700
    @@ -15,7 +15,11 @@
    ************************************************** **************************/

    #include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/acpi.h>
    #include <linux/pci.h>

    diff -Naur fglrx/build_mod/kcl_agp.c fglrx_patched/build_mod/kcl_agp.c
    --- fglrx/build_mod/kcl_agp.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_agp.c 2010-06-03 12:44:18.000000000 -0700
    @@ -31,7 +31,11 @@
    */

    #include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/pci.h>
    #include <linux/agp_backend.h>
    #include <linux/string.h>
    diff -Naur fglrx/build_mod/kcl_io.c fglrx_patched/build_mod/kcl_io.c
    --- fglrx/build_mod/kcl_io.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_io.c 2010-06-03 12:44:18.000000000 -0700
    @@ -37,7 +37,11 @@
    */

    #include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/poll.h>
    #include <linux/signal.h>
    #include <asm/io.h>
    diff -Naur fglrx/build_mod/kcl_osconfig.h fglrx_patched/build_mod/kcl_osconfig.h
    --- fglrx/build_mod/kcl_osconfig.h 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_osconfig.h 2010-06-03 12:44:18.000000000 -0700
    @@ -20,7 +20,11 @@
    #define KCL_OSCONFIG_H

    #include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif

    // Choose modern way to call 32-on-64 IOCTLs if configured in the kernel
    #if defined(CONFIG_COMPAT) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
    diff -Naur fglrx/build_mod/kcl_pci.c fglrx_patched/build_mod/kcl_pci.c
    --- fglrx/build_mod/kcl_pci.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_pci.c 2010-06-03 12:44:18.000000000 -0700
    @@ -31,7 +31,11 @@
    */

    #include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/pci.h>

    #include "kcl_config.h"
    diff -Naur fglrx/build_mod/kcl_str.c fglrx_patched/build_mod/kcl_str.c
    --- fglrx/build_mod/kcl_str.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_str.c 2010-06-03 12:44:18.000000000 -0700
    @@ -30,7 +30,12 @@
    *
    */

    +#include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/string.h>
    #include <linux/module.h>

    diff -Naur fglrx/build_mod/kcl_wait.c fglrx_patched/build_mod/kcl_wait.c
    --- fglrx/build_mod/kcl_wait.c 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/kcl_wait.c 2010-06-03 12:44:18.000000000 -0700
    @@ -31,7 +31,11 @@
    */

    #include <linux/version.h>
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    +#include <generated/autoconf.h>
    +#else
    #include <linux/autoconf.h>
    +#endif
    #include <linux/wait.h>
    #include <linux/highmem.h>
    #include <linux/sched.h>
    diff -Naur fglrx/build_mod/make.sh fglrx_patched/build_mod/make.sh
    --- fglrx/build_mod/make.sh 2010-06-03 13:10:34.000000000 -0700
    +++ fglrx_patched/build_mod/make.sh 2010-06-03 12:44:18.000000000 -0700
    @@ -218,8 +218,15 @@
    # UTS-define is in external version-*.h files, i.e. linux-2.2.14-5.0-RedHat does this flaw
    kernel_release=`cat $linuxincludes/linux/version-*.h | grep UTS_RELEASE | grep \"$OsRelease\" | cut -d'"' -f2`
    else
    - # For 2.6.18 or higher, UTS-define is defined in utsrelease.h.
    - kernel_release=`cat $linuxincludes/linux/utsrelease.h | grep UTS_RELEASE | grep \"$OsRelease\" | cut -d'"' -f2`
    + UTS_REL_COUNT=`cat $linuxincludes/generated/utsrelease.h 2>/dev/null | grep UTS_RELEASE -c`
    +
    + if [ $UTS_REL_COUNT -gt 0 ]; then
    + # 2.6.33+
    + kernel_release=`cat $linuxincludes/generated/utsrelease.h | grep UTS_RELEASE | grep \"$OsRelease\" | cut -d'"' -f2`
    + else
    + # For 2.6.18 to 2.6.32, UTS-define is defined in utsrelease.h.
    + kernel_release=`cat $linuxincludes/linux/utsrelease.h | grep UTS_RELEASE | grep \"$OsRelease\" | cut -d'"' -f2`
    + fi
    fi
    fi
    fi
    @@ -302,7 +309,8 @@
    # 3
    # linux/autoconf.h may contain this: #define CONFIG_SMP 1

    -src_file=$linuxincludes/linux/autoconf.h
    +src_file=$linuxincludes/generated/autoconf.h
    +[ -e $src_file ] || src_file=$linuxincludes/linux/autoconf.h

    if [ ! -e $src_file ]; then
    echo "Warning:" >> $logfile
    @@ -355,7 +363,8 @@
    MODVERSIONS=0

    # linux/autoconf.h may contain this: #define CONFIG_MODVERSIONS 1
    -src_file=$linuxincludes/linux/autoconf.h
    +src_file=$linuxincludes/generated/autoconf.h
    +[ -e $src_file ] || src_file=$linuxincludes/linux/autoconf.h
    if [ ! -e $src_file ];
    then
    echo "Warning:" >> $logfile

    -----------------------------------------------------------------------

  • #2
    I wonder if you could file this as a bug in the AMD bugzilla, then file this diff as a solution suggestion and see if they integrate it or something based on it.

    Comment


    • #3
      Originally posted by nanonyme View Post
      I wonder if you could file this as a bug in the AMD bugzilla, then file this diff as a solution suggestion and see if they integrate it or something based on it.
      Thanks for the suggestion. Could you please clarify which AMD bugzilla I should try? A link would be nice. I will gladly file it.

      The last reply I have from AMD/ATI was:

      "Currently AMD has no plan supporting a RT driver therefore no update will be supplied. You would have to be responsible to conduct all needed tests thoroughly."

      Comment

      Working...
      X