1

I trying to write i2c device driver and all is gone fine:

  1. device detected successfully
  2. device in sysfs class with value attribute created too
  3. then I init a hrtimer and start it
  4. I am trying to send data from store function of attribute and it's work fine

but when I trying to send data from hrtimer callback function my system going down. Here is some code (i was remove incudes, defines and non-important code):

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;
}

What is wrong?

Alvin Wong
  • 12,210
  • 5
  • 51
  • 77
DBuTbKa
  • 106
  • 5
  • I think I am understand what is wrong. I cannot use any function which use active and maybe passive delays (like msleep or in this case i2c_smbus_write_byte_data). I need to use tasklets or workqueue. Correct? – DBuTbKa Jun 18 '13 at 20:21
  • One way to find out is to set the hrtimer but do nothing in the handler but printk(). Once that works you could add the I2C reads/writes. I'm doubting this delay would crash the kernel here, though. – Peter L. Jun 19 '13 at 00:24
  • Without i2c send it's work fine. If I am add msleep or i2c send it's cause system fault. – DBuTbKa Jun 19 '13 at 05:16
  • Can you try the I2C send routine in a read or write dispatch call? – Peter L. Jun 19 '13 at 05:43
  • How I can do this? ;-) – DBuTbKa Jun 19 '13 at 07:32
  • You can add read and write dispatch functions to your driver, then make a device node and then open the device from a test app in user space and read/write to it. Alternatively, you can create a proc entry and invoke a proc handler by echo-ing something to it from a shell prompt. That might be easiest/fastest. – Peter L. Jun 19 '13 at 15:10
  • 1
    I had a sysfs device and attribute for it. So I was put i2c_smbus_write_byte_data in store function (value_store) - it's work correctly I was wrote about it in my question. So I can do **echo 128 > /sysfs/class/../value** and driver send it fine. I think problem is what i2c_smbus_write_byte_data use some delays and it's cause system fault. I will try to use workqueue from timer callback – DBuTbKa Jun 19 '13 at 16:50
  • 1
    So tasklets too cause system fault. But workqueue is work fine. – DBuTbKa Jun 19 '13 at 20:14
  • 2
    Interesting, perhaps your theory about faulting after doing a sleep in the I2C code may be correct. BTW, this might be relevant: http://stackoverflow.com/questions/2147299/when-to-use-kernel-threads-vs-workqueues-in-the-linux-kernel – Peter L. Jun 19 '13 at 21:01
  • Please do not add "solved" to questions. Instead, post an answer and accept it. – Alvin Wong Jun 25 '13 at 12:52

0 Answers0