Портирование кода таймера до 4.15 для драйвера ядра графического процессора mali450 на ARM64
У меня есть старая телевизионная приставка на базе Amlogic S905X ARM64 SoC, Tanix TX5, которая изначально работала на Android. Мне не нравится, когда меня лишают возможности использовать мое оборудование, поэтому я внимательно следил за развитием проекта Armbian, и недавно я установил версию 5.67, основанную на Ubuntu Bionic, работающую на Linux 4.19.6.
Все отлично работает, есть работающие драйверы для Ethernet, Wi-Fi, Bluetooth, и т. Д., Но, к сожалению, драйвер ядра не включен для поддержки встроенного GPU mali450. Вывод hdmi работает, но Xorg работает на fbdev, и обновление экрана мучительно медленное, видео в полноэкранном режиме недоступно для просмотра. Я не слишком уверен в том, что это за история, но, очевидно, amlogic сохраняет свою текущую версию драйвера при себе. Однако, зайдя на их FTP-сайт, я нашел старое дерево исходников для драйвера ядра ( http://openlinux.amlogic.com:8000/download/ARM/gpu/gpu-2016-08-18-fe6d7b1d1b.tar.gz). Он устарел, но я продвинулся в портировании его на текущее ядро, и до сих пор это было легко исправить. Теперь я могу скомпилировать около половины исходных файлов просто отлично.
Я должен пояснить, что я не разработчик Linux по профессии, я даже не разработчик C... Я балуюсь, я знаю достаточно, чтобы быть опасным, и я очень мотивирован. Моя ежедневная сделка - C#, поэтому я знаю более или менее, что я делаю.
Текущая проблема, с которой я столкнулся, связана с mali/linux/mali_osk_timers.c . Это оригинальный код:
/*
* Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_timers.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include <linux/timer.h>
#include <linux/slab.h>
#include "mali_osk.h"
#include "mali_kernel_common.h"
struct _mali_osk_timer_t_struct {
struct timer_list timer;
};
typedef void (*timer_timeout_function_t)(unsigned long);
_mali_osk_timer_t *_mali_osk_timer_init(void)
{
_mali_osk_timer_t *t = (_mali_osk_timer_t *)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL);
if (NULL != t) init_timer(&t->timer);
return t;
}
void _mali_osk_timer_add(_mali_osk_timer_t *tim, unsigned long ticks_to_expire)
{
MALI_DEBUG_ASSERT_POINTER(tim);
tim->timer.expires = jiffies + ticks_to_expire;
add_timer(&(tim->timer));
}
void _mali_osk_timer_mod(_mali_osk_timer_t *tim, unsigned long ticks_to_expire)
{
MALI_DEBUG_ASSERT_POINTER(tim);
mod_timer(&(tim->timer), jiffies + ticks_to_expire);
}
void _mali_osk_timer_del(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
del_timer_sync(&(tim->timer));
}
void _mali_osk_timer_del_async(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
del_timer(&(tim->timer));
}
mali_bool _mali_osk_timer_pending(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
return 1 == timer_pending(&(tim->timer));
}
void _mali_osk_timer_setcallback(_mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data)
{
MALI_DEBUG_ASSERT_POINTER(tim);
tim->timer.data = (unsigned long)data;
tim->timer.function = (timer_timeout_function_t)callback;
}
void _mali_osk_timer_term(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
kfree(tim);
}
Основная проблема здесь заключается в том, что этот код использует таймеры через интерфейс, который давно устарел и полностью удален из ядра в 4.15. Я смог посмотреть, как портировать этот код, и управлял почти всем файлом, но в конце концов я недостаточно знаком с синтаксисом C и правилами использования указателей, чтобы понять, как это сделать. Основной проблемой является функция _mali_osk_timer_setcallback(). Я не совсем уверен, как его модифицировать, сохраняя при этом ту же сигнатуру функции.
редактировать
Вот текущий код и текущий вывод компилятора:
/*
* Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_timers.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include <linux/timer.h>
#include <linux/slab.h>
#include "mali_osk.h"
#include "mali_kernel_common.h"
#define MALI_TIMER_FLAGS 0
struct _mali_osk_timer_t_struct {
struct timer_list timer;
void (*ticked)(unsigned long data);
};
static void tick_trampoline(struct timer_list *t) {
typedef struct _mali_osk_timer_t_struct Tldr;
Tldr *m = container_of(t, Tldr, timer);
m->ticked(t->data);
}
typedef void (*timer_timeout_function_t)(unsigned long);
_mali_osk_timer_t *_mali_osk_timer_init(void)
{
_mali_osk_timer_t *t = (_mali_osk_timer_t *)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL);
if (NULL != t) timer_setup(&(t->timer), tick_trampoline, MALI_TIMER_FLAGS);
return t;
}
void _mali_osk_timer_add(_mali_osk_timer_t *tim, unsigned long ticks_to_expire)
{
MALI_DEBUG_ASSERT_POINTER(tim);
tim->timer.expires = jiffies + ticks_to_expire;
add_timer(&(tim->timer));
}
void _mali_osk_timer_mod(_mali_osk_timer_t *tim, unsigned long ticks_to_expire)
{
MALI_DEBUG_ASSERT_POINTER(tim);
mod_timer(&(tim->timer), jiffies + ticks_to_expire);
}
void _mali_osk_timer_del(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
del_timer_sync(&(tim->timer));
}
void _mali_osk_timer_del_async(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
del_timer(&(tim->timer));
}
mali_bool _mali_osk_timer_pending(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
return 1 == timer_pending(&(tim->timer));
}
void _mali_osk_timer_setcallback(_mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data)
{
MALI_DEBUG_ASSERT_POINTER(tim);
&(tim->timer).data = (unsigned long)data;
tim->ticked = (timer_timeout_function_t)callback; /* Note no cast */
timer_setup(&(tim->timer), tick_trampoline, MALI_TIMER_FLAGS);
}
void _mali_osk_timer_term(_mali_osk_timer_t *tim)
{
MALI_DEBUG_ASSERT_POINTER(tim);
kfree(tim);
}
_
hugo@tx5:/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali$ sudo KDIR=../../kernel/Amlogic_s905-kernel USING_UMP=0 BUILD=release make
make ARCH=arm64 -C ../../kernel/Amlogic_s905-kernel M=/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali modules
make[1]: Entering directory '/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/kernel/Amlogic_s905-kernel'
WARNING: Symbol version dump ./Module.symvers
is missing; modules will have no dependencies and modversions.
CC [M] /media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.o
/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.c: In function ‘tick_trampoline’:
/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.c:31:17: error: ‘struct timer_list’ has no member named ‘data’
m->ticked(t->data);
^~
/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.c: In function ‘_mali_osk_timer_setcallback’:
/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.c:77:18: error: ‘struct timer_list’ has no member named ‘data’
&(tim->timer).data = (unsigned long)data;
^
/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.c: At top level:
cc1: warning: unrecognized command line option ‘-Wno-data-time’
scripts/Makefile.build:305: recipe for target '/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.o' failed
make[2]: *** [/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali/linux/mali_osk_timers.o] Error 1
Makefile:1517: recipe for target '_module_/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali' failed
make[1]: *** [_module_/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/gpu-2016-08-18-fe6d7b1d1b/mali] Error 2
make[1]: Leaving directory '/media/hugo/7d79c22a-4ac8-4fcb-ae1c-3310a851a73d/kernel/Amlogic_s905-kernel'
Makefile:192: recipe for target 'all' failed
make: *** [all] Error 2
1 ответ
Новый интерфейс таймера, gasp, оставляет значение контекста внутри структуры таймера и вместо этого передает указатель на эту структуру. Идея состоит в том, что использование данных прекратится, так как общепринятым было то, что данные были указателем на структуру, которая содержала структуру timer_list.
Поскольку вы, вероятно, хотите минимизировать изменения в mali, описанные здесь изменения должны помочь; он просто вставляет небольшую функцию преобразования протокола, чтобы он выглядел по-старому.
struct _mali_osk_timer_t_struct {
struct timer_list timer;
unsigned long data;
void (*ticked)(unsigned long data); /* Add this */
};
#define MALI_TIMER_FLAGS 0 /* NB: choose the right bits for this! */
/* This function converts between the “new” and “old” notifications */
static void tick_trampoline(struct timer *t) {
typedef struct _mali_osk_timer_t_struct Tldr;
Tldr *m = container_of(t, Tldr, timer);
m->ticked(m->data);
}
/* change this one: */
void _mali_osk_timer_setcallback(_mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data)
{
MALI_DEBUG_ASSERT_POINTER(tim);
tim->data = (unsigned long)data;
tim->ticked = callback; /* Note no cast */
timer_setup(&tim->ticked, tick_trampoline, MALI_TIMER_FLAGS);
}
"Без приведения" - это призыв позволить системе типов выполнять свою работу.