драйвер устройства i2c. Система не работает при попытке отправить данные

Я пытаюсь написать драйвер устройства i2c, и все прошло нормально:

  1. устройство успешно обнаружено
  2. устройство в классе sysfs с атрибутом value также создано
  3. затем я инициализирую hrtimer и запускаю его
  4. Я пытаюсь отправить данные из функции хранения атрибута, и все работает нормально

но когда я пытаюсь отправить данные из функции обратного вызова hrtimer, моя система выходит из строя. Вот некоторый код (я удалил вставки, определения и неважный код):

led-indicator.h

struct timer_job {
        ktime_t period;
        struct hrtimer timer;
        ...
};

struct ledindicator {
        struct i2c_client *client;
        struct device *device;
        struct timer_job job;
        int value;
};

led-indicator.c

include "led-indicator.h"
static struct ledindicator *li;

// device attribute [value] store function
static ssize_t value_store(struct device *device, struct device_attribute *attr, const char *buffer, size_t count)
{
    int val;
    kstrtoint(buffer, 10, &val);
    li->value = val;
    i2c_smbus_write_byte_data(li->client,  0xBA, 0x02); // this is work fine
    LOG("New value is %d \n", li->value);
    return count;
}

//timer callback, fire each timer_job.period
static enum hrtimer_restart send_next(struct hrtimer * tim) {
    long start = jiffies;
    struct timer_job *job = container_of(tim, struct timer_job, timer);
    i2c_smbus_write_byte_data(li->client, 0xBA, 0x02); // this cause system fault
    hrtimer_forward_now(tim, job->period);
    return HRTIMER_RESTART;
}

//when device is detected I am create sysfs device and init timer. 
enter code here//Also I am crate led_indicator structure and save i2c_client pointer for future use
static int li_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int ret = 0;
    li = kmalloc(sizeof(*li), GFP_KERNEL);
    li->client = client;
    li->value = 0;

    ...
    // here creating device and attribute for it
    ...

    hrtimer_init(&(li->job.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);

    li->job.timer.function = send_next;
    li->job.period = ktime_set(1, 0); //1 sec
    hrtimer_start(&(li->job.timer), li->job.period, HRTIMER_MODE_REL);

    return ret;
}

Что случилось?


person DBuTbKa    schedule 18.06.2013    source источник
comment
Я думаю, я понимаю, что не так. Я не могу использовать никакие функции, использующие активные и, возможно, пассивные задержки (например, msleep или в данном случае i2c_smbus_write_byte_data). Мне нужно использовать тасклеты или рабочую очередь. Правильный?   -  person DBuTbKa    schedule 19.06.2013
comment
Один из способов узнать это — установить hrtimer, но ничего не делать в обработчике, кроме функции printk(). Как только это сработает, вы можете добавить чтение/запись I2C. Однако я сомневаюсь, что эта задержка приведет к сбою ядра.   -  person Peter L.    schedule 19.06.2013
comment
Без i2c send работает нормально. Если я добавляю msleep или i2c send, это вызывает системную ошибку.   -  person DBuTbKa    schedule 19.06.2013
comment
Можете ли вы попробовать процедуру отправки I2C в диспетчерском вызове чтения или записи?   -  person Peter L.    schedule 19.06.2013
comment
Как я могу это сделать? ;-)   -  person DBuTbKa    schedule 19.06.2013
comment
Вы можете добавить функции диспетчеризации чтения и записи в свой драйвер, затем создать узел устройства, а затем открыть устройство из тестового приложения в пользовательском пространстве и выполнить чтение/запись в него. В качестве альтернативы вы можете создать запись proc и вызвать обработчик proc, отправив ему что-то эхо из приглашения оболочки. Это может быть проще/быстрее.   -  person Peter L.    schedule 19.06.2013
comment
У меня было устройство sysfs и атрибут для него. Итак, я поставил i2c_smbus_write_byte_data в функцию хранилища (value_store) - работает корректно, об этом писали в моем вопросе. Так что я могу сделать echo 128 › /sysfs/class/../value, и драйвер отправит его нормально. Я думаю, что проблема в том, что i2c_smbus_write_byte_data использует некоторые задержки, и это вызывает системную ошибку. Я попытаюсь использовать рабочую очередь из обратного вызова таймера   -  person DBuTbKa    schedule 19.06.2013
comment
Так что тасклеты тоже вызывают системную ошибку. Но рабочая очередь работает нормально.   -  person DBuTbKa    schedule 20.06.2013
comment
Интересно, возможно, ваша теория об ошибках после сна в коде I2C может быть правильной. Кстати, это может иметь значение: stackoverflow.com/questions/2147299/   -  person Peter L.    schedule 20.06.2013
comment
Спасибо за помощь.   -  person DBuTbKa    schedule 20.06.2013
comment
Пожалуйста, не добавляйте решенные к вопросам. Вместо этого опубликуйте ответ и примите его.   -  person Alvin Wong    schedule 25.06.2013