Skip to contentSkip to conversation

Is it safe to use these Linux function (test_bit(), set_bit(), clear_bit()) in character device driver for 2.6.10 ppc kernel.

DISCUSSION Misbah khan 5 participants 12 messages Sep 27, 2007 – Oct 4, 2007

lore
Share & tools
lore
#0 lore raw

Hi all

I am using "test_bit(),set_bit(),clear_bit() etc" API functions provided by the Linux kernel. I want to know that if anybody is used it and have full faith in its operation then please let me know. Driver in the while loop is calling these API's hence i want to make sure that its operation will remain stable.

I need your comments in this regard

Thank you
Misbah

Signature · 2 lines
View this message in context: http://www.nabble.com/Is-it-safe-to-use-these-Linux-function-%28test_bit%28%29%2Cset_bit%28%29%2Cclear_bit%28%29%29-in-character-device-driver-for-2.6.10-ppc-kernel.-tf4527008.html#a12916782
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
#1 lore raw
Quoted 1 line · Misbah khan

Hi all I am using "test_bit(),set_bit(),clear_bit() etc" API functions provided by the Linux kernel. I want to know that if anybody is used it and have full faith in its operation then please let me know. Driver in the while loop is calling these API's hence i want to make sure that its operation will remain stable.

They're used all over the place. Is there anything about them that you find suspect?

-Scott

#2 lore raw
Quoted 47 lines · Scott Wood-2 wrote:
Quoted 5 lines · Misbah khan

Hi all I am using "test_bit(),set_bit(),clear_bit() etc" API functions provided by the Linux kernel. I want to know that if anybody is used it and have full faith in its operation then please let me know. Driver in the while loop is calling these API's hence i want to make sure that its operation will remain stable.

They're used all over the place. Is there anything about them that you find suspect?

-Scott

I have devloped a character driver for FPGA which is memory mapped and using these API's to test a bit , set a bit or to clear a bit in the memory for eg :-

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(UINT32 *)(\
			(void *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return -1;
		}

People working for FPGA are sure that they are not making the bit high where in my driver is returning -1 from the kernel space aborting it after running for few minutes or so . Please let me know that This function is stable and i should tell them that the driver is stable in its operation and they should check it from there side.

Misbah

_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Signature · 2 lines
View this message in context: http://www.nabble.com/Is-it-safe-to-use-these-Linux-function-%28test_bit%28%29%2Cset_bit%28%29%2Cclear_bit%28%29%29-in-character-device-driver-for-2.6.10-ppc-kernel.-tf4527008.html#a12934517
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
#3 lore raw
Quoted 29 lines · Misbah khan
Quoted 26 lines · Scott Wood-2 wrote:
Quoted 1 line · Misbah khan

Hi all I am using "test_bit(),set_bit(),clear_bit() etc" API functions provided by the Linux kernel. I want to know that if anybody is used it and have full faith in its operation then please let me know. Driver in the while loop is calling these API's hence i want to make sure that its operation will remain stable.

They're used all over the place. Is there anything about them that you find suspect?

-Scott

I have devloped a character driver for FPGA which is memory mapped and using these API's to test a bit , set a bit or to clear a bit in the memory for eg :-

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(UINT32 *)(\
			(void *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return -1;
		}
Quoted 6 lines
Quoted 6 lines

People working for FPGA are sure that they are not making the bit high where in my driver is returning -1 from the kernel space aborting it after running for few minutes or so . Please let me know that This function is stable and i should tell them that the driver is stable in its operation and they should check it from there side.

I think a more more likely source of the problem is that the FPGA
pointer is not cast volatile, or perhaps the FPGA is mapped cached and the hardware doesn't always get touched when you think it does. The bit manipulation macros are probably fine.

jeff

#4 lore raw
Quoted 89 lines · Jeff Mock-2 wrote:
Quoted 35 lines · Misbah khan
Quoted 32 lines · Scott Wood-2 wrote:
Quoted 6 lines · Misbah khan

Hi all I am using "test_bit(),set_bit(),clear_bit() etc" API functions provided by the Linux kernel. I want to know that if anybody is used it and have full faith in its operation then please let me know. Driver in the while loop is calling these API's hence i want to make sure that its
operation will remain stable.

They're used all over the place. Is there anything about them that you find suspect?

-Scott

I have devloped a character driver for FPGA which is memory mapped and using these API's to test a bit , set a bit or to clear a bit in the memory for eg :-

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(UINT32 *)(\
			(void *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return -1;
		}
Quoted 7 lines
Quoted 7 lines

People working for FPGA are sure that they are not making the bit high where in my driver is returning -1 from the kernel space aborting it after
running for few minutes or so . Please let me know that This function is stable and i should tell them that the driver is stable in its operation and they should check it from there side.

I think a more more likely source of the problem is that the FPGA pointer is not cast volatile, or perhaps the FPGA is mapped cached and the hardware doesn't always get touched when you think it does. The bit manipulation macros are probably fine.

jeff

FPGA is Indeed mapped non cashed here is the part of the code

/* Physical bus memory is mapped */

	mmap_reg_ptr=(UINT32 *)ioremap_nocache(PHY_MEM_ADDR,PHY_MEM_SIZE);

And is it ok if I caste FPGA pointer volatile like this will reduce the probability of failure

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(volatile UINT32 *)(\
			(volatile UINT32 *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return CASHEL_FAILURE;
		}

__________________

is there anything else that we could do to rely fully in our code.

Misbah
_____________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Signature · 2 lines
View this message in context: http://www.nabble.com/Is-it-safe-to-use-these-Linux-function-%28test_bit%28%29%2Cset_bit%28%29%2Cclear_bit%28%29%29-in-character-device-driver-for-2.6.10-ppc-kernel.-tf4527008.html#a12937117
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
#5 lore raw
Quoted 112 lines · Misbah khan
Quoted 106 lines · Jeff Mock-2 wrote:
Quoted 37 lines · Misbah khan
Quoted 34 lines · Scott Wood-2 wrote:
Quoted 8 lines · Misbah khan

Hi all I am using "test_bit(),set_bit(),clear_bit() etc" API functions provided by the Linux kernel. I want to know that if anybody is used it
and have full faith in its operation then please let me know. Driver in
the while loop is calling these API's hence i want to make sure that its
operation will remain stable.

They're used all over the place. Is there anything about them that you find suspect?

-Scott

I have devloped a character driver for FPGA which is memory mapped and using these API's to test a bit , set a bit or to clear a bit in the memory for eg :-

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(UINT32 *)(\
			(void *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return -1;
		}
Quoted 9 lines
Quoted 9 lines

People working for FPGA are sure that they are not making the bit high where in my driver is returning -1 from the kernel space aborting it after
running for few minutes or so . Please let me know that This function is
stable and i should tell them that the driver is stable in its operation
and they should check it from there side.

I think a more more likely source of the problem is that the FPGA pointer is not cast volatile, or perhaps the FPGA is mapped cached and the hardware doesn't always get touched when you think it does. The bit manipulation macros are probably fine.

jeff

FPGA is Indeed mapped non cashed here is the part of the code

/* Physical bus memory is mapped */

	mmap_reg_ptr=(UINT32 *)ioremap_nocache(PHY_MEM_ADDR,PHY_MEM_SIZE);

And is it ok if I caste FPGA pointer volatile like this will reduce the probability of failure

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(volatile UINT32 *)(\
			(volatile UINT32 *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return CASHEL_FAILURE;
		}

__________________

is there anything else that we could do to rely fully in our code.

Misbah
MAX_DELAY_BUSY corresponds to 10 ms .Driver should poll the bit for few micro second at the max and come out .

I had earlier tried with ioread32() and iowrite32() wrapper functions but the output i got is bit swapped hence i went for direct dereferencing the pointer .

do you think in_be32() could be the best approach than direct
dereferencing. And about test_bit() function does it looks fine to you

Misbah

_____________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Signature · 2 lines
View this message in context: http://www.nabble.com/Is-it-safe-to-use-these-Linux-function-%28test_bit%28%29%2Cset_bit%28%29%2Cclear_bit%28%29%29-in-character-device-driver-for-2.6.10-ppc-kernel.-tf4527008.html#a12966462
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
#6 lore raw

First, PLEASE stop quoting your own text. Do not append > in front of the lines you write yourself in the reply. It makes it impossible to tell what parts are new and what are old.

Quoted 7 lines · Misbah khan
Quoted 7 lines
Quoted 7 lines

FPGA is Indeed mapped non cashed here is the part of the code

/* Physical bus memory is mapped */

	mmap_reg_ptr=(UINT32 *)ioremap_nocache(PHY_MEM_ADDR,PHY_MEM_SIZE);

And is it ok if I caste FPGA pointer volatile like this will reduce the probability of failure

You cannot ever use set_bit/clear_bit to uncacheable memory. Ever. It uses load-reserve/store-conditional, and they are not legal to use to uncacheable memory.

Also, regular ioremap() is by default uncacheable, so it's quite adequate to use in this case, no need to use the _nocache version.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

do you think in_be32() could be the best approach than direct
dereferencing. And about test_bit() function does it looks fine to you

You need to use in_be32() + manipulating the value + out_be32(), yes. Depending on the rest of your driver you might need to protect it with a spinlock, but that's beyond the scope of this question.

-Olof

#7 lore raw
Quoted 70 lines · Olof Johansson-2 wrote:

First, PLEASE stop quoting your own text. Do not append > in front of the lines you write yourself in the reply. It makes it impossible to tell what parts are new and what are old.

Quoted 8 lines · Misbah khan
Quoted 6 lines
Quoted 6 lines

FPGA is Indeed mapped non cashed here is the part of the code

/* Physical bus memory is mapped */

	mmap_reg_ptr=(UINT32 *)ioremap_nocache(PHY_MEM_ADDR,PHY_MEM_SIZE);

And is it ok if I caste FPGA pointer volatile like this will reduce

the

Quoted 1 line
Quoted 1 line

probability of failure

You cannot ever use set_bit/clear_bit to uncacheable memory. Ever. It uses load-reserve/store-conditional, and they are not legal to use to uncacheable memory.

Also, regular ioremap() is by default uncacheable, so it's quite adequate to use in this case, no need to use the _nocache version.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

do you think in_be32() could be the best approach than direct
dereferencing. And about test_bit() function does it looks fine to you

You need to use in_be32() + manipulating the value + out_be32(), yes. Depending on the rest of your driver you might need to protect it with a spinlock, but that's beyond the scope of this question.

-Olof

I am confused that some people tells me to map the memory noncacheble and some tells me not. could you tell me which is the best approach and please elaborate the reason as well. The part of the code is mentioned above is a reference and my concern are as follows:-

1. I am mapping 32 KB of memory for which i am using _nocasheble. Is it absolutely fine????

2. I am directly dereferencing the pointer to the mapped region insted of using a wrapper function due to (1) Aready used in the past and have faith in it .
(2) I had used functions like ioread32() iowrite32() in the past which
is suggested by rubini in his book on Linux device Driver but the output i got was bitswapped .

3. test_bit()/clear_bit() are the functions which i am using in my driver and in the way i described above , please let me know that is looks fine in the Implimention or shall i read the value and mask the bits rather than beliving in these functions for eg :-

dfr_data_ret=*(volatile UINT32 *)((volatile UINT32 *)mmap_reg_ptr+DATA_STATUS_REG);

dfr_data_ret&=STATUS_MASK;

Please reply to clear my doubts.

Misbah

_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Signature · 2 lines
View this message in context: http://www.nabble.com/Is-it-safe-to-use-these-Linux-function-%28test_bit%28%29%2Cset_bit%28%29%2Cclear_bit%28%29%29-in-character-device-driver-for-2.6.10-ppc-kernel.-tf4527008.html#a12973587
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
#8 lore raw
Quoted 5 lines · Misbah khan
Quoted 4 lines · Olof Johansson-2 wrote:

First, PLEASE stop quoting your own text. Do not append > in front of the lines you write yourself in the reply. It makes it impossible to tell what parts are new and what are old.

Please read the above again, since you didn't fix your mailer.

Also, make sure it doesn't prepend spaces in front of the lines you are writing.

Quoted 4 lines
Quoted 4 lines

I am confused that some people tells me to map the memory noncacheble and some tells me not. could you tell me which is the best approach and please elaborate the reason as well. The part of the code is mentioned above is a reference and my concern are as follows:-

It depends on your application and how the FPGA is attached. Buf if it is attached outside of the coherence domain (for example on PCI), then you should map it uncacheable. Otherwise you will have to do manual flushing of caches to make sure writes make it out to the device, and also flush any copy in cache before you read any register. In other words, it makes things considerably more complicated and error-prone.

Quoted 2 lines
Quoted 2 lines

1. I am mapping 32 KB of memory for which i am using _nocasheble. Is it absolutely fine????

Just use ioremap().

Quoted 3 lines
Quoted 3 lines

2. I am directly dereferencing the pointer to the mapped region insted of using a wrapper function due to (1) Aready used in the past and have faith in it .

I don't care if you have faith in it or not, it's still not the correct way to do it. It might work right some of the time by pure luck but it is the incorrect way of accessing device memory.

Quoted 3 lines
Quoted 3 lines

(2) I had used functions like ioread32() iowrite32() in the past which
is suggested by rubini in his book on Linux device Driver but the output i got was bitswapped .

I assume you mean byte swapped and not bit swapped.

Are your registers on the device big- or little endian?

If they are big endian, use in_be32/out_be32. If they're little endian, use in_le32/out_le32. That will take care of any swapping for you.

Quoted 3 lines
Quoted 3 lines

3. test_bit()/clear_bit() are the functions which i am using in my driver and in the way i described above , please let me know that is looks fine in the Implimention

No it is not fine. You cannot use set_bit/clear_bit against noncacheable memory. EVER.

Quoted 9 lines
Quoted 9 lines

or shall i read the value and mask the bits rather
than beliving in these functions for eg :-

dfr_data_ret=*(volatile UINT32 *)((volatile UINT32 *)mmap_reg_ptr+DATA_STATUS_REG);

dfr_data_ret&=STATUS_MASK;

Please reply to clear my doubts.

Just do what I told you earlier:

To read the status register, mask out the STATUS_MASK and write it back, do:

val = in_be32(mmap_reg_ptr + DATA_STATUS_REG);
val &= STATUS_MASK;
out_be32(MMAP_REG_PTR + DATA_STATUS_REG, val);

-Olof

#9 lore raw

Hi ...
I did followed you and it worked as well. I really Thank you for it.

At one Place i am doing memcpy() of floating point data to the memory mapped registers, what could be the substitute of it like "memcpy_toio() " which is suggested in the Book. I am working BE architecture.

I would really appreaciate if you would let me know the defineation of these wrapper functions (in_be32,out_be32(),ioread32(),iowrite32(),etc) so that i could have the clear idea of the reason for not directly dreferencing the Pointer.

Misbah

Quoted 94 lines · Olof Johansson-2 wrote:
Quoted 5 lines · Misbah khan
Quoted 4 lines · Olof Johansson-2 wrote:

First, PLEASE stop quoting your own text. Do not append > in front of the lines you write yourself in the reply. It makes it impossible to tell what parts are new and what are old.

Please read the above again, since you didn't fix your mailer.

Also, make sure it doesn't prepend spaces in front of the lines you are writing.

Quoted 7 lines
Quoted 1 line

I am confused that some people tells me to map the memory noncacheble

and

Quoted 1 line

some tells me not. could you tell me which is the best approach and

please

Quoted 1 line

elaborate the reason as well. The part of the code is mentioned above

is a

Quoted 1 line

reference and my concern are as follows:-

It depends on your application and how the FPGA is attached. Buf if it is attached outside of the coherence domain (for example on PCI), then you should map it uncacheable. Otherwise you will have to do manual flushing of caches to make sure writes make it out to the device, and also flush any copy in cache before you read any register. In other words, it makes things considerably more complicated and error-prone.

Quoted 2 lines
Quoted 2 lines

1. I am mapping 32 KB of memory for which i am using _nocasheble. Is it absolutely fine????

Just use ioremap().

Quoted 5 lines
Quoted 1 line

2. I am directly dereferencing the pointer to the mapped region insted

of

Quoted 1 line

using a wrapper function due to (1) Aready used in the past and have

faith

Quoted 1 line

in it .

I don't care if you have faith in it or not, it's still not the correct way to do it. It might work right some of the time by pure luck but it is the incorrect way of accessing device memory.

Quoted 5 lines
Quoted 1 line

(2) I had used functions like ioread32() iowrite32() in the past

which

Quoted 1 line

is suggested by rubini in his book on Linux device Driver but the

output i

Quoted 1 line

got was bitswapped .

I assume you mean byte swapped and not bit swapped.

Are your registers on the device big- or little endian?

If they are big endian, use in_be32/out_be32. If they're little endian, use
in_le32/out_le32. That will take care of any swapping for you.

Quoted 5 lines
Quoted 1 line

3. test_bit()/clear_bit() are the functions which i am using in my

driver

Quoted 1 line

and in the way i described above , please let me know that is looks

fine

Quoted 1 line

in the Implimention

No it is not fine. You cannot use set_bit/clear_bit against noncacheable memory. EVER.

Quoted 9 lines
Quoted 9 lines

or shall i read the value and mask the bits rather
than beliving in these functions for eg :-

dfr_data_ret=*(volatile UINT32 *)((volatile UINT32 *)mmap_reg_ptr+DATA_STATUS_REG);

dfr_data_ret&=STATUS_MASK;

Please reply to clear my doubts.

Just do what I told you earlier:

To read the status register, mask out the STATUS_MASK and write it back, do:

val = in_be32(mmap_reg_ptr + DATA_STATUS_REG);
val &= STATUS_MASK;
out_be32(MMAP_REG_PTR + DATA_STATUS_REG, val);

-Olof
_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Signature · 2 lines
View this message in context: http://www.nabble.com/Is-it-safe-to-use-these-Linux-function-%28test_bit%28%29%2Cset_bit%28%29%2Cclear_bit%28%29%29-in-character-device-driver-for-2.6.10-ppc-kernel.-tf4527008.html#a13039401
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
#10 lore raw
Quoted 4 lines · Misbah khan

Hi ...
I did followed you and it worked as well. I really Thank you for it.

Quoted 8 lines

At one Place i am doing memcpy() of floating point data to the memory mapped registers, what could be the substitute of it like "memcpy_toio() " which is suggested in the Book. I am working BE architecture.

I would really appreaciate if you would let me know the defineation of these wrapper functions (in_be32,out_be32(),ioread32(),iowrite32(),etc) so that i could have the clear idea of the reason for not directly dreferencing the Pointer.

You don't want to directly dereference pointers to device registers because you don't want the processor or compiler to reorder your register accesses. The in/out_* wrappers keeps the compiler from reordering things, and the wrappers contain the 'sync' instruction which prevents the processor from reordering operations at runtime.

g.

Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
[email protected]
(403) 399-0195
#11 lore raw
In reply to Misbah khan
Quoted 10 lines · Misbah khan
Quoted 7 lines · Scott Wood-2 wrote:

They're used all over the place. Is there anything about them that you find suspect?

-Scott

I have devloped a character driver for FPGA which is memory mapped and using these API's to test a bit , set a bit or to clear a bit in the memory for eg :-

Please don't use quote markers on newly added text.

Quoted 4 lines
Quoted 4 lines

/* poll till data is transfered from sdram to dpram */

		while((test_bit(DFR_BUSY,(UINT32 *)(\
			(void *)mmap_reg_ptr + DATA_STATUS_REG))==1)\
			&& (delay < MAX_DELAY_BUSY))

You should use in_be32() rather than direct dereferencing.

Quoted 12 lines
Quoted 12 lines
		{
			KDEBUG3(" In the Dfr delay loop \n");
			mdelay(DELAY);
			delay+=DELAY;
		}/* End of while(test_bit(FPGA_BUSY,(void *)register name) */

		if(delay==MAX_DELAY_BUSY)
		{
			KDEBUG1("Out of the the Dfr busy loop \n");
			return -1;
		}
Quoted 3 lines
Quoted 3 lines

People working for FPGA are sure that they are not making the bit high where in my driver is returning -1 from the kernel space aborting it after running for few minutes or so .

I don't suppose the "few minutes" corresponds to MAX_DELAY_BUSY?

-Scott