Перейти к содержанию
    

Посмотрел примеры драйверов, все, оказывается, пользуются read, write???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"Нативными" методами работы с драйверами устройств являются open,read,write,close.

fopen,fread,fwrite,fclose - это уже функции библитеки libc, они удобны для работы с файлами, как с потоками данных (stream), поэтому читают из устройства (как бы файла) сразу большими блоками и буферизируют внутри себя данные. Это позволяет добиться существенного выиграша в скорости при работе с файловой системой, даже если верхний уровень читает по 16 байт, в "глубине души" чтение идёт блоками, удобными устройству и буферизируется, а когда юзер снова попросит следующие 16 байт, уже ничего читать не нужно, можно скопировать из буфера уже прочитанное...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Откуда взялся номер 11 в конфигурационной области? Если его пишет система (или BIOS), то почему после переопределения номера линии прерывания он не переписывается на правильный?

 

Полагаю, что он задается в device tree.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

Возник вопрос, какой максимальный размер памяти с непрерывной адресацией можно выделить в ядре?

Посмотрел, что kmalloc, dma_alloc_coherent максимум дают 4МБ, что делать если хочу больше?

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если использовать alloc_pages, то вообще выделяет только 8 страниц, далее выдаёт ошибку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую.

В функции инициализации модуля pcievx7_init хочу добраться до struct pci_dev *pdev, вроде как должно помочь container_of, но получаются

разные значения для pdev и my_pdev. Может кто подскажет, что тут неправильно? Значения pdev->driver и &pcievx7_pci_driver одинаковы.

static int pcievx7_probe(struct pci_dev *pdev , const struct pci_device_id *id)
{
    ...
    PINFO("pdev = %p\n", pdev);
    PINFO("pdev->driver = %p\n", pdev->driver); // выводит в syslog адрес pcievx7_pci_driver = DRIVER_ADDRESS
    ...
}

static struct pci_driver pcievx7_pci_driver =
{
    .name        = DRIVER_NAME,
    .probe        = pcievx7_probe,
    .remove        = pcievx7_remove,
    .id_table    = pcievx7_pci_driver_ids
};

static int __init pcievx7_init(void)
{
    struct pci_dev *my_pdev; 
    ...
    pci_register_driver(&pcievx7_pci_driver);
    PINFO("&pcievx7_pci_driver = %p\n", &pcievx7_pci_driver); // выводит в syslog адрес pcievx7_pci_driver = DRIVER_ADDRESS
    my_pdev = container_of(&pcievx7_pci_driver, struct pci_dev, driver);
    PINFO("my_pdev = %p\n", my_pdev);
    ...
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы поле имени pdev->driver->name напечатал в консоль для обоих. Может помочь понять. Перед печатью проверьте если pdev->driver не равен нулю иначе система рухнет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы поле имени pdev->driver->name напечатал в консоль для обоих. Может помочь понять. Перед печатью проверьте если pdev->driver не равен нулю иначе система рухнет.

Если правильно Вас понял, то сделал это:

static int pcievx7_probe(struct pci_dev *pdev , const struct pci_device_id *id)
{
    PINFO("%s\n", pdev->driver->name); // выводит в syslog имя драйвера "pcievx7"
}

static struct pci_driver pcievx7_pci_driver =
{
    .name        = DRIVER_NAME,
    .probe       = pcievx7_probe,
    .remove      = pcievx7_remove,
    .id_table    = pcievx7_pci_driver_ids
};

static int __init pcievx7_init(void)
{
    pci_register_driver(&pcievx7_pci_driver);
    PINFO("%s\n", (&pcievx7_pci_driver)->name); // выводит в syslog имя драйвера "pcievx7"
}

Имя драйвера в обоих случаях одинаково. Вопрос остался.

 

Попробовал сделать так:

static int pcievx7_probe(struct pci_dev *pdev , const struct pci_device_id *id)
{
    struct pci_dev *test_pdev;

    test_pdev = container_of(pdev->driver, struct pci_dev, driver);

    PINFO("%p\n", test_pdev);
    PINFO("%p\n", pdev);
}

Получаю разные значения для test_pdev и pdev. Объясните, что тут неправильно?

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Надо было так:

static int pcievx7_probe(struct pci_dev *pdev , const struct pci_device_id *id)
{
    struct pci_dev *test_pdev;

    test_pdev = container_of(&pdev->driver, struct pci_dev, driver);

    PINFO("%p\n", test_pdev);
    PINFO("%p\n", pdev);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если использовать alloc_pages, то вообще выделяет только 8 страниц, далее выдаёт ошибку.

Так это же известнейшее ограничение что нельзя сразу много страниц вподряд выделить. Для этого надо использовать SG-DMA подход (LDD3, 15.4. Direct Memory Access). Я как раз сам в процессе освоения этого.

 

У Вас что-то получилось по этой теме? Куча вопросов, я пока только смог сделать запись и чтение регистров своего устройства через MMIO...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так это же известнейшее ограничение что нельзя сразу много страниц вподряд выделить.

 

В последних ядрах есть CMA (Contiguous Memory Allocator), в принципе можно выделить и подряд много, сам пробовал, получалось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В последних ядрах есть CMA (Contiguous Memory Allocator), в принципе можно выделить и подряд много, сам пробовал, получалось.

Я может что-то не понимаю, но меня искренне удивляет что работа устройства будет отдана воле случая, выделится а может нет - зачем такое делать?

 

Допустим в системе 16 гигабайт ОЗУ. CMA может выделить буфер 5 гигабайт? Я знаю что так делать не хорошо, но что если будет некоторое устройство, которому именно что требуется это, и пользователь будет предупрежден что именно столько надо для работы устройства.

 

Я сторонник исключительно 100% надежно работающих подходов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я может что-то не понимаю, но меня искренне удивляет что работа устройства будет отдана воле случая, выделится а может нет - зачем такое делать?

 

Допустим в системе 16 гигабайт ОЗУ. CMA может выделить буфер 5 гигабайт? Я знаю что так делать не хорошо, но что если будет некоторое устройство, которому именно что требуется это, и пользователь будет предупрежден что именно столько надо для работы устройства.

 

Я сторонник исключительно 100% надежно работающих подходов.

 

Я так понимаю, если в системе только один драйвер использует подобный алгоритм выделения памяти, то вообще никаких проблем не будет, если несколько, то надо следить за суммарным размером области. В целом да, специфично, но зато можно без SGDMA обойтись. Да и производительность чуть-чуть будет повыше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...