LINUX.ORG.RU

6
Всего сообщений: 75

Как пользоваться модулем ядра gpio-beeper?

Всем привет!

Есть такой чудный модуль. Создал для него DTS и прописал там ногу процессора. Подгрузил модуль в ядро. Вроде как на этом всё. А как пикнуть то? :)

модуль зарегистрировал себя как:

input_set_capability(input, EV_SND, SND_BELL);


Как теперь из ОС взаимодействовать с такими устройствами?

 ,

Spider55 ()

Поиск исполнителей и сбор донатов и на рефакторинг кода ядерной консоли.

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

Контакты можно публиковать не открытыми, а в виде команды пишущей их в терминале, например:
echo FM3SQOJSGEUTGNZQFUZDKLJVHEFA====|base32 -d

Создал в организации репозитарий, предлагаю обсуждение продолжить там:
https://github.com/Kernel-Crowdfunding/New-Linux-Console

Ссылка для записи разработчиков: Developers
Ссылка для записи спонсоров: Sponsors

Мотивация:

  1. Необходимость исправить указанные Линусом ошибки: Линуса гномеры покусали?
  2. Запуск иксов на дополнительной отдельной видеокарте нарушает работу консоли на основной видеокарте.
  3. Если раньше собственно консоль и иксы пользовались раздельными драйверами, и переключение в консоль при переполнении ОЗУ приводило к переключению на другой драйвер которому для нормальной работы хватало оставшейся памяти, что позволяло запустить htop и вручную удалить занимающий всю свободную память процесс, то теперь, когда благодаря KMS иксы и консоль используют один драйвер так уже сделать нельзя, распухшая графическая программа парализует работу графики и иксах, и в консоли.
    Подробнее можно прочитать здесь: Поиск исполнителей и сбор донатов и на рефакторинг кода ядерной консоли. (комментарий)

Что имхо надо, оно же ТЗ:

  1. Вынести код консоли в отдельный модуль ядра, который должен уметь принимать опции инициализации и как аргумент запуска модуля, и как опцию в командной строке ядра, при этом опции в командной строке ядра должны иметь приоритет, чтобы иметь возможность спасти положение при неправильном написании системных конфигов.
    При этом надо понимать то, что данное внесённое предложение предлагает не текущий ремонт подсистемы консоли, а полностью новый код для развития системы консоли с новым функционалом.
  2. В состав принимаемых модулем опций должны входить:
    2.1 Однозначная идентификация используемых видеопортов для подключения монитора должна осуществляться через указание конкретной используемой видеокарты по идентификаторам вендора, модели устройства,серийному номеру и идентификатору используемого для подключения монитора видеопорта.
    2.2 Аналогично однозначная идентификация назначаемых модулю клавиатуры и мыши, с указанием индентификаторов и типа подключаемого устройства ввода? Или может просто давать список устройств без указания их типа, а там модуль пусть разбирается сам, где мышь, а где клавиатура?
    2.3 Модуль должен использовать только статичное выделение памяти с запретом свопинга(Мотивация 3) и принимать в опциях размер буферов, под которые сразу должен выделять память и не менять самостоятельно её в процессе работы, но возможно создание в /proc или /sys отдельной директории с параметрами через которые можно будет поменять размер тех или иных буферов и поменять прочие настройки модуля.
  3. Должна быть предусмотрена возможность параллельной загрузки и работы нескольких таких модулей, на разных комплектах из видеокарты, клавиатуры и прочих USB устройств, этот модуль должен уметь проверять занятие устройств другими модулями и выдавать соответствующую ошибку и список со статусом, кто чем занят всех имеющихся устройств.
    Вообще надо подумать как этим модулем будут обрабатываться конфликты занятости того или иного устройства теми или иными модулями или программами ядра.
    Всё это надо за тем, чтобы за одним компом могло работать несколько человек с разных комплектов видеокарта + устройства ввода(клавиатура, мышь и пр.) и эти устройства не путались между различными модулями.
  4. Надо предусмотреть продолжение работы модуля при отключении или пропажи связи с тем иным устройством и возобновления работы с ним при его обратном подключении к системе.
    Должна быть предусмотрена возможность запуска модуля при отсутствии в системе назначенных ему устройств.
  5. Модуль должен использовать только общие стандартные интерфейсы видеокарт(Мотивация 3)
  6. При запуске на той или иной видеокарте иксервера модуль должен передавать и принимать управление видеокартой аналогично тому, как это происходило до появления KMS и modesetting.(Мотивация 3)
    Так же он должен суметь передать и все сопутствующие устройства ввода(тут возможно придётся попилить и икссервер)
  7. В принципе хорошо бы и сам графический сервер переписать так, чтобы при параллельном запуске нескольких экземпляров на разных видеокартах каждый экземпляр бы наследовал от модуля консоли привязанного к данной видеокарте назначенные этому модулю консоли устройства ввода, для этого надо предусмотреть экспорт информации о подключенных устройствах в файл на файловых системах /proc или /sys.
    (Сервер можно не переписывать, но механизм передачи и приёма устройств ввода предусмотреть нужно)
  8. Надо предусмотреть вывод консоли в стереорежиме при работе с устройством через VR шлем. Ничего сложного делать не надо, просто выводить текст на два экрана со смещением влево для левого и вправо для правого экрана для того чтобы при просмотре через VR шлем можно было просматривать текст обоими глазами, а не одним. Номера портов в видеокарте для вывода в стереорежиме и величина смещения кадров должна задаваться через параметр командной строке ядра и через специальные файлы в proc и sysfs.
  9. При подключении к видеокарте нескольких мониторов модуль должен вывести консоль на каждый монитор, при этом каждая выведенная консоль должна свободно переключатся на любую консоль, но при этом каждая консоль должна отобразатся только на одном экране, при этом при переключении консоли текущая консоль и консоль на которую переключаются должны менятся местами.

Перемещено leave из job

 , , , ,

torvn77 ()

I3-gaps, polybar, module/i3

Не так давно решил опробовать WM под название i3wm, все устраивает, в целом разобрался. Но есть момент, который не могу понять.

В модуле i3 для панельки polybar я закоментировал несколько рабочих столов, дабы они не отображались, сделал отображение имени стола, а не номера. Так вот, при переключении на 10 рабочий стол, он переключается, но он закоментирован и не должен отображаться и более того, он именуется первым рабочим столм. Выглядит это примерно так: https://i.imgur.com/cT8vvo7.png

Не то, чтобы это так уж критично, но хотелось бы понять, почему такое происходит. С 9, 8 рабочими столами все ок.

Если кто знает причину и куда копать, подскажите, пожалуйста.

 , ,

skyhawk1979 ()

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

Есть модуль ядра, вроде loop, только его можно попросить создать устройство не для общения с файлом, а для общения с другим блочным устройством (попутно выполняя некоторые преобразования над данными). При старте системы модуль загружается из initrd, и создаёт устройство (по просьбе) /dev/xcc0 для общения с /dev/sda2. Далее, система успешно грузится с /dev/xcc0. После входа в систему, прошу модуль создать ещё одно устройство, для общения с /dev/loop0, а он создаёт мне опять /dev/xcc0. Без initrd всё работает как надо. При необходимости могу выложить код создания устройства, если предоставленной информации будет недостаточно. В чём может быть дело?

 , , , ,

zenbooster ()

Запуск модуля ядра wil6210

помогите завести wifi.

Я занялся портирование linux на Android устройство, но столкнулся с трудностью запуска wifi.Но я не понимаю некоторых тонкостей. так что если я не прав поправите.

  1. Запускается модуль ядра.
  2. Запускается framework
  3. Запуск network-manager

я нарыл вот это, но что с этим делать не очень понимаю wireless.wiki.kernel.org - wil6210

этой командой я запускаю модуль wil6210

$ sudo insmod /lib/modules/3.18.71XR5/kernel/drivers/net/wireless/ath/wil6210/wil6210.ko rtap_include_phy_info=0 rx_align_2=0 max_assoc_sta=1 agg_wsize=0 led_id=0 use_msi=1 alt_ifname=1 debug_fw=0 oob_mode=0 no_fw_recovery=0 rx_ring_overflow_thrsh=1 rx_ring_order=10 tx_ring_order=10 bcast_ring_order=7

но модуль не запукаеться, а в dmesg пишет

[  481.572726] Context not found

вот я и не понимаю что за контекст он не может найти это контекст selinux или framework или чего другого, а ещё я бы не откозался от пояснения как работает это дело

 , ,

rootlol ()

Для запуска бота выдает ошибку Error: Cannot find module 'talib'

Всем привет.

Я пытаюсь запустить команду в боте и мне выдает ошибку талиб.

Я ставлю командой талиб вот sudo npm install talib а оно теперь выдает ошибку npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! talib@1.1.3 install: `node ./src/lib/build.js && node-gyp configure && node-gyp build` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the talib@1.1.3 install script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

Я не давно разбираюсь в этом и не могу понять, почему оно не ставит его.

Заранее благодарен.

 

Enrico ()

Видимость функций

OpenWrt: в ядре есть cfg80211, скомпилен как модуль ядра, так же есть драйвер который скомпилен как модуль ядра. Необходимо сделать так, что бы драйвер видел функции модуля cfg80211. Как сделать?

 ,

k000858 ()

Ошибка при попытке закрузки модуля

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

modprobe snd-usb-audio
modprobe: FATAL: Module snd-usb-audio not found in directory /lib/modules/4.19.86-gentoo

Ядро собрал с этим модулем, по идее он лежит где положено, даже автодополнение modprobe показывает его имя (не факт, что это значит, что все хорошо).

Кто с таким сталкивался и как побороть? Да, modprobe делаю из-под рута, все ок.

//Всех с наступающим.

Спасибо анону, помог его совет: Ошибка при попытке закрузки модуля (комментарий)

 , ,

LongLiveUbuntu ()

Не запускается модуль pulseaudio

Доброго времени суток. Хочу передать звук с arch на android. Делаю так:

pactl load-module module-simple-protocol-tcp rate=48000 format=s16le channels=2 source=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor record=true port=8000 listen=192.168.1.130
а arch мне в ответ:
Произошла ошибка: Не удалось инициализировать модуль
а я ему с правами sudo:
sudo pactl load-module module-simple-protocol-tcp rate=48000 format=s16le channels=2 source=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor record=true port=8000 listen=192.168.1.130
а он мне:
Ошибка подключения: Соединение отвергнуто
Произошла ошибка при выполнении pa_context_connect(): Соединение отвергнуто
Вот чего он выпендривается?

 , , , ,

AnnaS ()

Отваливается netif_rx при передаче sk_buff от netlink socket.

Создал соединение между user space и kernel space через netlink socket. В программе формирую raw-пакет и шлю его через netlink socket в модуль. В модуле принимаю его как sk_buff. Ядро при этом виснет намертво, а логи просто обрываются. Как все таки правильно отправить буффер в netif_rx?

Сам код:

static void nl_recv_msg(struct sk_buff *skb) {

	char *msg = skb->data + 16;
	int msg_size = skb->len - 16 - 3;
	struct sk_buff *skb_out;

	skb_out = dev_alloc_skb(msg_size);
	if (skb_out) {
		skb_put(skb_out, msg_size);
		memcpy(skb_out->data, msg, msg_size);
		skb_out->dev = dev;
		skb_out->protocol = 0x0019; /* ETH_P_80211_RAW */
		skb_out->ip_summed = CHECKSUM_UNNECESSARY;
		netif_rx(skb_out);
	} else {
		pr_err("Allocation failure.\n");
	}
}

Функция «nl_recv_msg» используется тут:

static int __init my_init( void ) {
	struct netlink_kernel_cfg cfg = {
		.input = nl_recv_msg,
	};

        ......................................................

	nl_sk = netlink_kernel_create(&init_net, MYPROTO, &cfg);

        ......................................................

}

 , , ,

kashka ()

вызов generic_make_request из обработчика запросов блочного устройства

Есть проект: https://github.com/OrenKishon/stackbd - это блочное устройство, которое перенаправляет все запросы на некоторое другое устройство, попутно добавляя информацию об этих запросах в syslog. В качестве подхода к реализации обмена данными выбрано прямое выполнение запроса без использование очереди. Если же переделать код таким образом, что бы очередь использовалась, модуль повисает в том случае, если в устройство записать больше 8 секторов за раз (с помощью dd например, при count=9). С чтением при этом проблем нет.

Есть идеи, почему так, как лечить?

#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
 
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h>     /* everything... */
#include <linux/errno.h>  /* error codes */
#include <linux/types.h>  /* size_t */
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/kthread.h>
 
#include <trace/events/block.h>
 
#include "../common/stackbd.h"
 
#define USE_BLKMQ 1
 
#if USE_BLKMQ
#include <linux/blk-mq.h>
#endif
 
#define LOGOUT(lvl, fmt, args...) printk(lvl "%s [task=%p] %s: " fmt, THIS_MODULE->name, current, __func__, ## args)
#define PINFO(fmt, args...) LOGOUT(KERN_INFO, fmt, ## args)
#define PWARN(fmt, args...) LOGOUT(KERN_WARNING, fmt, ## args)
#define PERROR(fmt, args...) LOGOUT(KERN_ERR, fmt, ## args)
 
#define STACKBD_BDEV_MODE (FMODE_READ | FMODE_WRITE | FMODE_EXCL)
#define DEBUGGG printk("stackbd: %d\n", __LINE__);
/*
 * We can tweak our hardware sector size, but the kernel talks to us
 * in terms of small sectors, always.
 */
#define KERNEL_SECTOR_SHIFT 9
#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT)
#define KERNEL_PAGE_SHIFT 12
#define KERNEL_PAGE_SIZE (1 << KERNEL_PAGE_SHIFT)
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
#   define DECLARE_BIO_VEC struct bio_vec
#   define ACCESS_BIO_VEC(x) (x)
#else
#   define DECLARE_BIO_VEC struct bio_vec *
#   define ACCESS_BIO_VEC(x) (*(x))
#endif
 
MODULE_LICENSE("Dual BSD/GPL");
 
static int major_num = 0;
module_param(major_num, int, 0);
static int LOGICAL_BLOCK_SIZE = 4096;
module_param(LOGICAL_BLOCK_SIZE, int, 0);
 
/*
 * The internal representation of our device.
 */
static struct stackbd_t {
    sector_t capacity; /* Sectors */
    struct gendisk *gd;
    spinlock_t lock;
    struct bio_list bio_list;    
    struct task_struct *thread;
    int is_active;
    struct block_device *bdev_raw;
    /* Our request queue */
    struct request_queue *queue;
#if USE_BLKMQ
    struct blk_mq_tag_set tag_set;
#endif
} stackbd;
 
struct bio_private
{
    void *bi_private_old;
    void *data;
    bool is_ready;
};
 
typedef struct hidden_cmd_s
{
    long ret;
} hidden_cmd_t;
 
 
static DECLARE_WAIT_QUEUE_HEAD(req_event);
 
int ald_buffer_read(
    unsigned long sector,
    unsigned long nsect,
    char *buffer
)
{
    int result = 0;
    unsigned nsize = nsect << KERNEL_SECTOR_SHIFT;
    int npages = ((nsize - 1) >> KERNEL_PAGE_SHIFT) + 1;
    struct bio *bio = bio_alloc(GFP_ATOMIC, npages);
    struct block_device *bdev = stackbd.bdev_raw;
 
    PINFO("begin; sector=%ld; nsect=%ld; buffer=%p\n", sector, nsect, buffer);
 
    if(unlikely(!bio))
    {
        PINFO("bio_alloc failed!\n");
        result = -ENOMEM;
        return result;
    }
    bio_set_dev(bio, bdev);
    bio->bi_iter.bi_sector = sector;
    bio_set_op_attrs(bio, REQ_OP_READ, 0);
    {
        char *ptr = buffer;
        do
        {
            struct page *page;
            page = virt_to_page(ptr);
            if(unlikely(!page))
            {
                PINFO("virt_to_page failed!\n");
                result = -ENOMEM;
                break;
            }
 
            {
                unsigned this_step = min((unsigned)(PAGE_SIZE - offset_in_page(ptr)), nsize);
                bio_add_page(bio, page, this_step, offset_in_page(ptr));
                nsize -= this_step;
                ptr += this_step;
            }
        } while(nsize > 0);
 
        if(likely(!result))
        {
            result = submit_bio_wait(bio);
        }
        bio_put(bio);
    }
    PINFO("end (%d)\n", result);
    return result;
}
 
int ald_buffer_write(
    unsigned long sector,
    unsigned long nsect,
    char *buffer
)
{
    int result = 0;
    unsigned nsize = nsect << KERNEL_SECTOR_SHIFT;
    int npages = ((nsize - 1) >> KERNEL_PAGE_SHIFT) + 1;
    struct bio *bio = bio_alloc(GFP_ATOMIC, npages);
    struct block_device *bdev = stackbd.bdev_raw;
 
    PINFO("begin; sector=%ld; nsect=%ld; buffer=%p\n", sector, nsect, buffer);
 
    if(unlikely(!bio))
    {
        PINFO("bio_alloc failed!\n");
        result = -ENOMEM;
        return result;
    }
    bio_set_dev(bio, bdev);
    bio->bi_iter.bi_sector = sector;
    bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
    {
        char *ptr = buffer;
        do
        {
            struct page *page = virt_to_page(ptr);
 
            if(unlikely(!page))
            {
                PINFO("alloc page failed!\n");
                result = -ENOMEM;
                break;
            }
 
            {
                unsigned op = offset_in_page(ptr);
                unsigned this_step = min((unsigned)(KERNEL_PAGE_SIZE - op), nsize);
                bio_add_page(bio, page, this_step, op);
                nsize -= this_step;
                ptr += this_step;
            }
        } while(nsize > 0);
 
        if(likely(!result))
        {
            result = submit_bio_wait(bio);
        }
        bio_put(bio);
    }
    PINFO("end (%d)\n", result);
    return result;
}
 
#if USE_BLKMQ
static void pb_alloc(struct bio *bio, void *data)
{
    struct bio_private *pb = kmalloc(sizeof(struct bio_private), GFP_ATOMIC);
 
    pb->bi_private_old = bio->bi_private;
    pb->data = data;
    pb->is_ready = false;
    bio->bi_private = pb;
}
 
static void pb_free(struct bio *bio)
{
    struct bio_private *pb = bio->bi_private;
    void *t = bio->bi_private;
    bio->bi_private = pb->bi_private_old;
    kfree(t);
}
#endif
 
static void my_bio_complete(struct bio *bio, int ret)
{
#if USE_BLKMQ
   struct bio_private *pb = bio->bi_private;
   struct request *rq = pb->data;
 
   pb_free(bio);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
   blk_mq_end_request(rq, ret ? BLK_STS_IOERR : BLK_STS_OK);
#else
   blk_mq_end_io(rq, ret ? BLK_STS_IOERR : BLK_STS_OK);
#endif
 
#else // #if USE_BLKMQ
    bio_endio(bio);
#endif // #if USE_BLKMQ
}
 
 
static void stackbd_io_fn(struct bio *bio)
{
    sector_t sector = bio->bi_iter.bi_sector;
    int size = bio->bi_iter.bi_size;
    int nsect = size >> KERNEL_SECTOR_SHIFT;
    DECLARE_BIO_VEC bvec;
    struct bvec_iter iter;
    u8 *buffer = kmalloc(size, GFP_ATOMIC);
    u8 *ptr = buffer;
 
    if (bio_data_dir(bio) == READ)
    {
        ald_buffer_read(sector, nsect, ptr);
 
        bio_for_each_segment(bvec, bio, iter)
        {
            u8 *dst = page_address(ACCESS_BIO_VEC(bvec).bv_page) + ACCESS_BIO_VEC(bvec).bv_offset;
            int len = ACCESS_BIO_VEC(bvec).bv_len;
            memcpy(dst, ptr, len);
            ptr += len;
        }
    }
    else
    {
        bio_for_each_segment(bvec, bio, iter)
        {
            u8 *src = page_address(ACCESS_BIO_VEC(bvec).bv_page) + ACCESS_BIO_VEC(bvec).bv_offset;
            int len = ACCESS_BIO_VEC(bvec).bv_len;
            memcpy(ptr, src, len);
            ptr += len;
        }
        ald_buffer_write(sector, nsect, buffer);
    }
    kfree(buffer);
    my_bio_complete(bio, 0);
}
 
static int stackbd_threadfn(void *data)
{
    struct bio *bio;
 
    set_user_nice(current, -20);
 
    while (!kthread_should_stop())
    {
        /* wake_up() is after adding bio to list. No need for condition */ 
        wait_event_interruptible(req_event, kthread_should_stop() ||
                !bio_list_empty(&stackbd.bio_list));
 
        spin_lock_irq(&stackbd.lock);
        if (bio_list_empty(&stackbd.bio_list))
        {
            spin_unlock_irq(&stackbd.lock);
            continue;
        }
 
        bio = bio_list_pop(&stackbd.bio_list);
        spin_unlock_irq(&stackbd.lock);
 
        stackbd_io_fn(bio);
    }
 
    return 0;
}
 
#if USE_BLKMQ
//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 3)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
static blk_status_t hidden_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data* bd)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
static blk_status_t hidden_queue_rq(struct blk_mq_hw_ctx *hctx, struct request* rq, bool last)
#else
static blk_status_t hidden_queue_rq(struct blk_mq_hw_ctx *hctx, struct request* rq)
#endif
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
    struct request *rq = bd->rq;
#endif
    struct bio *bio = rq->bio;
    pb_alloc(bio, rq);
    spin_lock_irq(&stackbd.lock);
    if (!stackbd.bdev_raw)
    {
        printk("stackbd: Request before bdev_raw is ready, aborting\n");
        goto abort;
    }
    if (!stackbd.is_active)
    {
        printk("stackbd: Device not active yet, aborting\n");
        goto abort;
    }
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
    blk_mq_start_request(rq);
#endif
 
    bio_list_add(&stackbd.bio_list, bio);
    wake_up(&req_event);
exit:
    spin_unlock_irq(&stackbd.lock);
 
//exit:
    return BLK_STS_OK; //always return ok
abort:
    my_bio_complete(bio, -EIO);
    goto exit;
}
 
static struct blk_mq_ops _mq_ops =
{
    .queue_rq = hidden_queue_rq,
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 2, 0)
    .map_queue = blk_mq_map_queue
#endif
};
#else // #if USE_BLKMQ
/*
 * Handle an I/O request.
 */
static blk_qc_t stackbd_make_request(struct request_queue *q, struct bio *bio)
{
    printk("stackbd: make request %-5s block %-12lu #pages %-4hu total-size "
            "%-10u\n", bio_data_dir(bio) == WRITE ? "write" : "read",
            bio->bi_iter.bi_sector, bio->bi_vcnt, bio->bi_iter.bi_size);
 
//    printk("<%p> Make request %s %s %s\n", bio,
//           bio->bi_rw & REQ_SYNC ? "SYNC" : "",
//           bio->bi_rw & REQ_FLUSH ? "FLUSH" : "",
//           bio->bi_rw & REQ_NOIDLE ? "NOIDLE" : "");
//
    spin_lock_irq(&stackbd.lock);
    if (!stackbd.bdev_raw)
    {
        printk("stackbd: Request before bdev_raw is ready, aborting\n");
        goto abort;
    }
    if (!stackbd.is_active)
    {
        printk("stackbd: Device not active yet, aborting\n");
        goto abort;
    }
    bio_list_add(&stackbd.bio_list, bio);
    wake_up(&req_event);
    spin_unlock_irq(&stackbd.lock);
 
    goto exit;
 
abort:
    spin_unlock_irq(&stackbd.lock);
    printk("<%p> Abort request\n\n", bio);
    bio_io_error(bio);
exit:
    return BLK_QC_T_NONE;
}
#endif // #if USE_BLKMQ
 
static struct block_device *stackbd_bdev_open(char dev_path[])
{
    /* Open underlying device */
    struct block_device *bdev_raw = lookup_bdev(dev_path);
    printk("Opened %s\n", dev_path);
 
    if (IS_ERR(bdev_raw))
    {
        printk("stackbd: error opening raw device <%lu>\n", PTR_ERR(bdev_raw));
        return NULL;
    }
 
    if (!bdget(bdev_raw->bd_dev))
    {
        printk("stackbd: error bdget()\n");
        return NULL;
    }
 
    if (blkdev_get(bdev_raw, STACKBD_BDEV_MODE, &stackbd))
    {
        printk("stackbd: error blkdev_get()\n");
        bdput(bdev_raw);
        return NULL;
    }
 
    return bdev_raw;
}
 
static int stackbd_start(char dev_path[])
{
    unsigned max_sectors;
 
    if (!(stackbd.bdev_raw = stackbd_bdev_open(dev_path)))
        return -EFAULT;
 
    /* Set up our internal device */
    stackbd.capacity = get_capacity(stackbd.bdev_raw->bd_disk);
    printk("stackbd: Device real capacity: %lu\n", stackbd.capacity);
 
    set_capacity(stackbd.gd, stackbd.capacity);
 
    max_sectors = queue_max_hw_sectors(bdev_get_queue(stackbd.bdev_raw));
    blk_queue_max_hw_sectors(stackbd.queue, max_sectors);
    printk("stackbd: Max sectors: %u\n", max_sectors);
 
    stackbd.thread = kthread_create(stackbd_threadfn, NULL,
           stackbd.gd->disk_name);
    if (IS_ERR(stackbd.thread))
    {
        printk("stackbd: error kthread_create <%lu>\n",
               PTR_ERR(stackbd.thread));
        goto error_after_bdev;
    }
 
    printk("stackbd: done initializing successfully\n");
    stackbd.is_active = 1;
    wake_up_process(stackbd.thread);
 
    return 0;
 
error_after_bdev:
    blkdev_put(stackbd.bdev_raw, STACKBD_BDEV_MODE);
    bdput(stackbd.bdev_raw);
 
    return -EFAULT;
}
 
static int stackbd_ioctl(struct block_device *bdev, fmode_t mode,
             unsigned int cmd, unsigned long arg)
{
    char dev_path[80];
    void __user *argp = (void __user *)arg;    
 
    switch (cmd)
    {
    case STACKBD_DO_IT:
        printk("\n*** DO IT!!!!!!! ***\n\n");
 
        if (copy_from_user(dev_path, argp, sizeof(dev_path)))
            return -EFAULT;
 
        return stackbd_start(dev_path);
    default:
        return -ENOTTY;
    }
}
 
/*
 * The HDIO_GETGEO ioctl is handled in blkdev_ioctl(), which
 * calls this. We need to implement getgeo, since we can't
 * use tools such as fdisk to partition the drive otherwise.
 */
int stackbd_getgeo(struct block_device * block_device, struct hd_geometry * geo)
{
    long size;
 
    /* We have no real geometry, of course, so make something up. */
    size = stackbd.capacity * (LOGICAL_BLOCK_SIZE / KERNEL_SECTOR_SIZE);
    geo->cylinders = (size & ~0x3f) >> 6;
    geo->heads = 4;
    geo->sectors = 16;
    geo->start = 0;
    return 0;
}
 
/*
 * The device operations structure.
 */
static struct block_device_operations stackbd_ops = {
        .owner  = THIS_MODULE,
        .getgeo = stackbd_getgeo,
        .ioctl  = stackbd_ioctl,
};
 
static int __init stackbd_init(void)
{
    /* Set up our internal device */
    spin_lock_init(&stackbd.lock);
 
    /* blk_alloc_queue() instead of blk_init_queue() so it won't set up the
     * queue for requests.
     */
#if USE_BLKMQ
    stackbd.tag_set.ops = &_mq_ops;
    stackbd.tag_set.nr_hw_queues = 1;
    stackbd.tag_set.queue_depth = 128;
    stackbd.tag_set.numa_node = NUMA_NO_NODE;
    stackbd.tag_set.cmd_size = sizeof(hidden_cmd_t);
    stackbd.tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE | BLK_MQ_F_BLOCKING;
    stackbd.tag_set.driver_data = &stackbd;
 
    {
        int res = blk_mq_alloc_tag_set(&stackbd.tag_set);
        if (res)
        {
            PWARN("unable to allocate tag set (%d)\n", res);
            return -EFAULT;
        }
    }
    stackbd.queue = blk_mq_init_queue(&stackbd.tag_set);
    if (IS_ERR(stackbd.queue))
    {
        int res = PTR_ERR(stackbd.queue);
        PWARN("Failed to allocate queue (%d)", res);
        return -EFAULT;
    }
#else
    if (!(stackbd.queue = blk_alloc_queue(GFP_KERNEL)))
    {
        printk("stackbd: alloc_queue failed\n");
        return -EFAULT;
    }
 
    blk_queue_make_request(stackbd.queue, stackbd_make_request);
#endif
    blk_queue_logical_block_size(stackbd.queue, LOGICAL_BLOCK_SIZE);
 
    /* Get registered */
    if ((major_num = register_blkdev(major_num, STACKBD_NAME)) < 0)
    {
        printk("stackbd: unable to get major number\n");
        goto error_after_alloc_queue;
    }
 
    /* Gendisk structure */
    if (!(stackbd.gd = alloc_disk(16)))
        goto error_after_redister_blkdev;
    stackbd.gd->major = major_num;
    stackbd.gd->first_minor = 0;
    stackbd.gd->fops = &stackbd_ops;
    stackbd.gd->private_data = &stackbd;
    strcpy(stackbd.gd->disk_name, STACKBD_NAME_0);
    stackbd.gd->queue = stackbd.queue;
    add_disk(stackbd.gd);
 
    printk("stackbd: init done\n");
 
    return 0;
 
error_after_redister_blkdev:
    unregister_blkdev(major_num, STACKBD_NAME);
error_after_alloc_queue:
    blk_cleanup_queue(stackbd.queue);
 
    return -EFAULT;
}
 
static void __exit stackbd_exit(void)
{
    printk("stackbd: exit\n");
 
    if (stackbd.is_active)
    {
        kthread_stop(stackbd.thread);
        blkdev_put(stackbd.bdev_raw, STACKBD_BDEV_MODE);
        bdput(stackbd. bdev_raw);
    }
 
    del_gendisk(stackbd.gd);
    put_disk(stackbd.gd);
    unregister_blkdev(major_num, STACKBD_NAME);
    blk_cleanup_queue(stackbd.queue);
#if USE_BLKMQ
    if (stackbd.tag_set.tags)
        blk_mq_free_tag_set(&stackbd.tag_set);
#endif
}
 
module_init(stackbd_init);
module_exit(stackbd_exit);

 , , , ,

zenbooster ()

как создать виртуальный platform_device в ядре?

Пытаюсь заюзать старый код от 2012 года https://gist.github.com/maxlapshin/99c01ab4cf4e48d76819f4a96f6b8a90

dvb_dummy_adapter.c

Штука делает простую вещь: программа настраивает тестовый DVB тюнер и начинает сосать данные. Данные попадают те, которые заливаются в тюнер из юзерленда через /dev/dvb/adapter0/dvr0

Сейчас драйвер устроен как platform_driver

В нём есть старый код, который deprecated: в инициализации драйвера идет прямое создание устройства:

https://gist.github.com/maxlapshin/99c01ab4cf4e48d76819f4a96f6b8a90#file-dvb_...

platform_device_register_simple

Это мало того, что очень не рекомендуется, так ещё и не дает выгрузить драйвер: после rmmod в /sys/devices/platform/dvb_dummy_adapter.0 остаются данные

Вопрос: а как отказаться от platform_device_register_simple если такого устройства нет?

Как сообщить ядру, что я хочу что бы создалось устройство dvb_dummy_adapter@0, которое будет обслуживаться этим драйвером?

Если я правильно понимаю, то в нормальных условиях какой-то пробник шины найдет устройство и запустит ему функцию probe, а как это должно тут работать?

 , , ,

max_lapshin ()

go module

Hi all !

Пару лет мне понадобилось написать одну небольшую прожку на go, ну более менее разобрался, написал ... потом особо не требовалось.

Тут опять нужно стало, беру го по новее начинаю читать что там изменилось, и увидел сабж. Хм.

Что то мне не очень нравится эта затея :( Раньше было наоборот прикольно все упорядочивалось в одном месте ... а теперь что ? Может я что то не догоняю ?

Спросил у знающего народа - сказали что это из-за того что многие не могли осилить го-патч ... что ? Я фигею. Это же только для разрабов, вон в жаве класс-патч для юзеров и те даже не парятся а тут :(((

 ,

mx__ ()

8192cu module verification failed

Установлен usb wifi с драйвером из AUR 8192cu-dkms. Вот такие сообщения получаю при загрузке в dmesg. Адаптер вроде бы пашет.

OC: Arch Linux \n Адаптер: RTL8192CU

8192cu: loading out-of-tree module taints kernel.
8192cu: module verification failed: signature and/or required key missing - tainting kernel
usbcore: registered new interface driver rtl8192cu
rtl8192cu 1-1:1.0 enp0s30f0u1: renamed from wlan0

 , ,

intervent ()

spi устройство из модуля kernel

Всем привет, пытаюсь из своего модуля заставить работать spi интерфейс для взаимодействия с устройством на шине с cs0. И при попытке обмена получаю дамп. Но дамп вываливается не всегда. Иногда обмен проходит.

Как я инициализирую устройство. Добавил описание в DTS (соответсвенно скомпилировал и указал при загрузке)

&spi1 {
        num-cs = <1>;
        cs-gpios = <&gpioa 25 0>;
        status = "okay";
        mptiospi: spi@0{
                compatible = "epm3128";
                spi-max-frequency = <100000>;
                reg=<0>;
        };

};

После загрузки устройство успешно отображается на sys_fs

# ls /sys/class/spi_master/spi1/
device      power       statistics  uevent
of_node     spi1.0      subsystem
В модуле ядра следующий код.
...
static struct spi_device * epm3128_spi_dev;
extern struct bus_type  spi_bus_type;
...
void
my_spi_init(void)
{
        struct spi_master *spi_1;
        struct spi_message	m;
        struct spi_transfer xfer  = {       
                        .tx_buf = &spi_tx_buf,
                        .rx_buf = &spi_rx_buf,
                        .len = 2, 
                        .bits_per_word = 16,
        };

        spi_1 = spi_busnum_to_master(1);
        epm3128_spi_dev = bus_find_device_by_name(&spi_bus_type,spi_1,"spi1.0");

        if(epm3128_spi_dev) {
                spi_tx_buf = 0xaaaa;
                spi_rx_buf = 0;
                spi_setup(epm3128_spi_dev);
                spi_message_init_with_transfers(&m,&xfer,1);
                spi_async(epm3128_spi_dev,&m);
        }
}

Есть идеи, что я мог упустить?

( дамп )

 , ,

Niore ()

centos 7 nginx lua module

есть centos 7, установлен nginx из репо epel

rpm -qa | grep nginx
nginx-mod-mail-1.12.2-2.el7.x86_64
nginx-1.12.2-2.el7.x86_64
nginx-filesystem-1.12.2-2.el7.noarch
nginx-mod-http-geoip-1.12.2-2.el7.x86_64
nginx-mod-http-xslt-filter-1.12.2-2.el7.x86_64
nginx-all-modules-1.12.2-2.el7.noarch
nginx-mod-stream-1.12.2-2.el7.x86_64
nginx-mod-http-perl-1.12.2-2.el7.x86_64
nginx-mod-http-image-filter-1.12.2-2.el7.x86_64

мне надо подключить два модуля ndk_http_module.so и ngx_http_lua_module.so

как их можно установить через репозиторий или только собирать с этими модулями?

на debian/ubuntu есть пакет nginx-extras и там нормально можно подключаться модули, а как правильно это делается на CentOS?

 , , ,

Garcia ()

Ищу железяку

Привет. Прошу навести меня на правильный путь ибо никак не могу найти верный путь для достижения поставленной цели. Итак, задача такова: хочу поставить в ноутбук pcie/m2 плату которая при загрузке линукса появилась бы как сервис/демон и выполняла некую работу. Например, мониторила бы файл в фс и выключала ноут при его модификации/удалении. Что ищу: поскольку кодить такое на асемблере ужасное мучение, то программа которая будет записана на плате должна быть написана нормальным языком вроде си.

Помогите пож-та определиться есть ли такое в природе?

 , ,

fenicks ()

Fedora Modular Server

Почитал я про сабж и не фига не понял :( https://fedoramagazine.org/modularity-fedora-28-server-edition/

Я достаточно много использую SC ( software collection ) и понимаю что это такое.

Даже скачал для пробы :

nodejs-6.13.1-1.module_1575+55808bea.x86_64.rpm
nodejs-9.8.0-1.module_1571+4f4bc63d.x86_64.rpm
python2-django1.11-1.11.11-1.fc28.noarch.rpm
python2-django-1.6.11.7-1.module_1560+089ce146.noarch.rpm

Взаимо исключающие rpm.

Может кто в курсе ?

 ,

mx__ ()

Модули к ядру, устанавливаемые как .ebuild-ы

Есть, к примеру, zfs собираемая как модуль ядра. Но распространяться она с ядром вместе не может.

Я посмотрел на gpo.zugaina.org и не нашел её там, нашел только в виде fuse.

Ещё такая же история была раньше с aufs (сейчас как там я не знаю).

Почему же, почему не сделают ебилдов для модулей ядра?

 , ,

Einstok_Fair ()

Есть ли бюджетное устройство для написания драйвера?

Есть ли устройство, на котором я бы мог попрактиковаться в написании модуля ядра? Только оно не должно быть сложным. И надо ли будет заглядывать в datasheet? Как вообще программируют для устройства, нужно знать очень много об устройстве, и где эту инфу получить и как ей пользоваться?

Есть ли вообще такое?

 , ,

u0atgKIRznY5 ()