Question about using spinlock to synchronize between kernel driver and an interrupt handler
Hi, I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver. Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; } void f2() { spin_lock(&mylock); //... } The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock); My question is if I call f1() f2() // i want this to block until the interrupt return saying setting REG_ADDR is done. when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected" How can I re-write my code so that kernel does not think I have a deadlock? I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Thank you.
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Sorry, I mean I want to set a bit in a HW Register 1. HW will send an interrupt when setting the register is done. I want my driver code to block until the interrupt is sent from the HW. On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW.
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote: don't top-post
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt Yes this is how most drivers work.
when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. so i suppose this is what you want to do.
write ->register->interrupt happens->disable register ->handle interrupt --->enable register. Look at any driver code from linux kernel code and it mostly does this.
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Sat, Feb 1, 2014 at 12:48 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote: don't top-post
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt Yes this is how most drivers work.
when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. so i suppose this is what you want to do.
write ->register->interrupt happens->disable register ->handle interrupt --->enable register. Look at any driver code from linux kernel code and it mostly does this.
Thanks. But I want my driver code to block until I get the interrupt from HW.
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Sat, Feb 1, 2014 at 1:03 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:48 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote: don't top-post
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt Yes this is how most drivers work.
when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. so i suppose this is what you want to do.
write ->register->interrupt happens->disable register ->handle interrupt --->enable register. Look at any driver code from linux kernel code and it mostly does this.
Thanks. But I want my driver code to block until I get the interrupt from HW.
if (driver code == interrupt handler) { it_is_not_running_anyway_as_there_is_no_interrupt } else { i don't know what you mean by driver code here? }
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else On Sat, Feb 1, 2014 at 1:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 1:03 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:48 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote: don't top-post
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt Yes this is how most drivers work.
when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. so i suppose this is what you want to do.
write ->register->interrupt happens->disable register ->handle interrupt --->enable register. Look at any driver code from linux kernel code and it mostly does this.
Thanks. But I want my driver code to block until I get the interrupt from HW.
if (driver code == interrupt handler) { it_is_not_running_anyway_as_there_is_no_interrupt } else { i don't know what you mean by driver code here? }
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); } interrupt_handler(){ x_variable=1 wake_up(); } request_irq(interrupt_handler);
On Sat, Feb 1, 2014 at 1:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 1:03 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:48 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote: don't top-post
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt Yes this is how most drivers work.
when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. so i suppose this is what you want to do.
write ->register->interrupt happens->disable register ->handle interrupt --->enable register. Look at any driver code from linux kernel code and it mostly does this.
Thanks. But I want my driver code to block until I get the interrupt from HW.
if (driver code == interrupt handler) { it_is_not_running_anyway_as_there_is_no_interrupt } else { i don't know what you mean by driver code here? }
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to learn about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Sat, Feb 01, 2014 at 01:32:49AM -0800, anish singh wrote:
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); }
interrupt_handler(){ x_variable=1 wake_up(); }
request_irq(interrupt_handler);
Please investigate the usage of completions in your driver. See include/linux/completion.h. It sounds like it fits your usecase nicely. Josh
On Sat, Feb 1, 2014 at 5:34 AM, Josh Cartwright <joshc@eso.teric.us> wrote:
On Sat, Feb 01, 2014 at 01:32:49AM -0800, anish singh wrote:
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); }
interrupt_handler(){ x_variable=1 wake_up(); }
request_irq(interrupt_handler);
Please investigate the usage of completions in your driver. See include/linux/completion.h. It sounds like it fits your usecase nicely.
Josh
I have loooked at linux completion for my usecase So I think I can do DECLARE_COMPLETION(my_completion); some_func() { set_register_value wait_for_completion(my_completion); } interrupt_handler(){ complete(my_completion); } request_irq(interrupt_handler); My question now is what if 1 kernel thread execute some_funct(), but before interrupt_handler() get invoked (from HW), another kernel thread executes some_func(). In essence, set_register_value is execute twice before interrupt_handler() return once. how can I prevent another kernel thread from executing "set_register_value()" when 1 is wait_for_completion?
On Sat, Feb 1, 2014 at 11:49 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 5:34 AM, Josh Cartwright <joshc@eso.teric.us> wrote:
On Sat, Feb 01, 2014 at 01:32:49AM -0800, anish singh wrote:
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); }
interrupt_handler(){ x_variable=1 wake_up(); }
request_irq(interrupt_handler);
Please investigate the usage of completions in your driver. See include/linux/completion.h. It sounds like it fits your usecase nicely.
Josh
I have loooked at linux completion for my usecase So I think I can do
DECLARE_COMPLETION(my_completion);
some_func() { set_register_value wait_for_completion(my_completion); }
interrupt_handler(){ complete(my_completion); }
request_irq(interrupt_handler);
My question now is what if 1 kernel thread execute some_funct(), but before interrupt_handler() get invoked (from HW), another kernel thread executes some_func(). In essence, set_register_value is execute twice before interrupt_handler() return once.
how can I prevent another kernel thread from executing "set_register_value()" when 1 is wait_for_completion? Please implement your driver or whatever you are doing and if you run into a wall then ask here as what you are asking is incoherent.
Hi Silverstri, On Sun, Feb 2, 2014 at 1:19 PM, m silverstri <michael.j.silverstri@gmail.com
wrote:
On Sat, Feb 1, 2014 at 5:34 AM, Josh Cartwright <joshc@eso.teric.us> wrote:
On Sat, Feb 01, 2014 at 01:32:49AM -0800, anish singh wrote:
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); }
interrupt_handler(){ x_variable=1 wake_up(); }
request_irq(interrupt_handler);
Please investigate the usage of completions in your driver. See include/linux/completion.h. It sounds like it fits your usecase nicely.
Josh
I have loooked at linux completion for my usecase So I think I can do
DECLARE_COMPLETION(my_completion);
some_func() { set_register_value wait_for_completion(my_completion); }
interrupt_handler(){ complete(my_completion); }
request_irq(interrupt_handler);
My question now is what if 1 kernel thread execute some_funct(), but before interrupt_handler() get invoked (from HW), another kernel thread executes some_func(). In essence, set_register_value is execute twice before interrupt_handler() return once.
Use a mutex_lock(). So your code will be as follows: DECLARE_COMPLETION(my_completion); struct mutex dev_lock; some_func() { mutex_lock(&dev_lock); set_register_value wait_for_completion(my_completion); mutex_unloc(&dev_lock); } interrupt_handler(){ complete(my_completion); } mutex_init(&dev_lock); request_irq(interrupt_handler); Thanks, Arun
how can I prevent another kernel thread from executing "set_register_value()" when 1 is wait_for_completion?
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Thanks Arun, But why not just use mutex and remove the completion? i.e. do this: struct mutex dev_lock; some_func() { mutex_lock(&dev_lock); set_register_value } interrupt_handler(){ mutex_unloc(&dev_lock); } mutex_init(&dev_lock); request_irq(interrupt_handler); On Mon, Feb 3, 2014 at 1:54 AM, Arun KS <getarunks@gmail.com> wrote:
Hi Silverstri,
On Sun, Feb 2, 2014 at 1:19 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 5:34 AM, Josh Cartwright <joshc@eso.teric.us> wrote:
On Sat, Feb 01, 2014 at 01:32:49AM -0800, anish singh wrote:
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); }
interrupt_handler(){ x_variable=1 wake_up(); }
request_irq(interrupt_handler);
Please investigate the usage of completions in your driver. See include/linux/completion.h. It sounds like it fits your usecase nicely.
Josh
I have loooked at linux completion for my usecase So I think I can do
DECLARE_COMPLETION(my_completion);
some_func() { set_register_value wait_for_completion(my_completion); }
interrupt_handler(){ complete(my_completion); }
request_irq(interrupt_handler);
My question now is what if 1 kernel thread execute some_funct(), but before interrupt_handler() get invoked (from HW), another kernel thread executes some_func(). In essence, set_register_value is execute twice before interrupt_handler() return once.
Use a mutex_lock(). So your code will be as follows:
DECLARE_COMPLETION(my_completion); struct mutex dev_lock;
some_func() { mutex_lock(&dev_lock); set_register_value wait_for_completion(my_completion); mutex_unloc(&dev_lock); }
interrupt_handler(){ complete(my_completion); }
mutex_init(&dev_lock); request_irq(interrupt_handler);
Thanks, Arun
how can I prevent another kernel thread from executing "set_register_value()" when 1 is wait_for_completion?
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Feb 4, 2014 12:00 AM, "m silverstri" <michael.j.silverstri@gmail.com> wrote:
Thanks Arun,
But why not just use mutex and remove the completion? i.e. do this:
struct mutex dev_lock;
some_func() { mutex_lock(&dev_lock); set_register_value
}
You'll block all tasks until your handler unlock the mutex. The idea is to let the tasks block on driver code and let them submit request to your driver. This mutex should be private to your driver code and not visible to upper layer tasks.
interrupt_handler(){ mutex_unloc(&dev_lock); }
What if the interrupt never happens? Or is lost?. Whatever your task want to do with device it should be like a private binding. Like for example the input buffer would be per task and the output as well. Your device may handle multiple functions so setting register values should also be per task. So it can be like each task sets the desired value in the request structure and when driver gets to this request it would call the appropriate function to set the values for register. I would recommend keeping register setting functions private to your driver code and only expose some integers corresponding to functions provided by your device. Keeping it clean will help you manage your code.
mutex_init(&dev_lock); request_irq(interrupt_handler);
On Mon, Feb 3, 2014 at 1:54 AM, Arun KS <getarunks@gmail.com> wrote:
Hi Silverstri,
On Sun, Feb 2, 2014 at 1:19 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 5:34 AM, Josh Cartwright <joshc@eso.teric.us> wrote:
On Sat, Feb 01, 2014 at 01:32:49AM -0800, anish singh wrote:
On Sat, Feb 1, 2014 at 1:15 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else ok so you are looking for below code:
some_func() { set_register_value x_variable=0 wait_for_event*(x_variable); }
interrupt_handler(){ x_variable=1 wake_up(); }
request_irq(interrupt_handler);
Please investigate the usage of completions in your driver. See include/linux/completion.h. It sounds like it fits your usecase
nicely.
Josh
I have loooked at linux completion for my usecase So I think I can do
DECLARE_COMPLETION(my_completion);
some_func() { set_register_value wait_for_completion(my_completion); }
interrupt_handler(){ complete(my_completion); }
request_irq(interrupt_handler);
My question now is what if 1 kernel thread execute some_funct(), but before interrupt_handler() get invoked (from HW), another kernel thread executes some_func(). In essence, set_register_value is execute twice before interrupt_handler() return once.
Use a mutex_lock(). So your code will be as follows:
DECLARE_COMPLETION(my_completion); struct mutex dev_lock;
some_func() { mutex_lock(&dev_lock); set_register_value wait_for_completion(my_completion); mutex_unloc(&dev_lock); }
interrupt_handler(){ complete(my_completion); }
mutex_init(&dev_lock); request_irq(interrupt_handler);
Thanks, Arun
how can I prevent another kernel thread from executing "set_register_value()" when 1 is wait_for_completion?
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
---P.K.S
On Feb 1, 2014 2:48 PM, "m silverstri" <michael.j.silverstri@gmail.com> wrote:
By driver code , I mean the code which set the register values and wait till the values is set (via an interrupt handler) before continues doing something else
On Sat, Feb 1, 2014 at 1:06 AM, anish singh <anish198519851985@gmail.com>
wrote:
On Sat, Feb 1, 2014 at 1:03 AM, m silverstri <michael.j.silverstri@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:48 AM, anish singh <anish198519851985@gmail.com> wrote:
On Sat, Feb 1, 2014 at 12:32 AM, m silverstri <michael.j.silverstri@gmail.com> wrote: don't top-post
In my driver code, I want to set a bit in a HW Register 1. HW will send an interrupt Yes this is how most drivers work.
when setting the register is done. I don't want my driver code to block until the interrupt is sent from the HW. so i suppose this is what you want to do.
write ->register->interrupt happens->disable register ->handle interrupt --->enable register. Look at any driver code from linux kernel code and it mostly does this.
Thanks. But I want my driver code to block until I get the interrupt from HW.
if (driver code == interrupt handler) { it_is_not_running_anyway_as_there_is_no_interrupt } else { i don't know what you mean by driver code here? }
On Sat, Feb 1, 2014 at 12:06 AM, anish singh <anish198519851985@gmail.com> wrote:
On Fri, Jan 31, 2014 at 11:55 PM, m silverstri <michael.j.silverstri@gmail.com> wrote:
Hi,
I read this article http://www.linuxjournal.com/article/5833 to
learn
about spinlock. I try this to use it in my kernel driver.
Here is what my driver code needs to do: In f1(), it will get the spin lock, and caller can call f2() will wait for the lock since the spin lock is not being unlock. The spin lock will be unlock in my interrupt handler (triggered by the HW). Wrong design!!!
void f1() { spin_lock(&mylock); // write hardware REG_ADDR += FLAG_A; So here you take spinlock and release in interrupt handler.What if there is no interrupt handler and someone calls this fucntion he will blocked forever.
}
void f2() { spin_lock(&mylock); //... }
The hardware will send the application an interrupt and my interrupt handler will call spin_unlock(&mylock);
My question is if I call f1() f2() // i want this to block until the interrupt return saying settingyou
I think you want to block a task for an event to happen. That event is triggered by HW. What i would suggest is that you use completion variable which would be per request. Don't make it global otherwise you'll again need locks to protect global variable. Try to pass this completion variable along with request to your driver. Also i suppose that your driver could implement a list where requests from tasks can be queued and each task would wait for completion which already is per task embedded in its request. The driver would deque requests one by one or depending on how many requests can your hw handle and will trigger completion waking up the task that triggered it. So you'll have a clean api design where locks are held and unlocked at same layer instead of current design.
REG_ADDR is done.
when I run this, I get an exception in kernel saying a deadlock " INFO: possible recursive locking detected"
How can I re-write my code so that kernel does not think I have a deadlock?
I want my driver code to wait until HW sends me an interrupt saying setting REG_ADDR is done. Let us know what is your requirement?I am sure there must be a simple way to handle than this magic done here. Explain what are you trying to do in detail and I am sure lot of people will jump to help.
Thank you.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
---P.K.S
participants (5)
-
anish singh -
Arun KS -
Josh Cartwright -
m silverstri -
Pranay Srivastava