LINUX.ORG.RU

[arm][ядро][DMA] Покритикуйте

 , ,


0

1

Что может быть плохого в таком коде:

struct my_struct
{
...
short* offset;
...
short data[SOME_LENGTH];
};

...
void some_irq_handler(int irq, void* data)
{
struct my_struct* ms;
dma_addr_t dma;
...
ms = kzalloc(sizeof(struct my_struct), GFP_ATOMIC);
if ( ms == NULL ) goto cleanup;
ms->offset = ms->data;
...
dma = dma_map_single(...., ms->offset, ..., ...);
....
}

Вся эта мура в немного более сложном виде у меня завязана на SSC + PDC (архитектура AT91). Так вот если есть строка ms->offset = ms->data то передатчик SSC via PDC начинает терять первое слово (грубо говоря первый кадр попросту пропадает) если делать не так (без этой строки) все ОК. В чем может быть ЛАЖА?

google alignment

Весьма вероятно, что проблемы в том, что твой контролер DMA не может осуществлять запись по невыравненному по границе 4 байта (машинное слово) адресу.

anonymous
()
Ответ на: комментарий от anonymous

Возможно, но тогда если я передаю 4 кадра по 16 бит в каждом и первый кадр контроллер не может передать из-за выравнивания он не сможет передать и все остальные либо не сможет передать и 3 кадр тоже в зависимости от того как относительно границы выравнивания расположен первый.

При этом замете что ликвидация «ссылочного» адреса (операции ms->offset = ms->data) не меняет выравния самих данных.

ЗЫ: Может я чего совсем не понимаю, но в моей голове выравнивание как причина постоянно проскальзывает но не укладывается, по означенным причинам.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> При этом замете что ликвидация «ссылочного» адреса (операции ms->offset = ms->data) не меняет выравния самих данных.

Если убрать эту строку, то ms->offset будет 0 и у тебя вообще ничего не должно работать.

Проверь документацию и посмотри на ограничения на трансферы для твоего PDC.

anonymous
()

Из обрывка не понять что происходит - код вырван из контекста. Есть пара вопросов

1 Зачем в прерывании каждый раз выделять память под данные ?
2 В ядре есть драйвер i2s кодека для атмел - вы его видели ? а то возможно велик изобретаете
http://lxr.free-electrons.com/source/sound/spi/at73c213.c

anonymous
()
Ответ на: комментарий от mskmsk1985

> тогда если я передаю 4 кадра по 16 бит в каждом и первый кадр контроллер не может передать из-за выравнивания он не сможет передать и все остальные

Невозможно предсказать все фокусы, которые даст неправильное выравнивание.

P.S. kzalloc и dma_map_* в прерывании выглядят как минимум подозрительно.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Да видел, оно не подходит и велик мы не придумываем.

mskmsk1985
() автор топика
Ответ на: комментарий от anonymous

Я же говорю что можно сделать немного по другому без использования этого поля вообще и проблемы не будет (но поле при этом в самой структуре можно и оставить)

mskmsk1985
() автор топика
Ответ на: комментарий от anonymous

1 - За тем что когда после прихода одних данных нужно выделить очередь под новые данные которые ожидаются.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

>1 - За тем что когда после прихода одних данных нужно выделить очередь под новые данные которые ожидаются.

Что подозрительного в использовании kzalloc и dma_map_* в обработчике прерывания?


Понятно что для новых данных нужен буфер но обработчик прерывания должен делать минимаотную работу поэтому все нормальные люди буферы готовят заранее а в прерываниях ищут первый свободный.

Кстати чем не подходит атмеловский драйвер ssc и alsa драйвер для кодека ?

anonymous
()
Ответ на: комментарий от anonymous

1 - В боевом режиме буферы Я распределяю заранее, это я привел тестовй вариант на поиграться и понять в чем лажа

2 - Мне не аудио кодек нужен, а реализация собственного протокола для управления перефирифными устройствами разрабатываемыми на фирме. Протокол дуплексный и текут по нему команды и данные для управления а не аудиопоток. Естественно атмеловский драйвак не подходит так как на этом at73c213 только передатчик ssc используется (во всяком случае приемник к соответствующей микросхеме не разведен) и предназначен он немного не для того что нужно.

mskmsk1985
() автор топика

я бы лучше с kfifo сделал с записями и без блокировки.

+ не надо ничего kzalloc() в обработчике.
- нужно будет предварительно сделать пару телодвижений.
± ??????

nanoo_linux
()
Ответ на: комментарий от mskmsk1985

Понятно. Небольшая проблема в втом что в твоем коде ты выделяешь память через kzalloc

ms = kzalloc(sizeof(struct my_struct), GFP_ATOMIC);

ms будет выравнена по границе страницы памяти, но когда пытаешься смапить этот буфер на dma (вообще это криво звучит - все наоборот - это буфер в памяти смапен в адресное пространство процессора через kzalloc, а тут просто сливают кеши) ты передаешь уже не выравненый на границу страницы адрес который указывает хз куда в этом буфере - из куска кода непонятно какого размера у тебя структура, поэтому ядро у тебя его автоматом выравнивает и ты теряешь часть данных. Короче говоря все укзатели должны быть выравнены на страницы 4 кб.

anonymous
()
Ответ на: комментарий от anonymous

ОК, над этим пошел думать, но вопрос в другом: если я в dma_map_ пердаю не ms->offset а ms->data то если строку ms->offset = ms->data убрать то все работает, если нет то начинаются потери первого кадра причем иногда только со второй передачи. Итак вопрос: строка кода не влияет на выравнивание данных, так в чем фишка?

mskmsk1985
() автор топика
Ответ на: комментарий от anonymous

> Короче говоря все укзатели должны быть выравнены на страницы 4 кб.

Не должны. Выравнивать необходимо на границу выравнивания устройства, но не более. Если посмотреть, например, в scatterlist, там даже предусмотрено поле «смещение от начала страницы».

tailgunner ★★★★★
()
Ответ на: комментарий от mskmsk1985

Ты задаешь неправильные какие-то вопросы - откуда я знаю что там скрыто у тебя за многоточиями - очевидный баг в том что ты передаешь невыровненный на странице памяти указатель, очевидный фикс - выровнять его :) например так

struct my_struct
{
...
short* offset;
...

};

...
void some_irq_handler(int irq, void* data)
{
struct my_struct* ms;
dma_addr_t dma;
...
ms = kzalloc(sizeof(struct my_struct), GFP_ATOMIC);
if ( ms == NULL ) goto cleanup;
ms->offset = kzalloc(sizeof(short) * SOME_LENGTH, GFP_ATOMIC);
...
dma = dma_map_single(...., ms->offset, ..., ...);
....
}
anonymous
()
Ответ на: комментарий от anonymous

> выровнять его :) например так

ms->offset = kzalloc(sizeof(short) * SOME_LENGTH, GFP_ATOMIC);

Ясно. Предыдущий вопрос снимается.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Простите за тупой вопрос, а где она находится?

mskmsk1985
() автор топика
Ответ на: комментарий от tailgunner

>Не должны.

Похоже я нагнал и ты прав. Хотя смотрел поверхностно, но там с кешем ничего не связано и просто возращается результат virt_to_phys

anonymous
()
Ответ на: комментарий от anonymous

Вернее ядро проверяет находится ли буфер в области памяти когерентной с кешем, если да то просто возвращает virt_to_phys

 dma_addr = virt_to_dma(dev, ptr);
а если нет - выделяет буфер из пула dma или создает когерентный с кешем

buf = alloc_safe_buffer(device_info, ptr, size, dir);

копирует туда исходный буфер

                 if ((dir == DMA_TO_DEVICE) ||
                     (dir == DMA_BIDIRECTIONAL)) {
                         dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
                                 __func__, ptr, buf->safe, size);
                         memcpy(buf->safe, ptr, size);
                 }
и возвращает его физический адрес и новый указатель
                 ptr = buf->safe;

                 dma_addr = buf->safe_dma_addr;

так что то мое предположение о выравнивании ложное.

anonymous
()
Ответ на: комментарий от anonymous

Я проверил, все выровнено по границе 16 битного слова (как и должно быть) но эффект остается: если распределить буфер и взять адресс его начала (сохранил его в переменной типа указатель) до его использования (сразу после распределения) есть проблема (первое слово в 16 бит не передается никуды), не трогаешь адресс этого буфера - нет проблемы. В чем мистика (выравнивание здесь нипричем, кэш может быть, но каким боком)?

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> кэш может быть, но каким боком)?

Ну, например, обоащение к ms->offset подгружает в кэш строку, которая пересекается с первыми словами, приходящими с устройства. Если ты не делаешь dma_sync_for_*, упс.

А вообще, трудно отлаживать драйверы по переписке.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Фишка в том, что передачи первого слова ВООБЩЕ НЕ ПРОИСХОДИТ! Сохранил указатель - нет передачи первого слова (на ответном конце даже прерывание о приеме данных не генерируется), не трогаешь указатель все ОК.

mskmsk1985
() автор топика
Ответ на: комментарий от tailgunner

Заметил и не совсем понял зачем оно тут? У меня вроде как не scatter/gather буфер и отображение я делаю уже после того как сохранил адрес начала буфера И я этот адресс потом вообще никак не трогаю! Может я чего не понял?

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> Заметил

Как я понимаю, ответ «нет, я не использую dma_sync_for_*».

и не совсем понял зачем оно тут?

Для исключения эффектов кэша.

У меня вроде как не scatter/gather буфер

Нерелевантно. Прочитай уже DMA-API.txt

Может я чего не понял?

Странный вопрос. Если бы ты всё понял, ты бы не спрашивал,да?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Так как читал я DMA-API.txt то и интересуюсь нашиш мне нужно dma_sync_for_*? Оно ведь используется когда я хочу обратиться к УЖЕ МАППИРОВАННОЙ В DMA область памяти БЕЗ СНЯТИЯ этого отображения. У меня ничего подобного нет: я распределяю буфер, сохраняю его адресс еще одной переменной, потом делаю отображение, настраиваю контроллер DMA (PDC), пускаю передачу, дожидаюсь её завершения, снимаю отображение с буфера. Все работает если не сохранять адресс буфера в еще одной переменной. Куда я по Вашему должен этот dma_sync_for_* сунуть?

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> У меня ничего подобного нет: я распределяю буфер, сохраняю его адресс еще одной переменной, потом делаю отображение, настраиваю контроллер DMA (PDC), пускаю передачу, дожидаюсь её завершения, снимаю отображение с буфера.

У тебя в драйвере ошибка, ты не знаешь, где она, спрашиваешь совета, но, вместо того, чтобы ему последовать (это 5 минут) долго доказываешь, что у тебя всё правильно. Ну, прекрасно, я рад.

Куда я по Вашему должен этот dma_sync_for_* сунуть?

Между dma_map_single и последним обращением к ms->data (через ms->offset или любым другим способом).

tailgunner ★★★★★
()
Ответ на: комментарий от mskmsk1985

о вопрос в другом: если я в dma_map_ пердаю не ms->offset а ms->data то если строку ms->offset = ms->data убрать то все работает, если нет то начинаются потери первого кадра причем иногда только со второй передачи. Итак вопрос: строка кода не влияет на выравнивание данных, так в чем фишка?


«Фишка» в том, что ты не понимаешь, что делаешь. Если не хочешь делать по-нормальному, попробуй сделать вот так:

struct your_struct {
u16 offset;
u16 padding[30];
u16 data[SOME_CONSTANT];
};

anonymous
()
Ответ на: комментарий от anonymous

Или так, если поле не offset, а на самом деле указатель на данные:

struct your_struct { u16* data_ptr; u16 padding[28]; u16 data[SOME_CONSTANT]; };

Поля в структуры добавляй в конец

anonymous
()
Ответ на: комментарий от anonymous

Я уже структуры данных каким только раком не ставил. Еще раз: ВЫРАВНИВАНИЕ НЕ ПРИЧЕМ! Это факт медицинский.

ЗЫ: «фишка» не в том что я там чего-то там не понимаю, как вам хочется считать, а в том что компилятор криво оптимизирует код, ни больше ни меньше.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

>Вот как раз экспериментирую.

Вот это и есть эфект многоточия - хер знает что там написано, но после dma_map_single буфер лучше не трогать, по крайней мере я написал хуеву кучу драйверов и никаких сайд эфектов не наблюдал.

anonymous
()
Ответ на: комментарий от mskmsk1985

> Я уже структуры данных каким только раком не ставил. Еще раз: ВЫРАВНИВАНИЕ НЕ ПРИЧЕМ! Это факт медицинский.

Ты так и не понял, зачем между двумя полями вставлен паддинг? Первое поле и данные разнесенны на 32 байта (что должно составлять два кэшлайна, ну или 1 в крайнем случае) и попадают в разные кэшлайны.

ЗЫ: «фишка» не в том что я там чего-то там не понимаю, как вам хочется считать, а в том что компилятор криво оптимизирует код, ни больше ни меньше.

Дело именно в этом - в непонинамии. Ты 1) не привёл полные сэмплы кода (рабочий + нерабочий) 2) Не понимаешь, где у тебя проблемы 3) Предложения людей игнорируешь и постоянно ноешь о том, что у тебя всё правильно, но почему-то не работает ж)

anonymous
()
Ответ на: комментарий от anonymous

Во-первых я не ною. Во вторых Вы мне так и не удосужелись объяснить какого хрена порядок строк кода влияет на выравнивание, а проблема именно в перемене местами строчек кода. Втретьих , опустим, ибо конструктив с Вашей стороны похоже иссекает.

mskmsk1985
() автор топика
Ответ на: комментарий от anonymous

Те кто идут к успеху, не нуждаются в поднятии чуства собственного достоинства по средвом анонимного общения в интернете. А не тупят только идиоты. Дальше у меня на тебя игнор.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> Ага, переставляет местами операции записи контрольных регистров SSC и PDC в итоге получается фуфло.

Где записи этих регистров в твоём сэмпле кода в #1 посте? Их нет.

И ещё, неужели ты не вкурсе про memory barriers? Смех и грех. Зато ЧСВ и упёртость зашкаливает.

anonymous
()
Ответ на: комментарий от mskmsk1985

> Во вторых Вы мне так и не удосужелись объяснить какого хрена порядок строк кода влияет на выравнивание

Тебе уже писали про кэши. Если значение попадёт в кэш, а дальше этот кэшлайн будет сброшен - то данные покараптятся. Разве это не очевидно? Плюс порядок строк кода в структе влияет на поля и на выравние. Это тоже очевидно.

а проблема именно в перемене местами строчек кода.

Каких именно строк? Ты писал, что проблема в убирании 1ой строки. Научись 1) формулировать свои мысли 2) Предоставлять (хотя бы по-запросу) сэмплы кода - рабочего и нет, чтоб остальным не приходилось выдумывать за тебя и предлгагать решения (хотя эти решения ты и так отвергаешь).

Втретьих , опустим, ибо конструктив с Вашей стороны похоже иссекает.

libastral сегодня барахлит, трудно читать твой код через твой мозг.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.