Re: Why shoud we cause panic in scsi_da.c?

2015-07-16 Thread Kohji Okuno
Subject: Re: Why shoud we cause panic in scsi_da.c?
Date: Tue, 14 Jul 2015 15:49:29 -0400
 On Mon, Jul 13, 2015 at 18:29:36 +0300, Alexander Motin wrote:
 Hi.
 
 On 13.07.2015 11:51, Kohji Okuno wrote:
  On 07/13/15 10:11, Kohji Okuno wrote:
  Could you comment on my quesion?
 
  I found panic() in scsi_da.c. Please find the following.
  I think we should return with error without panic().
  What do you think about this?
 
  scsi_da.c:
  3018} else if (bp != NULL) {
  3019 if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 0)
  3020panic(REQ_CMP with QFRZN);
 
 
  It looks to me more like an KASSERT() is appropriate here.
 
 As I can see, this panic() call was added by ken@ about 15 years ago.
 I've added him to CC in case he has some idea why it was done. From my
 personal opinion I don't see much reasons to allow CAM_DEV_QFRZN to be
 returned only together with error. While is may have little sense in
 case of successful command completion, I don't think it should be
 treated as error. Simply removing this panic is probably a bad idea,
 since if it happens device will just remain frozen forever, that will be
 will be difficult to diagnose, but I would better just dropped device
 freeze in that case same as in case of completion with error.
 
 I put it there because it indicates a software error.  The queue shouldn't
 be frozen if the command is successful.  The reason for freezing the queue
 is to allow error recovery to happen.  The queue will get unfrozen after
 error recovery completes.
 
 We could alternately just print a diagnostic message, unfreeze the queue
 and move on, but the idea is to allow the driver writer to detect and
 correct his error immediately.
 
 As for the original poster's problem, he has uncovered a bug that needs to
 be fixed.  (And I don't mean in the da(4) driver.  The bug is in the
 component that left the queue frozen.  Most likely in the USB driver, but
 it will take a little more investigation.)  The panic worked as intended. :)

I don't know the reaseon. When I accessed the specified sector on the
specified HDD, I encounter the panic. But, I can access other sectors
on the same HDD. And, I can access all sectors on the other HDD (same
model).

Even if Ken's logic is correct, I think that we should do panic in
da(4) driver.

Best regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Why shoud we cause panic in scsi_da.c?

2015-07-13 Thread Kohji Okuno
Hi HPS,

Thank you for your comment.
I will wait for the commnet.

Kohji Okuno

 On 07/13/15 10:11, Kohji Okuno wrote:
 Hi,

 Could you comment on my quesion?

 Best regards,
   Kohji Okuno

 Hi,

 I found panic() in scsi_da.c. Please find the following.
 I think we should return with error without panic().
 What do you think about this?

 scsi_da.c:
 3018} else if (bp != NULL) {
 3019 if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 0)
 3020panic(REQ_CMP with QFRZN);

 
 Hi,
 
 It looks to me more like an KASSERT() is appropriate here.
 
 Might be some people which can answer this are on vacation currently.
 
 --HPS
 
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Why shoud we cause panic in scsi_da.c?

2015-07-13 Thread Kohji Okuno
Hi,

From: Alexander Motin m...@freebsd.org
Date: Mon, 13 Jul 2015 18:29:36 +0300
 Hi.
 
 On 13.07.2015 11:51, Kohji Okuno wrote:
 On 07/13/15 10:11, Kohji Okuno wrote:
 Could you comment on my quesion?

 I found panic() in scsi_da.c. Please find the following.
 I think we should return with error without panic().
 What do you think about this?

 scsi_da.c:
 3018  } else if (bp != NULL) {
 3019 if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 0)
 3020  panic(REQ_CMP with QFRZN);


 It looks to me more like an KASSERT() is appropriate here.
 
 As I can see, this panic() call was added by ken@ about 15 years ago.
 I've added him to CC in case he has some idea why it was done. From my
 personal opinion I don't see much reasons to allow CAM_DEV_QFRZN to be
 returned only together with error. While is may have little sense in
 case of successful command completion, I don't think it should be
 treated as error. Simply removing this panic is probably a bad idea,
 since if it happens device will just remain frozen forever, that will be
 will be difficult to diagnose, but I would better just dropped device
 freeze in that case same as in case of completion with error.

Thank you for your comment.
I have a strange USB HDD. When I access the specified sector, the
kernel causes panic(REQ_CMP with QFRZN) always.

After I modified the following, I think that I can recover from this
state, although the specified sector access fails. This recovery means
that I can access other sectors after this recovery.

What do you think about my idea?


@@ -3016,8 +3016,17 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
 /*timeout*/0,
 /*getcount_only*/0);
} else if (bp != NULL) {
+#if 0
if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 0)
panic(REQ_CMP with QFRZN);
+#else
+   if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 0)
+   cam_release_devq(done_ccb-ccb_h.path,
+/*relsim_flags*/0,
+/*reduction*/0,
+/*timeout*/0,
+/*getcount_only*/0);
+#endif
if (state == DA_CCB_DELETE)
bp-bio_resid = 0;
else

Best regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Why shoud we cause panic in scsi_da.c?

2015-07-13 Thread Kohji Okuno
Hi,

Could you comment on my quesion?

Best regards,
 Kohji Okuno

 Hi,
 
 I found panic() in scsi_da.c. Please find the following.
 I think we should return with error without panic().
 What do you think about this?
 
 scsi_da.c:
 3018  } else if (bp != NULL) {
 3019  if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 
 0)
 3020  panic(REQ_CMP with QFRZN);
 
 Best regards,
  Kohji Okuno
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Why shoud we cause panic in scsi_da.c?

2015-07-09 Thread Kohji Okuno
Hi,

I found panic() in scsi_da.c. Please find the following.
I think we should return with error without panic().
What do you think about this?

scsi_da.c:
3018} else if (bp != NULL) {
3019if ((done_ccb-ccb_h.status  CAM_DEV_QFRZN) != 
0)
3020panic(REQ_CMP with QFRZN);

Best regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: About pmap_mapdev() pmap_unmapdev()

2014-10-06 Thread Kohji Okuno
Hi Konstantin,

I tested your patch. It was no problem.
Thank you for your kind correspondence.

Regards,
 Kohji Okuno

 On Sat, Oct 04, 2014 at 05:53:26PM +0900, Kohji Okuno wrote:
 Hi, Konstantin,
 
  At the end of the mail is commit candidate.  I did not even compiled this.
  Can you test and report back, please ?
 
 Could you check the following?
 (1) should use kernel_pmap-pm_stats.resident_count
   ^^^
 I'm sorry. My patch was wrong. 
 As well as mine.
 
 
 (2) should use pmap_resident_count_inc() in amd64.
 Correct.
 
 
 
 I will test, later.
 
 In addtion, I have one question.
 In current and 10-stable, is vm_map_delete() called by kva_free()?
 No, kva_free() only releases the vmem backing, leaving the page
 tables intact.  This is why I only did the stable/9 patch.
 
 If vm_map_delete() is called, this fix is needed in current and
 10-stable, I think.
 
 Updated patch below.
 
 Index: amd64/amd64/pmap.c
 ===
 --- amd64/amd64/pmap.c(revision 272506)
 +++ amd64/amd64/pmap.c(working copy)
 @@ -5040,6 +5040,9 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, in
   pa = trunc_page(pa);
   for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE)
   pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
 + PMAP_LOCK(kernel_pmap);
 + pmap_resident_count_inc(kernel_pmap, OFF_TO_IDX(size));
 + PMAP_UNLOCK(kernel_pmap);
   pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
   pmap_invalidate_cache_range(va, va + tmpsize);
   return ((void *)(va + offset));
 Index: i386/i386/pmap.c
 ===
 --- i386/i386/pmap.c  (revision 272506)
 +++ i386/i386/pmap.c  (working copy)
 @@ -5066,10 +5066,14 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, in
   size = roundup(offset + size, PAGE_SIZE);
   pa = pa  PG_FRAME;
  
 - if (pa  KERNLOAD  pa + size = KERNLOAD)
 + if (pa  KERNLOAD  pa + size = KERNLOAD) {
   va = KERNBASE + pa;
 - else
 + } else {
   va = kmem_alloc_nofault(kernel_map, size);
 + PMAP_LOCK(kernel_pmap);
 + kernel_pmap-pm_stats.resident_count += OFF_TO_IDX(size);
 + PMAP_UNLOCK(kernel_pmap);
 + }
   if (!va)
   panic(pmap_mapdev: Couldn't alloc kernel virtual memory);
  
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: About pmap_mapdev() pmap_unmapdev()

2014-10-05 Thread Kohji Okuno
Hi Konstantin,

Thank you very much for your detailed explanatin.
I understood the policy of vmem.

Many thanks,
 Kohji Okuno

 On Sun, Oct 05, 2014 at 01:15:12PM +0900, Kohji Okuno wrote:
 Hi,
 
  On Sat, Oct 04, 2014 at 08:53:35PM +0900, Kohji Okuno wrote:
  Hi Konstantin,
  
  Thank you for your prompt response.
  I will test and report from next monday.
  
   In addtion, I have one question.
   In current and 10-stable, is vm_map_delete() called by kva_free()?
   No, kva_free() only releases the vmem backing, leaving the page
   tables intact.  This is why I only did the stable/9 patch.
  
  Where are PTEs allocated by pmap_mapdev() freed in current and 10-stable?
  Could you please explain me?
  They are not freed. The removal of the vmem which covers the address
  space managed by corresponding ptes, allows the reuse of both KVA region
  and corresponding PTEs in the tables. The only concern with the resident
  page tables is to avoid two kva_alloc() to step over each other, and
  this is ensured by vmem.
 
 I agree that normal pages are reusable. But, since the pages mapped by
 pmap_mapdev() are concerned with the physicall address of device (For
 example: video memory), these PTEs aren't reusable, I think.
 So, should we free these PTEs by pmap_unmapdev()?
 There is no hold on any physical pages which were referenced by the ptes.
 The only thing which is left out are the records in the page tables
 which map the KVA to said device memory.  It is harmless.
 
 When the KVA is reused, the ptes in page tables are overwritten.
 
 It might be argued that clearing PTEs, or at least removing the PG_V
 bit catches erronous unintended accesses to the freed range, but by the
 cost of the overhead of re-polluting the caches. And since clearing is
 not effective without doing TLB flush, which requires broadcast IPI,
 it is more trouble than advantage.
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: About pmap_mapdev() pmap_unmapdev()

2014-10-04 Thread Kohji Okuno
Hi, Konstantin,

Thank you for your comment.
And, your change is better than mine.

 Do you mean that this panic is related to missed pmap_remove() ?
 I doubt it, since pmap_mapdev() does not establish managed mappings.

Yes, pmap_mapdev() does not establish managed mappings. But, if
kernel_pmap.pm_stats.resident_count is zero, then any managed pages
(for example pipe_map, exec_map, or etc.) are not able to change
unmanaged status, because pmap_remove() returns without calling
pmap_remove_pte().

In this result, I encounterd the panic. Could you refer the following?

Regards,
 Kohji Okuno

int
vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
{
  SNIP 
   /** this pmap_remove() does not change for mappings! **/
   pmap_remove(map-pmap, entry-start, entry-end);

/*
 * Delete the entry only after removing all pmap
 * entries pointing to its pages.  (Otherwise, its
 * page frames may be reallocated, and any modify bits
 * will be set in the wrong object!)
 */

/** this calls vm_page_free_toq() and causes panic! **/
vm_map_entry_delete(map, entry);
entry = next;
}
return (KERN_SUCCESS);
}

 On Fri, Oct 03, 2014 at 05:25:33PM +0900, Kohji Okuno wrote:
 Hi,
 
 At least in i386  9-stable, when we call pmap_mapdev() and
 pmap_unmapdev(), kernel_pmap.pm_stats.resident_count is decreased
 incorrectly.
 
 pmap_mapdev_attr()-pmap_kenter_attr():
 In this path, kernel_pmap.pm_stats.resident_count is not increlmented.
 
 pmap_unmapdev()-kmem_free(kernel_map)-vm_map_remove()-pmap_remove():
 But, in this path, kernel_pmap.pm_stats.resident_count is decreased in
 pmap_remove_pte().
 
 While I called pmap_mapdev() and pmap_unmapdev() repeatedly and
 kernel_pmap.pm_stats.resident_count became `0', since pmap_remove()
 returned without removing ptes, I encountered various kernel panics.
 I think you are right.
 
 The problem seems to be fixed in HEAD and 10, since mapdev was switched
 to use kva_alloc/kva_free.  I added stable@ to Cc:.
 
 
 And, when I enabled INVARIANTS, I looked the following panic message.
 panic: vm_page_free_toq: freeing mapped page 0x.
 Do you mean that this panic is related to missed pmap_remove() ?
 I doubt it, since pmap_mapdev() does not establish managed mappings.
 
 
 I think, I should change the following.
 What do you think about this?
 
 
 diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
 index 2adc6f8..a0998e8 100644
 --- a/sys/i386/i386/pmap.c
 +++ b/sys/i386/i386/pmap.c
 @@ -5061,6 +5061,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int 
 mode)
  {
  vm_offset_t va, offset;
  vm_size_t tmpsize;
 +int kmem_allocated = 0;
  
  offset = pa  PAGE_MASK;
  size = roundup(offset + size, PAGE_SIZE);
 @@ -5068,13 +5069,18 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int 
 mode)
  
  if (pa  KERNLOAD  pa + size = KERNLOAD)
  va = KERNBASE + pa;
 -else
 +else {
  va = kmem_alloc_nofault(kernel_map, size);
 +kmem_allocated = 1;
 
 You could just do
   PMAP_LOCK(kernel_pmap);
   kernel_pmap.pm_stats.resident_count += OFF_TO_IDX(size);
   PMAP_UNLOCK(kernel_pmap);
 there.  And, the same fix is needed for amd64.
 
 +}
  if (!va)
  panic(pmap_mapdev: Couldn't alloc kernel virtual memory);
  
 -for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE)
 +for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE) {
  pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
 +if (kmem_allocated)
 +kernel_pmap.pm_stats.resident_count++;
 +}
  pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
  pmap_invalidate_cache_range(va, va + size);
  return ((void *)(va + offset));
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: About pmap_mapdev() pmap_unmapdev()

2014-10-04 Thread Kohji Okuno
Hi, Konstantin,

 At the end of the mail is commit candidate.  I did not even compiled this.
 Can you test and report back, please ?

Could you check the following?
(1) should use kernel_pmap-pm_stats.resident_count
  ^^^
I'm sorry. My patch was wrong. 

(2) should use pmap_resident_count_inc() in amd64.


I will test, later.

In addtion, I have one question.
In current and 10-stable, is vm_map_delete() called by kva_free()?
If vm_map_delete() is called, this fix is needed in current and
10-stable, I think.

Regards,
 Kohji Okuno

 On Sat, Oct 04, 2014 at 05:00:36PM +0900, Kohji Okuno wrote:
 Hi, Konstantin,
 
 Thank you for your comment.
 And, your change is better than mine.
 At the end of the mail is commit candidate.  I did not even compiled this.
 Can you test and report back, please ?
 
 
  Do you mean that this panic is related to missed pmap_remove() ?
  I doubt it, since pmap_mapdev() does not establish managed mappings.
 
 Yes, pmap_mapdev() does not establish managed mappings. But, if
 kernel_pmap.pm_stats.resident_count is zero, then any managed pages
 (for example pipe_map, exec_map, or etc.) are not able to change
 unmanaged status, because pmap_remove() returns without calling
 pmap_remove_pte().
 
 In this result, I encounterd the panic. Could you refer the following?
 Yes, kmem_back() indeed uses managed mapping.
 
 Index: amd64/amd64/pmap.c
 ===
 --- amd64/amd64/pmap.c(revision 272506)
 +++ amd64/amd64/pmap.c(working copy)
 @@ -5040,6 +5040,9 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, in
   pa = trunc_page(pa);
   for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE)
   pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
 + PMAP_LOCK(kernel_pmap);
 + kernel_pmap.pm_stats.resident_count += OFF_TO_IDX(size);
 + PMAP_UNLOCK(kernel_pmap);
   pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
   pmap_invalidate_cache_range(va, va + tmpsize);
   return ((void *)(va + offset));
 Index: i386/i386/pmap.c
 ===
 --- i386/i386/pmap.c  (revision 272506)
 +++ i386/i386/pmap.c  (working copy)
 @@ -5066,10 +5066,14 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, in
   size = roundup(offset + size, PAGE_SIZE);
   pa = pa  PG_FRAME;
  
 - if (pa  KERNLOAD  pa + size = KERNLOAD)
 + if (pa  KERNLOAD  pa + size = KERNLOAD) {
   va = KERNBASE + pa;
 - else
 + } else {
   va = kmem_alloc_nofault(kernel_map, size);
 + PMAP_LOCK(kernel_pmap);
 + kernel_pmap.pm_stats.resident_count += OFF_TO_IDX(size);
 + PMAP_UNLOCK(kernel_pmap);
 + }
   if (!va)
   panic(pmap_mapdev: Couldn't alloc kernel virtual memory);
  
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: About pmap_mapdev() pmap_unmapdev()

2014-10-04 Thread Kohji Okuno
Hi Konstantin,

Thank you for your prompt response.
I will test and report from next monday.

 In addtion, I have one question.
 In current and 10-stable, is vm_map_delete() called by kva_free()?
 No, kva_free() only releases the vmem backing, leaving the page
 tables intact.  This is why I only did the stable/9 patch.

Where are PTEs allocated by pmap_mapdev() freed in current and 10-stable?
Could you please explain me?

Regards,
 Kohji Okuno

 On Sat, Oct 04, 2014 at 05:53:26PM +0900, Kohji Okuno wrote:
 Hi, Konstantin,
 
  At the end of the mail is commit candidate.  I did not even compiled this.
  Can you test and report back, please ?
 
 Could you check the following?
 (1) should use kernel_pmap-pm_stats.resident_count
   ^^^
 I'm sorry. My patch was wrong. 
 As well as mine.
 
 
 (2) should use pmap_resident_count_inc() in amd64.
 Correct.
 
 
 
 I will test, later.
 
 In addtion, I have one question.
 In current and 10-stable, is vm_map_delete() called by kva_free()?
 No, kva_free() only releases the vmem backing, leaving the page
 tables intact.  This is why I only did the stable/9 patch.
 
 If vm_map_delete() is called, this fix is needed in current and
 10-stable, I think.
 
 Updated patch below.
 
 Index: amd64/amd64/pmap.c
 ===
 --- amd64/amd64/pmap.c(revision 272506)
 +++ amd64/amd64/pmap.c(working copy)
 @@ -5040,6 +5040,9 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, in
   pa = trunc_page(pa);
   for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE)
   pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
 + PMAP_LOCK(kernel_pmap);
 + pmap_resident_count_inc(kernel_pmap, OFF_TO_IDX(size));
 + PMAP_UNLOCK(kernel_pmap);
   pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
   pmap_invalidate_cache_range(va, va + tmpsize);
   return ((void *)(va + offset));
 Index: i386/i386/pmap.c
 ===
 --- i386/i386/pmap.c  (revision 272506)
 +++ i386/i386/pmap.c  (working copy)
 @@ -5066,10 +5066,14 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, in
   size = roundup(offset + size, PAGE_SIZE);
   pa = pa  PG_FRAME;
  
 - if (pa  KERNLOAD  pa + size = KERNLOAD)
 + if (pa  KERNLOAD  pa + size = KERNLOAD) {
   va = KERNBASE + pa;
 - else
 + } else {
   va = kmem_alloc_nofault(kernel_map, size);
 + PMAP_LOCK(kernel_pmap);
 + kernel_pmap-pm_stats.resident_count += OFF_TO_IDX(size);
 + PMAP_UNLOCK(kernel_pmap);
 + }
   if (!va)
   panic(pmap_mapdev: Couldn't alloc kernel virtual memory);
  
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: About pmap_mapdev() pmap_unmapdev()

2014-10-04 Thread Kohji Okuno
Hi,

 On Sat, Oct 04, 2014 at 08:53:35PM +0900, Kohji Okuno wrote:
 Hi Konstantin,
 
 Thank you for your prompt response.
 I will test and report from next monday.
 
  In addtion, I have one question.
  In current and 10-stable, is vm_map_delete() called by kva_free()?
  No, kva_free() only releases the vmem backing, leaving the page
  tables intact.  This is why I only did the stable/9 patch.
 
 Where are PTEs allocated by pmap_mapdev() freed in current and 10-stable?
 Could you please explain me?
 They are not freed. The removal of the vmem which covers the address
 space managed by corresponding ptes, allows the reuse of both KVA region
 and corresponding PTEs in the tables. The only concern with the resident
 page tables is to avoid two kva_alloc() to step over each other, and
 this is ensured by vmem.

I agree that normal pages are reusable. But, since the pages mapped by
pmap_mapdev() are concerned with the physicall address of device (For
example: video memory), these PTEs aren't reusable, I think.
So, should we free these PTEs by pmap_unmapdev()?

Best regards,
 Kohji Okuno

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


About pmap_mapdev() pmap_unmapdev()

2014-10-03 Thread Kohji Okuno
Hi,

At least in i386  9-stable, when we call pmap_mapdev() and
pmap_unmapdev(), kernel_pmap.pm_stats.resident_count is decreased
incorrectly.

pmap_mapdev_attr()-pmap_kenter_attr():
In this path, kernel_pmap.pm_stats.resident_count is not increlmented.

pmap_unmapdev()-kmem_free(kernel_map)-vm_map_remove()-pmap_remove():
But, in this path, kernel_pmap.pm_stats.resident_count is decreased in
pmap_remove_pte().

While I called pmap_mapdev() and pmap_unmapdev() repeatedly and
kernel_pmap.pm_stats.resident_count became `0', since pmap_remove()
returned without removing ptes, I encountered various kernel panics.

And, when I enabled INVARIANTS, I looked the following panic message.
panic: vm_page_free_toq: freeing mapped page 0x.

I think, I should change the following.
What do you think about this?


diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 2adc6f8..a0998e8 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -5061,6 +5061,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
 {
vm_offset_t va, offset;
vm_size_t tmpsize;
+   int kmem_allocated = 0;
 
offset = pa  PAGE_MASK;
size = roundup(offset + size, PAGE_SIZE);
@@ -5068,13 +5069,18 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int 
mode)
 
if (pa  KERNLOAD  pa + size = KERNLOAD)
va = KERNBASE + pa;
-   else
+   else {
va = kmem_alloc_nofault(kernel_map, size);
+   kmem_allocated = 1;
+   }
if (!va)
panic(pmap_mapdev: Couldn't alloc kernel virtual memory);
 
-   for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE)
+   for (tmpsize = 0; tmpsize  size; tmpsize += PAGE_SIZE) {
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
+   if (kmem_allocated)
+   kernel_pmap.pm_stats.resident_count++;
+   }
pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
pmap_invalidate_cache_range(va, va + size);
return ((void *)(va + offset));
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Does the xHCI driver has a spec violation?

2014-09-22 Thread Kohji Okuno
Hi HPS,

Could you refer to the following document (4.6.6 Configure Endpoint:P.99)?
This document shows:

If the Drop Context flag is `1' and the Add Context flag is `1', the xHC shall:
o Release the current Resources and Bandwidth allocated to the
  endpoint and assign the new Resources and Bandwidth requested for
  the endpoint.

Regards,
 Kohji Okuno.

 On 09/22/14 06:58, Kohji Okuno wrote:
 Hi,

 I encountered a issue for USB mic.

 In fist time, my host controller (xHCI) sends single IN-tokens every
 8-SOFs. This is expected action. But, after I open, close and open, my
 host controller sends plural IN-tokens between SOF and SOF.

 In Intel Lynx Point, I could not reproduce this issue.
 I'm sorry. Unfortunately, I can't explain details about my proprietary
 host controler.

 I found the following explanation in the xHCI 1.1 specification
 http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf

 In 4.8.3 Endpoint Context State,
6. The Configure Endpoint Command (Add (A) = `1' and Drop (D) =`1')
   shall transition an endpoint, except the Default Control
   Endpoint, from the Stopped to the Running state.'


 So, I modify as the following, then I can run expectedly.
 What do you think about this change?
 
 Hi,
 
 I think we should issue the context drop separately. Are we certain that if
 both drop and add bits are set at the same time, that the drop bit will be
 processed before the add?
 
 This might be a bug in your hardware, which apparently doesn't check if the
 context has already been added or not. I'll be glad to make a workaround for
 it once we have settled on a solution.
 
 Can you test the attached patch using both your hardware and the Lynx Point.
 
 Thank you!
 
 --HPS
 

 Best regards,
   Kohji Okuno
 
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Does the xHCI driver has a spec violation?

2014-09-22 Thread Kohji Okuno
 On 09/22/14 08:31, Kohji Okuno wrote:
 Hi HPS,

 Could you refer to the following document (4.6.6 Configure Endpoint:P.99)?
 This document shows:

 If the Drop Context flag is `1' and the Add Context flag is `1', the xHC
 shall:
 o Release the current Resources and Bandwidth allocated to the
endpoint and assign the new Resources and Bandwidth requested for
the endpoint.

 
 Hi,
 
 I see.
 
 Then what is missing to your patch is to mask away bits 0 and 1, because those
 are reserved for D0 and D1 and should be zero?

Hi, HPS,

You are correct, I think. We shold mask D0 and D1.
My host controller works both.

Thanks,
 Kohji Okuno.


___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Does the xHCI driver has a spec violation?

2014-09-22 Thread Kohji Okuno
 Hi,
 
 Please verify:
 http://svnweb.freebsd.org/changeset/base/271953
 
 Thank you!
 
 --HPS

Hi, HPS,

I confirmed your commit. It was no problem.

Many thanks,
 Kohji Okuno.
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Does the xHCI driver has a spec violation?

2014-09-21 Thread Kohji Okuno
Hi,

I encountered a issue for USB mic.

In fist time, my host controller (xHCI) sends single IN-tokens every
8-SOFs. This is expected action. But, after I open, close and open, my
host controller sends plural IN-tokens between SOF and SOF.

In Intel Lynx Point, I could not reproduce this issue.
I'm sorry. Unfortunately, I can't explain details about my proprietary
host controler.

I found the following explanation in the xHCI 1.1 specification
http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf

In 4.8.3 Endpoint Context State, 
  6. The Configure Endpoint Command (Add (A) = `1' and Drop (D) =`1')
 shall transition an endpoint, except the Default Control
 Endpoint, from the Stopped to the Running state.'


So, I modify as the following, then I can run expectedly.
What do you think about this change?

Best regards,
 Kohji Okuno


static usb_error_t
xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop)
{
struct xhci_softc *sc = XHCI_BUS2SC(udev-bus);
struct usb_page_search buf_inp;
struct xhci_input_dev_ctx *pinp;
uint32_t temp;
uint8_t index;
uint8_t x;

index = udev-controller_slot_id;

usbd_get_page(sc-sc_hw.devs[index].input_pc, 0, buf_inp);

pinp = buf_inp.buffer;

if (drop) {
mask = XHCI_INCTX_NON_CTRL_MASK;
xhci_ctx_set_le32(sc, pinp-ctx_input.dwInCtx0, mask);
xhci_ctx_set_le32(sc, pinp-ctx_input.dwInCtx1, 0);
} else {
-   xhci_ctx_set_le32(sc, pinp-ctx_input.dwInCtx0, 0);
+   xhci_ctx_set_le32(sc, pinp-ctx_input.dwInCtx0, mask);
xhci_ctx_set_le32(sc, pinp-ctx_input.dwInCtx1, mask);
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


About the type of physaddr in struct usb_page.

2014-06-01 Thread Kohji Okuno
Hi HPS,

I think the type of physaddr in struct usb_page is incorrect.
We shuld use bus_addr_t for physaddr.
What do you think about this?

60   * The following structure defines physical and non kernel virtual
61   * address of a memory page having size USB_PAGE_SIZE.
62   */
63  struct usb_page {
64  #if USB_HAVE_BUSDMA
65  bus_size_t physaddr;
66  void   *buffer; /* non Kernel Virtual Address */
67  #endif
68  };

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


UFS SU+J bug? (Re: uninitialized journal data written in SU+J ?)

2014-04-22 Thread Kohji Okuno
Hi,

If you use UFS SU+J, could you check your `.sujournal'?
(For example: strings .sujournal)
You will find memory that already has been released.

In addition, unfotunately, if the memory was used for journal is
re-used, although the journal is incorrect, fsck will missunderstand it.

What do you think about this?

Regards,
 Kohji Okuno

From: takehara.mikih...@jp.panasonic.com
Subject: uninitialized journal data written in SU+J ?
Date: Tue, 22 Apr 2014 16:21:43 +0900
 Hello,
 
 
 I'm testing UFS with SU+J. But it seems sometimes broken journal data has 
 written.
 
 In softdep_process_journal (ffs_softdep.c), there is a while code to build 
 jsegrec and each entry.
 But by my test, sometimes there is no entry then break this while code 
 without building jsegrec.
 If this happens, bp-b_data is not initialized but this bp is written, I 
 think.
 
 I checked this behavior by following patch.
 
 diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
 index 585af50..2d4939c 100644
 --- a/sys/ufs/ffs/ffs_softdep.c
 +++ b/sys/ufs/ffs/ffs_softdep.c
 @@ -3421,6 +3421,15 @@ softdep_process_journal(mp, needwk, flags)
 data = bp-b_data + off;
 cnt--;
 }
 +
 +#if 1
 +   if (off == 0) {
 +   struct jsegrec *tmp = (struct jsegrec*)bp-b_data;
 +   if (tmp-jsr_seq != jseg-js_seq) {
 +   panic(test test);
 +   }
 +   }
 +#endif
 /*
  * Write this one buffer and continue.
  */
 
 
 If uninitialized data is valid by fsck suj, this may result filesystem 
 corruption, I think.
 I think it's better to clear b_data before using it.
 
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kevent has bug?

2014-04-03 Thread Kohji Okuno
 0x100   /* flux set in 
 kqueue_scan() */
   int kn_sfflags; /* saved filter flags */
   intptr_tkn_sdata;   /* saved data field */
   union {

Hi,

I think, we should add KN_SCAN after knote_attach() in
kqueue_register(), too. What do you think about this?

Best regards,
 Kohji Okuno

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kevent has bug?

2014-04-03 Thread Kohji Okuno
From: Konstantin Belousov kostik...@gmail.com
Date: Thu, 3 Apr 2014 16:48:14 +0300
 On Thu, Apr 03, 2014 at 06:26:56PM +0900, Kohji Okuno wrote:
  The done_ev_add case is indeed missed in my patch, thank you for noting.
  The case of EV_ADD does not need the KN_SCAN workaround, IMO, since the
  race is possible just by the nature of adding the knote.
 
 I think, we should add KN_SCAN after knote_attach() in
 kqueue_register(), too. What do you think about this?
 See above, I noted this case in the previous mail.  This may be elaborated.
 
 First, I think it is technically incorrect to allow the event
 notification before the f_attach() method is finished. So the KN_SCAN
 flag could be set only after f_attach() call, but due to both kq and
 knlist not locked there, we still have the same race. And this race is
 in fact acceptable, since it is the race between application calling
 EV_ADD, and external event occuring, which cannot be avoided. Until the
 kevent(EV_ADD) syscall returned, we do not have an obligation to report
 the event from the kqfd. Having the race somewhat bigger by not setting
 KN_SCAN is fine in my opinion.

Hi,

Thank you for your detailed commnet. And I uderstood about your opinion.
By the way, do you commit your change to HEAD?

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kevent has bug?

2014-04-02 Thread Kohji Okuno
From: John-Mark Gurney j...@funkthat.com
Date: Tue, 1 Apr 2014 23:15:51 -0700
 Kohji Okuno wrote this message on Wed, Apr 02, 2014 at 11:45 +0900:
 I think, kevent() has a bug.
 I tested sample programs by attached sources.
 This sample tests about EVFILT_SIGNAL.
 
 I build sample programs by the following commands.
 % gcc -O2 -o child child.c
 % gcc -O2 -o parent parent.c
 
 The expected result is the following.
 % ./parent
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
 OK
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
 OK
 
 But, sometimes the result was the following.
 % ./parent
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
 
 This result means the number of times the signal has occured was
 incorrect.
 
 I was able to reproduce this...
 
 In case of EVFILT_SIGNAL, according to `man kevent', `data' retuns the
 number of times the signal has occurred since the last call to
 kevent(). This `data' is recorded by filt_signal() (This is f_event in
 struct filterops).
 
 The system call kevent()'s events are processed by kqueue_scan() in
 kern_event.c. In kqueue_scan(), kn-kn_fop-f_event() is allways
 called after KN_INFLUX is set to kn-kn_status.
 
 On the other hand, kernel events are occured by knote() in
 kern_event.c. (In EVFILT_SIGNAL, knote() is called from tdsendsignal()
 in kern_sig.c.) In knote(), kn-kn_fop-f_event() is called only when
 KN_INFLUX is not set in kn-kn_status.
 
 In race condition between kqueue_scan() and knote(),
 kn-kn_fop-f_event() from knote() may not be called, I think.
 
 Considering that both are called w/ a lock, that cannot happen..
 KN_LIST_LOCK(kn) locks the same lock that is asserted that is held
 by knote...
 
 In knote(), because the context holds knlist's lock, the context can
 not sleep. So, KN_INFLUX should not be set on calling
 kn-kn_fop-f_event() in kqueue_scan(), I think.
 
 No, it needs to be set:
  * Setting the KN_INFLUX flag enables you to unlock the kq that this knote
  * is on, and modify kn_status as if you had the KQ lock.
 
 As this comment says, _INFLUX allows you to unlock the KQ w/o fear that
 the knote will disappear out from under you causing you to dereference
 possibly free'd memory..
 
 If you just tried to lock the list lock w/o unlocking the KQ lock, you
 could end up w/ a dead lock, as you aren't maintaining lock order
 properly..  The correct lock order if knlist - kq...
 
 What do you think about this issue?
 
 This is a real issue, but not due to the race you described
 above...

I beleave it's the result of the race.

Could you try to add printf() in knote()?
Please refer to attached patch.


 I have verified on my machine that it isn't because there is a knote
 waiting that isn't getting woken up, and the knote on my hung process
 has data == 0, so it definately lost one of the signals:
 (kgdb) print $14.kq_knhash[20].slh_first[0]
 $20 = {kn_link = {sle_next = 0x0}, kn_selnext = {sle_next = 0x0},
   kn_knlist = 0xf8005a9c5840, kn_tqe = {tqe_next = 0xf801fdab4500,
 tqe_prev = 0xf8004bb10038}, kn_kq = 0xf8004bb1, kn_kevent = {
 ident = 20, filter = -6, flags = 32, fflags = 0, data = 0, udata = 0x0},
   kn_status = 0, kn_sfflags = 0, kn_sdata = 0, kn_ptr = {
 p_fp = 0xf8005a9c54b8, p_proc = 0xf8005a9c54b8,
 p_aio = 0xf8005a9c54b8, p_lio = 0xf8005a9c54b8,
 p_v = 0xf8005a9c54b8}, kn_fop = 0x81405ef0, kn_hook = 0x0,
   kn_hookid = 0}
 
 If you want to find this yourself, you can run kgdb on a live system,
 switch to the thread of the parent (info threads, thread XXX), and
 do:
 frame 7
 
 (or a frame that has td, which is struct thread *), then:
 print *(struct kqueue *)td-td_proc[0].p_fd[0].fd_ofiles[3].fde_file[0].f_data
 
 This will give you the struct kqueue * of the parent, and then:
 print $XX.kq_knhash[0]@63
 
 to figure out where the knote is in the hash, and then you can print
 it out yourself...
 
 I'm going to take a look at this a bit more later... I'm thinking of
 using dtrace to collect the stacks where filt_signal is called, and
 match them up...  dtrace might even be able to get us the note's data
 upon return helping to make sure things got tracked properly...
 
 Thanks for finding this bug!  Hopefully we can find a solution to it..
 
 -- 
   John-Mark GurneyVoice: +1 415 225 5579
 
  All that I will do, has been done, All that I have, has not.
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index b3fb23d..7791447 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1868,6 +1868,8 @@ knote(struct knlist *list, long hint, int lockflags)
 		if ((kn-kn_status  KN_INFLUX) != KN_INFLUX) {
 			KQ_LOCK(kq);
 			if ((kn-kn_status  KN_INFLUX) == KN_INFLUX) {
+if (hint  NOTE_SIGNAL)
+	printf(Aee2\n);
 KQ_UNLOCK(kq);
 			} else if ((lockflags  KNF_NOKQLOCK) != 0) {
 kn-kn_status |= KN_INFLUX;
@@ -1886,6 +1888,10 @@ knote(struct knlist *list, long hint, int lockflags)
 KQ_UNLOCK

Re: kevent has bug?

2014-04-02 Thread Kohji Okuno
From: Konstantin Belousov kostik...@gmail.com
Date: Wed, 2 Apr 2014 15:07:45 +0300
 On Wed, Apr 02, 2014 at 04:06:16PM +0900, Kohji Okuno wrote:
 From: John-Mark Gurney j...@funkthat.com
 Date: Tue, 1 Apr 2014 23:15:51 -0700
  Kohji Okuno wrote this message on Wed, Apr 02, 2014 at 11:45 +0900:
  I think, kevent() has a bug.
  I tested sample programs by attached sources.
  This sample tests about EVFILT_SIGNAL.
  
  I build sample programs by the following commands.
  % gcc -O2 -o child child.c
  % gcc -O2 -o parent parent.c
  
  The expected result is the following.
  % ./parent
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
  OK
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
  OK
  
  But, sometimes the result was the following.
  % ./parent
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
  
  This result means the number of times the signal has occured was
  incorrect.
  
  I was able to reproduce this...
  
  In case of EVFILT_SIGNAL, according to `man kevent', `data' retuns the
  number of times the signal has occurred since the last call to
  kevent(). This `data' is recorded by filt_signal() (This is f_event in
  struct filterops).
  
  The system call kevent()'s events are processed by kqueue_scan() in
  kern_event.c. In kqueue_scan(), kn-kn_fop-f_event() is allways
  called after KN_INFLUX is set to kn-kn_status.
  
  On the other hand, kernel events are occured by knote() in
  kern_event.c. (In EVFILT_SIGNAL, knote() is called from tdsendsignal()
  in kern_sig.c.) In knote(), kn-kn_fop-f_event() is called only when
  KN_INFLUX is not set in kn-kn_status.
  
  In race condition between kqueue_scan() and knote(),
  kn-kn_fop-f_event() from knote() may not be called, I think.
  
  Considering that both are called w/ a lock, that cannot happen..
  KN_LIST_LOCK(kn) locks the same lock that is asserted that is held
  by knote...
  
  In knote(), because the context holds knlist's lock, the context can
  not sleep. So, KN_INFLUX should not be set on calling
  kn-kn_fop-f_event() in kqueue_scan(), I think.
  
  No, it needs to be set:
   * Setting the KN_INFLUX flag enables you to unlock the kq that this knote
   * is on, and modify kn_status as if you had the KQ lock.
  
  As this comment says, _INFLUX allows you to unlock the KQ w/o fear that
  the knote will disappear out from under you causing you to dereference
  possibly free'd memory..
  
  If you just tried to lock the list lock w/o unlocking the KQ lock, you
  could end up w/ a dead lock, as you aren't maintaining lock order
  properly..  The correct lock order if knlist - kq...
  
  What do you think about this issue?
  
  This is a real issue, but not due to the race you described
  above...
 
 I beleave it's the result of the race.
 
 Could you try to add printf() in knote()?
 Please refer to attached patch.
 
 
  I have verified on my machine that it isn't because there is a knote
  waiting that isn't getting woken up, and the knote on my hung process
  has data == 0, so it definately lost one of the signals:
  (kgdb) print $14.kq_knhash[20].slh_first[0]
  $20 = {kn_link = {sle_next = 0x0}, kn_selnext = {sle_next = 0x0},
kn_knlist = 0xf8005a9c5840, kn_tqe = {tqe_next = 0xf801fdab4500,
  tqe_prev = 0xf8004bb10038}, kn_kq = 0xf8004bb1, kn_kevent 
  = {
  ident = 20, filter = -6, flags = 32, fflags = 0, data = 0, udata = 
  0x0},
kn_status = 0, kn_sfflags = 0, kn_sdata = 0, kn_ptr = {
  p_fp = 0xf8005a9c54b8, p_proc = 0xf8005a9c54b8,
  p_aio = 0xf8005a9c54b8, p_lio = 0xf8005a9c54b8,
  p_v = 0xf8005a9c54b8}, kn_fop = 0x81405ef0, kn_hook = 0x0,
kn_hookid = 0}
  
  If you want to find this yourself, you can run kgdb on a live system,
  switch to the thread of the parent (info threads, thread XXX), and
  do:
  frame 7
  
  (or a frame that has td, which is struct thread *), then:
  print *(struct kqueue 
  *)td-td_proc[0].p_fd[0].fd_ofiles[3].fde_file[0].f_data
  
  This will give you the struct kqueue * of the parent, and then:
  print $XX.kq_knhash[0]@63
  
  to figure out where the knote is in the hash, and then you can print
  it out yourself...
  
  I'm going to take a look at this a bit more later... I'm thinking of
  using dtrace to collect the stacks where filt_signal is called, and
  match them up...  dtrace might even be able to get us the note's data
  upon return helping to make sure things got tracked properly...
  
  Thanks for finding this bug!  Hopefully we can find a solution to it..
  
  -- 
John-Mark Gurney Voice: +1 415 225 5579
  
   All that I will do, has been done, All that I have, has not.
 
 diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
 index b3fb23d..7791447 100644
 --- a/sys/kern/kern_event.c
 +++ b/sys/kern/kern_event.c
 @@ -1868,6 +1868,8 @@ knote(struct knlist *list, long hint, int lockflags)
  if ((kn-kn_status  KN_INFLUX) != KN_INFLUX

kevent has bug?

2014-04-01 Thread Kohji Okuno
Hi,

I think, kevent() has a bug.
I tested sample programs by attached sources.
This sample tests about EVFILT_SIGNAL.

I build sample programs by the following commands.
% gcc -O2 -o child child.c
% gcc -O2 -o parent parent.c

The expected result is the following.
% ./parent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
OK
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
OK

But, sometimes the result was the following.
% ./parent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

This result means the number of times the signal has occured was
incorrect.



In case of EVFILT_SIGNAL, according to `man kevent', `data' retuns the
number of times the signal has occurred since the last call to
kevent(). This `data' is recorded by filt_signal() (This is f_event in
struct filterops).

The system call kevent()'s events are processed by kqueue_scan() in
kern_event.c. In kqueue_scan(), kn-kn_fop-f_event() is allways
called after KN_INFLUX is set to kn-kn_status.

On the other hand, kernel events are occured by knote() in
kern_event.c. (In EVFILT_SIGNAL, knote() is called from tdsendsignal()
in kern_sig.c.) In knote(), kn-kn_fop-f_event() is called only when
KN_INFLUX is not set in kn-kn_status.

In race condition between kqueue_scan() and knote(),
kn-kn_fop-f_event() from knote() may not be called, I think.


In knote(), because the context holds knlist's lock, the context can
not sleep. So, KN_INFLUX should not be set on calling
kn-kn_fop-f_event() in kqueue_scan(), I think.

What do you think about this issue?

Best regards,
 Kohji Okuno
#include sys/types.h
#include stdlib.h
#include unistd.h
#include stdio.h

int
main()
{
sleep(1);
exit(0);
}
#include sys/types.h
#include sys/wait.h
#include sys/event.h
#include sys/time.h
#include stdlib.h
#include stdio.h
#include unistd.h
#include signal.h

#define NUM_CHILDREN20

int
main()
{
int i;
pid_t pid;
char *argv[2] = {child, NULL};
struct kevent kev;
int kqfd = kqueue();
int count;
int err;
int status;

EV_SET(kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
kevent(kqfd, kev, 1, NULL, 0, NULL);

while (1) {
count = 0;
for (i = 0; i  NUM_CHILDREN; i++) {
pid = fork();
if (pid == 0) {
execve(./child, argv, NULL);
}
}

while (1) {
err = kevent(kqfd, NULL, 0, kev, 1, NULL);
if (err  0  kev.ident == SIGCHLD) {
for (i = 0; i  kev.data; i++) {
pid = waitpid(-1, status, WNOHANG);
if (pid  0) {
count++;
printf(%d , count);
fflush(stdout);
if (count == NUM_CHILDREN) {
printf(\nOK\n);
goto next;
}
}
}
}
}
 next:
 ;
}
exit(0);
}
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: About kevent

2014-02-28 Thread Kohji Okuno
 Kohji Okuno wrote this message on Fri, Feb 28, 2014 at 11:13 +0900:
 I have a question about kevent.
 
 How should the userland judge knote which is cleared from knlist by
 knlist_clear() or knlist_delete()?
 
 It looks like I need to read the code better...  knlist_clear (killkn=0)
 and knlist_delete (killkn=1) are wrappers around knlist_cleardel...
 
 Looking at the code of knlist_cleardel, if killkn is set
 (knlist_delete) the knote will be dropped (free'd)... if it is not set,
 the flags _EOF and _ONESHOT will be set such that it'll be returned
 soon..
 
 Now that I look at the code, KNOTE_ACTIVATE is never called to be put
 on the list to be delivered, so now I'm not sure if it works the way
 it's suppose to... I have a feeling that the notes might hang around
 forever until the kq fd is closed...
 
 I'm also puzzled as to why _DETACHED isn't set, which would seem to
 mean that we'll call f_detach when we close the kq, which I assume
 could cause a panic...
 
 This needs to be investigated/tested...
 
 -- 
   John-Mark GurneyVoice: +1 415 225 5579
 
  All that I will do, has been done, All that I have, has not.

Hi,

Thank you for your comment.

I tried test by usb_dev. When a USB device is lost suddenly, I can
receive EV_EOF|EV_ONESHOT on kevent-flags.

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kqueue for usb_dev

2014-02-27 Thread Kohji Okuno
Hi HPS and John-Mark,

We should wait for empty of knlist before knlist_destroy().
When I tried 262551, the kernel panic at KN_LIST_LOCK(kn) in
kern_event.c.

Regards,
 Kohji Okuno

 On 02/27/14 10:00, Hans Petter Selasky wrote:
 Hi Kohji,

 Can you verify this commit:

 http://svnweb.freebsd.org/changeset/base/262550

 Please test using both read and write direction. For example you can use
 the ULPT driver or a /dev/usb/X.X.X node which supports both read and
 write.

 Thank you!

 --HPS
 
 And this commit too:
 http://svnweb.freebsd.org/changeset/base/262551
 
 Thank you!
 
 --HPS
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kqueue for usb_dev

2014-02-27 Thread Kohji Okuno
Hi HPS and John-Mark,

After I changed as the following, the kernel panic does not happen.
What do you think about this change?

+   knlist_clear(f-selinfo.si_note, 0);
knlist_destroy(f-selinfo.si_note);
 
Regards,
 Kohji Okuno

 We should wait for empty of knlist before knlist_destroy().
 When I tried 262551, the kernel panic at KN_LIST_LOCK(kn) in
 kern_event.c.
 
 Regards,
  Kohji Okuno
 
 On 02/27/14 10:00, Hans Petter Selasky wrote:
 Hi Kohji,

 Can you verify this commit:

 http://svnweb.freebsd.org/changeset/base/262550

 Please test using both read and write direction. For example you can use
 the ULPT driver or a /dev/usb/X.X.X node which supports both read and
 write.

 Thank you!

 --HPS
 
 And this commit too:
 http://svnweb.freebsd.org/changeset/base/262551
 
 Thank you!
 
 --HPS
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kqueue for KBD.

2014-02-27 Thread Kohji Okuno
Hi John-Mark,

Thank you for your comment.
I added knote_clear() and knote_destroy() in kbd_detach(). I attached
patch, again. But, maybe this patch can not resolve all cases you
pointed.

Regards,
 Kohji Okuno

 Kohji Okuno wrote this message on Thu, Feb 27, 2014 at 14:24 +0900:
 I tried to add kqueue I/F to kbd.c. I attached patch.
 What do you think about my patch?
 
 So, knlist_destroy is missing in this patch too..
 
 It also needs some style(9) loving in that some blank lines are missing
 and there are some extra curly braces...
 
 So, knlist_clear is usually used for something like close where it
 cannot be used again...  You use knlist_clear when the kbd goes away,
 but this also means that the user will never be notified that the kbd
 has gone, and could possibly end up leaking resources...
 
 I guess I should maybe write a function knlist_clearerr or something
 that detaches all the knotes from the knlist and sets the proper flag
 so that they can be reaped by userland...  I believe your usb patch
 had a similar issue and some of the other drivers have this issue too..
 
 Otherwise looks good...
 
 -- 
   John-Mark GurneyVoice: +1 415 225 5579
 
  All that I will do, has been done, All that I have, has not.
diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c
index 8036762..26dcaad 100644
--- a/sys/dev/kbd/kbd.c
+++ b/sys/dev/kbd/kbd.c
@@ -59,6 +59,7 @@ typedef struct genkbd_softc {
 	char		gkb_q[KB_QSIZE];		/* input queue */
 	unsigned int	gkb_q_start;
 	unsigned int	gkb_q_length;
+	unsigned int	gkb_index;
 } genkbd_softc_t;
 
 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
@@ -472,6 +473,7 @@ static d_read_t		genkbdread;
 static d_write_t	genkbdwrite;
 static d_ioctl_t	genkbdioctl;
 static d_poll_t		genkbdpoll;
+static d_kqfilter_t	genkbdkqfilter;
 
 
 static struct cdevsw kbd_cdevsw = {
@@ -483,12 +485,14 @@ static struct cdevsw kbd_cdevsw = {
 	.d_write =	genkbdwrite,
 	.d_ioctl =	genkbdioctl,
 	.d_poll =	genkbdpoll,
+	.d_kqfilter =	genkbdkqfilter,
 	.d_name =	kbd,
 };
 
 int
 kbd_attach(keyboard_t *kbd)
 {
+	genkbd_softc_t *sc;
 
 	if (kbd-kb_index = keyboards)
 		return (EINVAL);
@@ -498,8 +502,11 @@ kbd_attach(keyboard_t *kbd)
 	kbd-kb_dev = make_dev(kbd_cdevsw, kbd-kb_index, UID_ROOT, GID_WHEEL,
 	0600, %s%r, kbd-kb_name, kbd-kb_unit);
 	make_dev_alias(kbd-kb_dev, kbd%r, kbd-kb_index);
-	kbd-kb_dev-si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
+	sc = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
 	M_WAITOK | M_ZERO);
+	kbd-kb_dev-si_drv1 = sc;
+	sc-gkb_index = KBD_INDEX(kbd-kb_dev);
+	knlist_init_mtx(sc-gkb_rsel.si_note, NULL);
 	printf(kbd%d at %s%d\n, kbd-kb_index, kbd-kb_name, kbd-kb_unit);
 	return (0);
 }
@@ -507,12 +514,17 @@ kbd_attach(keyboard_t *kbd)
 int
 kbd_detach(keyboard_t *kbd)
 {
+	genkbd_softc_t *sc;
 
 	if (kbd-kb_index = keyboards)
 		return (EINVAL);
 	if (keyboard[kbd-kb_index] != kbd)
 		return (EINVAL);
 
+	sc = kbd-kb_dev-si_drv1;
+	knlist_clear(sc-gkb_rsel.si_note, 0);
+	knlist_destroy(sc-gkb_rsel.si_note);
+
 	free(kbd-kb_dev-si_drv1, M_DEVBUF);
 	destroy_dev(kbd-kb_dev);
 
@@ -697,6 +709,71 @@ genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *
 	return (error);
 }
 
+static void
+genkbd_kqops_detach(struct knote *kn)
+{
+	genkbd_softc_t *sc;
+	sc = kn-kn_hook;
+	knlist_remove(sc-gkb_rsel.si_note, kn, 0);
+}
+
+static int
+genkbd_kqops_event(struct knote *kn, long hint)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+
+	sc = kn-kn_hook;
+	kbd = kbd_get_keyboard(sc-gkb_index);
+
+	if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		return 1;	/* the keyboard has gone */
+	}
+	else {
+		if (sc-gkb_q_length  0)
+			return 1;
+		else
+			return 0;
+	}
+
+}
+static struct filterops genkbd_kqops =
+{
+	.f_isfd		= 1,
+	.f_attach	= NULL,
+	.f_detach	= genkbd_kqops_detach,
+	.f_event	= genkbd_kqops_event,
+};
+static int
+genkbdkqfilter(struct cdev *dev, struct knote *kn)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+	int error = 0;
+	int s;
+
+	s = spltty();
+	sc = dev-si_drv1;
+	kbd = kbd_get_keyboard(KBD_INDEX(dev));
+	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		error = EIO;
+	}
+	else  {
+		switch (kn-kn_filter) {
+		case EVFILT_READ:
+			kn-kn_fop = genkbd_kqops;
+			kn-kn_hook = (void *)sc;
+			knlist_add(sc-gkb_rsel.si_note, kn, 0);
+			break;
+		default:
+			error = EOPNOTSUPP;
+			break;
+		}
+	}
+	splx(s);
+	return (error);
+}
+
 static int
 genkbdpoll(struct cdev *dev, int events, struct thread *td)
 {
@@ -744,6 +821,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(sc-gkb_rsel, PZERO);
+		KNOTE_UNLOCKED(sc-gkb_rsel.si_note, 0);
 		return (0);
 	default:
 		return (EINVAL);
@@ -814,6 +892,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(sc-gkb_rsel, PZERO);
+		KNOTE_UNLOCKED(sc-gkb_rsel.si_note, 0);
 	}
 
 	return (0);
___
freebsd-current

Re: kqueue for usb_dev

2014-02-27 Thread Kohji Okuno
Hi HPS,

Your patch did not resolve the kernel panic.
I think, we should check knlist_clear() before knlist_destroy().
When a device is lost suddenly, usb_dev notify to a process in
usb_fifo_close() and then calls knlist_destroy(). knlist_destroy()
clears knlist-kn_lock and knlist-kn_unlock.

But, the process that is notified will start over kqueue_scan() after
knlist_destroy(). And, in KN_LIST_LOCK(kn), the context will call NULL
function (kn-knlist-kn_lock).

Regards,
 Kohji Okuno

 On 02/27/14 11:39, Kohji Okuno wrote:
 Hi HPS and John-Mark,

 After I changed as the following, the kernel panic does not happen.
 What do you think about this change?

 +   knlist_clear(f-selinfo.si_note, 0);
  knlist_destroy(f-selinfo.si_note);

 Regards,
   Kohji Okuno

 
 Can you try the attached patch instead?
 
 --HPS
 
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


About kevent

2014-02-27 Thread Kohji Okuno
Hi,

I have a question about kevent.

How should the userland judge knote which is cleared from knlist by
knlist_clear() or knlist_delete()?

Best regards,
 Kohji Okuno


___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


kqueue for usb_dev

2014-02-26 Thread Kohji Okuno
Hi,

I tried add kqueue I/F to usb_dev.c. I attached my patch.
What do you think about my patch?

Best regards,
 Kohji Okuno
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index f086a3c..4334be7 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -120,6 +120,9 @@ static d_ioctl_t usb_ioctl;
 static d_read_t usb_read;
 static d_write_t usb_write;
 static d_poll_t usb_poll;
+#if 1
+static d_kqfilter_t usb_kqfilter;
+#endif
 
 static d_ioctl_t usb_static_ioctl;
 
@@ -138,6 +141,10 @@ struct cdevsw usb_devsw = {
 	.d_read = usb_read,
 	.d_write = usb_write,
 	.d_poll = usb_poll
+#if 1
+	,
+	.d_kqfilter = usb_kqfilter
+#endif
 };
 
 static struct cdev* usb_dev = NULL;
@@ -505,6 +512,9 @@ usb_fifo_create(struct usb_cdev_privdata *cpd,
 		f-fifo_index = n + USB_FIFO_TX;
 		f-dev_ep_index = e;
 		f-priv_mtx = udev-device_mtx;
+#if 1
+		knlist_init_mtx(f-selinfo.si_note, f-priv_mtx);
+#endif
 		f-priv_sc0 = ep;
 		f-methods = usb_ugen_methods;
 		f-iface_index = ep-iface_index;
@@ -532,6 +542,9 @@ usb_fifo_create(struct usb_cdev_privdata *cpd,
 		f-fifo_index = n + USB_FIFO_RX;
 		f-dev_ep_index = e;
 		f-priv_mtx = udev-device_mtx;
+#if 1
+		knlist_init_mtx(f-selinfo.si_note, f-priv_mtx);
+#endif
 		f-priv_sc0 = ep;
 		f-methods = usb_ugen_methods;
 		f-iface_index = ep-iface_index;
@@ -712,6 +725,11 @@ usb_fifo_open(struct usb_cdev_privdata *cpd,
 	/* reset select flag */
 	f-flag_isselect = 0;
 
+#if 1
+	/* reset kevent flag */
+	f-flag_iskevent = 0;
+#endif
+
 	/* reset flushing flag */
 	f-flag_flushing = 0;
 
@@ -772,6 +790,13 @@ usb_fifo_close(struct usb_fifo *f, int fflags)
 	/* clear current cdev private data pointer */
 	f-curr_cpd = NULL;
 
+#if 1
+	/* check if we are watched by kevent */
+	if (f-flag_iskevent) {
+		KNOTE_LOCKED(f-selinfo.si_note, 0);
+		f-flag_iskevent = 0;
+	}
+#endif
 	/* check if we are selected */
 	if (f-flag_isselect) {
 		selwakeup(f-selinfo);
@@ -1113,6 +1138,179 @@ done:
 	return (err);
 }
 
+#if 1
+static void
+usb_filter_detach(struct knote *kn)
+{
+	struct usb_fifo *f = kn-kn_hook;
+	knlist_remove(f-selinfo.si_note, kn, 0);
+}
+
+static int
+usb_filter_write(struct knote *kn, long hint)
+{
+	struct usb_cdev_privdata* cpd;
+	struct usb_fifo *f;
+	struct usb_mbuf *m;
+	int is_usbfs = 0;
+
+	f = kn-kn_hook;
+	cpd = f-curr_cpd;
+	if (cpd == NULL) {
+		return (1);
+	}
+
+	if (f-fs_ep_max != 0) {
+		is_usbfs = 1;
+	}
+
+	if (!is_usbfs) {
+		if (f-flag_iserror) {
+			/* we got an error */
+			m = (void *)1;
+		} else {
+			if (f-queue_data == NULL) {
+/*
+ * start write transfer, if not
+ * already started
+ */
+(f-methods-f_start_write) (f);
+			}
+			/* check if any packets are available */
+			USB_IF_POLL(f-free_q, m);
+		}
+	} else {
+		if (f-flag_iscomplete) {
+			m = (void *)1;
+		} else {
+			m = NULL;
+		}
+	}
+
+	if (m) {
+		return (1);
+	} else {
+		return (0);
+	}
+}
+
+static int
+usb_filter_read(struct knote *kn, long hint)
+{
+	struct usb_cdev_privdata* cpd;
+	struct usb_fifo *f;
+	struct usb_mbuf *m;
+	int is_usbfs = 0;
+
+	f = kn-kn_hook;
+	cpd = f-curr_cpd;
+	if (cpd == NULL) {
+		return (1);
+	}
+
+	if (f-fs_ep_max != 0) {
+		is_usbfs = 1;
+	}
+
+	if (!is_usbfs) {
+		if (f-flag_iserror) {
+			/* we have and error */
+			m = (void *)1;
+		} else {
+			if (f-queue_data == NULL) {
+/*
+ * start read transfer, if not
+ * already started
+ */
+(f-methods-f_start_read) (f);
+			}
+			/* check if any packets are available */
+			USB_IF_POLL(f-used_q, m);
+		}
+	} else {
+		if (f-flag_iscomplete) {
+			m = (void *)1;
+		} else {
+			m = NULL;
+		}
+	}
+
+	if (m) {
+		return (1);
+	} else {
+		if (!is_usbfs) {
+			/* start reading data */
+			(f-methods-f_start_read) (f);
+		}
+		return (0);
+	}
+}
+
+static struct filterops usb_filtops_write =
+{
+	.f_isfd = 1,
+	.f_detach = usb_filter_detach,
+	.f_event = usb_filter_write,
+};
+
+static struct filterops usb_filtops_read =
+{
+	.f_isfd = 1,
+	.f_detach = usb_filter_detach,
+	.f_event = usb_filter_read,
+};
+
+
+/* ARGSUSED */
+static int
+usb_kqfilter(struct cdev* dev, struct knote *kn)
+{
+	struct usb_cdev_refdata refs;
+	struct usb_cdev_privdata* cpd;
+	struct usb_fifo *f;
+	int fflags;
+	int err = EINVAL;
+
+	if (devfs_get_cdevpriv((void **)cpd) != 0 ||
+	usb_ref_device(cpd, refs, 0) != 0)
+		return (ENXIO);
+
+	fflags = cpd-fflags;
+
+	/* Figure out who needs service */
+	switch (kn-kn_filter) {
+	case EVFILT_WRITE:
+		if (fflags  FWRITE) {
+			f = refs.txfifo;
+			kn-kn_fop = usb_filtops_write;
+			err = 0;
+		}
+		break;
+	case EVFILT_READ:
+		if (fflags  FREAD) {
+			f = refs.rxfifo;
+			kn-kn_fop = usb_filtops_read;
+			err = 0;
+		}
+		break;
+	default:
+		err = EOPNOTSUPP;
+		break;
+	}
+
+	if (err == 0) {
+		kn-kn_hook = f;
+		mtx_lock(f-priv_mtx);
+		knlist_add(f-selinfo.si_note, kn, 1);
+		f-flag_iskevent = 1;
+		mtx_unlock(f-priv_mtx);
+	}
+
+	usb_unref_device(cpd, refs);
+	return (err);
+}
+#endif
+
 /* ARGSUSED */
 static int
 usb_poll

kqueue for KBD.

2014-02-26 Thread Kohji Okuno
Hi,

I tried add kqueue I/F to kbd.c. I attached my patch.
What do you think about my patch?

Best regards,
 Kohji Okuno
diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c
index 8036762..df000ab 100644
--- a/sys/dev/kbd/kbd.c
+++ b/sys/dev/kbd/kbd.c
@@ -59,6 +59,9 @@ typedef struct genkbd_softc {
 	char		gkb_q[KB_QSIZE];		/* input queue */
 	unsigned int	gkb_q_start;
 	unsigned int	gkb_q_length;
+#if 1
+	unsigned int	gkb_index;
+#endif
 } genkbd_softc_t;
 
 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
@@ -472,6 +475,9 @@ static d_read_t		genkbdread;
 static d_write_t	genkbdwrite;
 static d_ioctl_t	genkbdioctl;
 static d_poll_t		genkbdpoll;
+#if 1
+static d_kqfilter_t	genkbdkqfilter;
+#endif
 
 
 static struct cdevsw kbd_cdevsw = {
@@ -483,6 +489,9 @@ static struct cdevsw kbd_cdevsw = {
 	.d_write =	genkbdwrite,
 	.d_ioctl =	genkbdioctl,
 	.d_poll =	genkbdpoll,
+#if 1
+	.d_kqfilter =	genkbdkqfilter,
+#endif
 	.d_name =	kbd,
 };
 
@@ -500,6 +509,13 @@ kbd_attach(keyboard_t *kbd)
 	make_dev_alias(kbd-kb_dev, kbd%r, kbd-kb_index);
 	kbd-kb_dev-si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
 	M_WAITOK | M_ZERO);
+#if 1
+	{
+		genkbd_softc_t *sc = kbd-kb_dev-si_drv1;
+		sc-gkb_index = KBD_INDEX(kbd-kb_dev);
+		knlist_init_mtx(sc-gkb_rsel.si_note, NULL);
+	}
+#endif
 	printf(kbd%d at %s%d\n, kbd-kb_index, kbd-kb_name, kbd-kb_unit);
 	return (0);
 }
@@ -697,6 +713,73 @@ genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *
 	return (error);
 }
 
+#if 1
+static void
+genkbd_kqops_detach(struct knote *kn)
+{
+	genkbd_softc_t *sc;
+	sc = kn-kn_hook;
+	knlist_remove(sc-gkb_rsel.si_note, kn, 0);
+}
+
+static int
+genkbd_kqops_event(struct knote *kn, long hint)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+
+	sc = kn-kn_hook;
+	kbd = kbd_get_keyboard(sc-gkb_index);
+
+	if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		return 1;	/* the keyboard has gone */
+	}
+	else {
+		if (sc-gkb_q_length  0)
+			return 1;
+		else
+			return 0;
+	}
+
+}
+static struct filterops genkbd_kqops =
+{
+	.f_isfd		= 1,
+	.f_attach	= NULL,
+	.f_detach	= genkbd_kqops_detach,
+	.f_event	= genkbd_kqops_event,
+};
+static int
+genkbdkqfilter(struct cdev *dev, struct knote *kn)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+	int error = 0;
+	int s;
+
+	s = spltty();
+	sc = dev-si_drv1;
+	kbd = kbd_get_keyboard(KBD_INDEX(dev));
+	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		error = EIO;
+	}
+	else  {
+		switch (kn-kn_filter) {
+		case EVFILT_READ:
+			kn-kn_fop = genkbd_kqops;
+			kn-kn_hook = (void *)sc;
+			knlist_add(sc-gkb_rsel.si_note, kn, 0);
+			break;
+		default:
+			error = EOPNOTSUPP;
+			break;
+		}
+	}
+	splx(s);
+	return (error);
+}
+#endif
+
 static int
 genkbdpoll(struct cdev *dev, int events, struct thread *td)
 {
@@ -744,6 +827,9 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(sc-gkb_rsel, PZERO);
+#if 1
+		knlist_clear(sc-gkb_rsel.si_note, 0);
+#endif
 		return (0);
 	default:
 		return (EINVAL);
@@ -814,6 +900,9 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(sc-gkb_rsel, PZERO);
+#if 1
+		KNOTE_UNLOCKED(sc-gkb_rsel.si_note, 0);
+#endif
 	}
 
 	return (0);
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

kqueue for KBD.

2014-02-26 Thread Kohji Okuno
Hi,

I tried to add kqueue I/F to kbd.c. I attached patch.
What do you think about my patch?

Best regards,
 Kohji Okuno
diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c
index 8036762..df000ab 100644
--- a/sys/dev/kbd/kbd.c
+++ b/sys/dev/kbd/kbd.c
@@ -59,6 +59,9 @@ typedef struct genkbd_softc {
 	char		gkb_q[KB_QSIZE];		/* input queue */
 	unsigned int	gkb_q_start;
 	unsigned int	gkb_q_length;
+#if 1
+	unsigned int	gkb_index;
+#endif
 } genkbd_softc_t;
 
 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
@@ -472,6 +475,9 @@ static d_read_t		genkbdread;
 static d_write_t	genkbdwrite;
 static d_ioctl_t	genkbdioctl;
 static d_poll_t		genkbdpoll;
+#if 1
+static d_kqfilter_t	genkbdkqfilter;
+#endif
 
 
 static struct cdevsw kbd_cdevsw = {
@@ -483,6 +489,9 @@ static struct cdevsw kbd_cdevsw = {
 	.d_write =	genkbdwrite,
 	.d_ioctl =	genkbdioctl,
 	.d_poll =	genkbdpoll,
+#if 1
+	.d_kqfilter =	genkbdkqfilter,
+#endif
 	.d_name =	kbd,
 };
 
@@ -500,6 +509,13 @@ kbd_attach(keyboard_t *kbd)
 	make_dev_alias(kbd-kb_dev, kbd%r, kbd-kb_index);
 	kbd-kb_dev-si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
 	M_WAITOK | M_ZERO);
+#if 1
+	{
+		genkbd_softc_t *sc = kbd-kb_dev-si_drv1;
+		sc-gkb_index = KBD_INDEX(kbd-kb_dev);
+		knlist_init_mtx(sc-gkb_rsel.si_note, NULL);
+	}
+#endif
 	printf(kbd%d at %s%d\n, kbd-kb_index, kbd-kb_name, kbd-kb_unit);
 	return (0);
 }
@@ -697,6 +713,73 @@ genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *
 	return (error);
 }
 
+#if 1
+static void
+genkbd_kqops_detach(struct knote *kn)
+{
+	genkbd_softc_t *sc;
+	sc = kn-kn_hook;
+	knlist_remove(sc-gkb_rsel.si_note, kn, 0);
+}
+
+static int
+genkbd_kqops_event(struct knote *kn, long hint)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+
+	sc = kn-kn_hook;
+	kbd = kbd_get_keyboard(sc-gkb_index);
+
+	if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		return 1;	/* the keyboard has gone */
+	}
+	else {
+		if (sc-gkb_q_length  0)
+			return 1;
+		else
+			return 0;
+	}
+
+}
+static struct filterops genkbd_kqops =
+{
+	.f_isfd		= 1,
+	.f_attach	= NULL,
+	.f_detach	= genkbd_kqops_detach,
+	.f_event	= genkbd_kqops_event,
+};
+static int
+genkbdkqfilter(struct cdev *dev, struct knote *kn)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+	int error = 0;
+	int s;
+
+	s = spltty();
+	sc = dev-si_drv1;
+	kbd = kbd_get_keyboard(KBD_INDEX(dev));
+	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		error = EIO;
+	}
+	else  {
+		switch (kn-kn_filter) {
+		case EVFILT_READ:
+			kn-kn_fop = genkbd_kqops;
+			kn-kn_hook = (void *)sc;
+			knlist_add(sc-gkb_rsel.si_note, kn, 0);
+			break;
+		default:
+			error = EOPNOTSUPP;
+			break;
+		}
+	}
+	splx(s);
+	return (error);
+}
+#endif
+
 static int
 genkbdpoll(struct cdev *dev, int events, struct thread *td)
 {
@@ -744,6 +827,9 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(sc-gkb_rsel, PZERO);
+#if 1
+		knlist_clear(sc-gkb_rsel.si_note, 0);
+#endif
 		return (0);
 	default:
 		return (EINVAL);
@@ -814,6 +900,9 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(sc-gkb_rsel, PZERO);
+#if 1
+		KNOTE_UNLOCKED(sc-gkb_rsel.si_note, 0);
+#endif
 	}
 
 	return (0);
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: kqueue for usb_dev

2014-02-26 Thread Kohji Okuno
Hi John-Mark,

I tested the attached sample source with USB mouse.

Thanks,
 Kohji Okuno

From: John-Mark Gurney j...@funkthat.com
 Kohji Okuno wrote this message on Thu, Feb 27, 2014 at 14:26 +0900:
 I tried add kqueue I/F to usb_dev.c. I attached my patch.
 What do you think about my patch?
 
 Do you have test cases for these patches?
 
 -- 
   John-Mark GurneyVoice: +1 415 225 5579
 
  All that I will do, has been done, All that I have, has not.
#include stdio.h
#include stdlib.h
#include stdint.h
#include sys/types.h
#include sys/event.h
#include sys/select.h
#include sys/time.h
#include unistd.h
#include fcntl.h
#include errno.h

#define DEV /dev/ums0

#if 0
int
main()
{
int i;
ssize_t ret;
uint8_t buf[128];
int fd = open(DEV, O_RDONLY);
fd_set readfds;

for (i = 0; i  10; i++) {
FD_ZERO(readfds);
FD_SET(fd, readfds);
ret = select(fd+1, readfds, NULL, NULL, NULL);
printf(select=%d\n, ret);

ret = read(fd, buf, sizeof(buf));
printf(%d:%02x %02x %02x\n, ret, buf[0], buf[1], buf[2]);
}

close(fd);
exit(0);
}
#else
int
main()
{
int i;
int err;
ssize_t ret;
uint8_t buf[128];
int fd = open(DEV, O_RDONLY);
int kqfd = kqueue();
struct kevent evlist[1];

EV_SET(evlist[0], fd, EVFILT_READ, EV_ADD, 0, 0, 0);
err = kevent(kqfd, evlist, 1, 0, 0, 0);
if (err) {
perror(kevent);
close(fd);
close(kqfd);
exit(1);
}

for (i = 0; i  10; i++) {
ret = kevent(kqfd, 0, 0, evlist, 1, 0);
printf(kev=%d\n, ret);

ret = read(fd, buf, sizeof(buf));
printf(%d:%02x %02x %02x\n, ret, buf[0], buf[1], buf[2]);
}

close(fd);
exit(0);
}
#endif
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: kqueue for usb_dev

2014-02-26 Thread Kohji Okuno
Hi John-Mark,

Thank you for you comment.

From: John-Mark Gurney j...@funkthat.com
 Kohji Okuno wrote this message on Thu, Feb 27, 2014 at 14:26 +0900:
 I tried add kqueue I/F to usb_dev.c. I attached my patch.
 What do you think about my patch?
 
 A few comments...
 
 1) You should just drop the use of flag_iskevent and just
 unconditionally call KNOTE... since you have the lock already held,
 the cost is minimal (and w/ modern branch prediction, may be cheaper)...

Should we set the use of flag_iskevent, when usb_filter_read() and
usb_filter_write() return `0'?


 2) Why do you try to start read/write transfers in the _filter?  You
 should just check to see if data is available and not do work..  This
 is also important since kqueue calls the filter just before delivering
 the knote to userland to verify that there is still data, and it will
 call your _event function for each knote on the fd...  The work should
 be started through other mechanisms, like read/write syscall or
 interrupt or timeout/callout...  If it's required to get results from
 USB_IF_POLL, then it's fine..

I copied from usb_poll().
Should we try to start read/write transfers in usb_kqfilter()?
Or should not we try to start read/write transfers in poll and kqueue?

 3) I don't see any calls to knlist_destroy... These calls are needed
 to clean up the knlist...

I understood.

 Obviously the #if 1's will need to go...
 
 Also, I don't think your change is against HEAD..  The line numbers
 in my version of usb_dev.c are different...

I'm sorry.

Many thanks,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: kqueue for usb_dev

2014-02-26 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
 On 02/27/14 08:13, Kohji Okuno wrote:
 Hi John-Mark,

 Thank you for you comment.

 From: John-Mark Gurney j...@funkthat.com
 Kohji Okuno wrote this message on Thu, Feb 27, 2014 at 14:26 +0900:
 I tried add kqueue I/F to usb_dev.c. I attached my patch.
 What do you think about my patch?

 A few comments...

 1) You should just drop the use of flag_iskevent and just
 unconditionally call KNOTE... since you have the lock already held,
 the cost is minimal (and w/ modern branch prediction, may be cheaper)...

 Should we set the use of flag_iskevent, when usb_filter_read() and
 usb_filter_write() return `0'?


 2) Why do you try to start read/write transfers in the _filter?  You
 should just check to see if data is available and not do work..  This
 is also important since kqueue calls the filter just before delivering
 the knote to userland to verify that there is still data, and it will
 call your _event function for each knote on the fd...  The work should
 be started through other mechanisms, like read/write syscall or
 interrupt or timeout/callout...  If it's required to get results from
 USB_IF_POLL, then it's fine..

 I copied from usb_poll().
 Should we try to start read/write transfers in usb_kqfilter()?
 Or should not we try to start read/write transfers in poll and kqueue?

 3) I don't see any calls to knlist_destroy... These calls are needed
 to clean up the knlist...

 I understood.

 Obviously the #if 1's will need to go...

 Also, I don't think your change is against HEAD..  The line numbers
 in my version of usb_dev.c are different...

 I'm sorry.
 
 
 Hi,
 
 I've found two bugs:
 
 1)
 
 
 +#if 1
 +   knlist_init_mtx(f_tx-selinfo.si_note, f_rx-priv_mtx);
 +#endif
 
 Should be:
 
 +#if 1
 +   knlist_init_mtx(f_tx-selinfo.si_note, f_tx-priv_mtx);
 +#endif
 
 
 2)
 
 Event filters need to lock the FIFO's mutex.
 
 BTW: I'm working on getting the code into -HEAD. I'll run some test before it
 goes in.

Hi,

Thank you for you comment.
1) You are right. 

2) I think that priv_mtx is hold in caller function.
   Would you refer to kqueue_scan() in kern/kern_event.c?

Thanks,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: spec violation of xHCI?

2013-12-16 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
Date: Mon, 16 Dec 2013 11:53:31 +0100
 Hi Kohji,
 
 A regression issue has been reported when using the CHAIN-BIT patch. Can you
 verify this additional patch on you hardware and report back?
 
 http://svnweb.freebsd.org/changeset/base/259462
 
 Thank you!
 
 --HPS

Hi HPS,

Thank you for informing your commit.
I tried your latest patch. It is OK in my environment.

Many thanks,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: spec violation of xHCI?

2013-12-12 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
Date: Thu, 12 Dec 2013 09:37:29 +0100
 On 12/12/13 08:40, Kohji Okuno wrote:
 From: Hans Petter Selasky h...@bitfrost.no

 Hi HPS,

 The endpoint type is BULK, and the direction is OUT.

 I checked by using a USB analyzer.  When I did not set CHAIN bit in
 LINK TRB, my host controller sent illegal packets sometimes.
 But, ZLPs were sent.

 
 Hi,
 
 Test OK here aswell.
 
 Does this commit look OK to you:
 
 http://svnweb.freebsd.org/changeset/base/259248

Hi HPS,

I confirmed that your commit is OK.

Many thanks,
 Kohji Okuno.
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


spec violation of xHCI?

2013-12-11 Thread Kohji Okuno
Hi,

I think the xHCI host controller driver has a spec violation.

Could you refer to 
``Table 126: Offset 0Ch – Link TRB Field Definitions''
in  xHCI_Specification_for_USB.pdf(Revision 1.0)?

The following is an excerpt about the CHAIN ​​BIT.

  Chain bit (CH). Set to ‘1’ by software to associate this TRB with
  the next TRB on the Ring. A Transfer Descriptor (TD) is defined as
  one or more TRBs. The Chain bit is used to identify the TRBs that
  comprise a TD. Refer to section 4.11.7 for more information on Link
  TRB placement within a TD. On a Command Ring this bit is ignored by
  the xHC.


I think that we should add XHCI_TRB_3_CHAIN_BIT to line 1895.
How do you think?


src/sys/dev/usb/controller/xhci.c:
1879/* fill out link TRB */
1880
1881if (td_next != NULL) {
1882/* link the current TD with the next one */
1883td-td_trb[x].qwTrb0 = 
htole64((uint64_t)td_next-td_self);
1884DPRINTF(LINK=0x%08llx\n, (long 
long)td_next-td_self);
1885} else {
1886/* this field will get updated later */
1887DPRINTF(NOLINK\n);
1888}
1889
1890dword = XHCI_TRB_2_IRQ_SET(0);
1891
1892td-td_trb[x].dwTrb2 = htole32(dword);
1893
1894dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
1895XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT;
1896
1897td-td_trb[x].dwTrb3 = htole32(dword);
1898
1899td-alt_next = td_alt_next;

--
Best regards,
 Kohji Okuno

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: spec violation of xHCI?

2013-12-11 Thread Kohji Okuno
 On 12/11/13 11:12, Kohji Okuno wrote:
 Hi,

 I think the xHCI host controller driver has a spec violation.

 Could you refer to
 ``Table 126: Offset 0Ch – Link TRB Field Definitions''
 in  xHCI_Specification_for_USB.pdf(Revision 1.0)?

 The following is an excerpt about the CHAIN ​​BIT.

Chain bit (CH). Set to ‘1’ by software to associate this TRB with
the next TRB on the Ring. A Transfer Descriptor (TD) is defined as
one or more TRBs. The Chain bit is used to identify the TRBs that
comprise a TD. Refer to section 4.11.7 for more information on Link
TRB placement within a TD. On a Command Ring this bit is ignored by
the xHC.


 I think that we should add XHCI_TRB_3_CHAIN_BIT to line 1895.
 How do you think?

 
 Hi Kohji,
 
 The double word written at line 1895 does not set the chain bit because this
 is the end of a transfer descriptor, TD. I'm unsure how hardware interprets
 this bit, if setting the bit on the previous TRB makes the next one connect to
 the previous one, or the other way around. If setting this bit makes the TRB
 connect to the previous one, you are correct. Else the current code is
 correct.

Hi, HPS,

Thank you for your comment.

I think that this (line 1895) is not the end of a transfer descriptor.
When the device driver needs a Zero Length Packet, this is not the
end. And, If xfer has nframes, this is not the end, too.

Regards,
 Kohji Okuno


 src/sys/dev/usb/controller/xhci.c:
 1879 /* fill out link TRB */
 1880 
 1881 if (td_next != NULL) {
 1882 /* link the current TD with the next one */
 1883 td-td_trb[x].qwTrb0 = htole64((uint64_t)td_next-td_self);
 1884 DPRINTF(LINK=0x%08llx\n, (long long)td_next-td_self);
 1885 } else {
 1886 /* this field will get updated later */
 1887 DPRINTF(NOLINK\n);
 1888 }
 1889 
 1890 dword = XHCI_TRB_2_IRQ_SET(0);
 1891 
 1892 td-td_trb[x].dwTrb2 = htole32(dword);
 1893 
 1894 dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
 1895 XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT;
 1896 
 1897 td-td_trb[x].dwTrb3 = htole32(dword);
 1898 
 1899 td-alt_next = td_alt_next;

 --
 Best regards,
   Kohji Okuno

 ___
 freebsd-...@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-usb
 To unsubscribe, send any mail to freebsd-usb-unsubscr...@freebsd.org

 
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: spec violation of xHCI?

2013-12-11 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
Date: Wed, 11 Dec 2013 13:44:37 +0100

 On 12/11/13 12:12, Kohji Okuno wrote:
 On 12/11/13 11:12, Kohji Okuno wrote:
 Hi,

 I think the xHCI host controller driver has a spec violation.

 Could you refer to
 ``Table 126: Offset 0Ch – Link TRB Field Definitions''
 in  xHCI_Specification_for_USB.pdf(Revision 1.0)?

 The following is an excerpt about the CHAIN ​​BIT.

 Chain bit (CH). Set to ‘1’ by software to associate this TRB with
 the next TRB on the Ring. A Transfer Descriptor (TD) is defined as
 one or more TRBs. The Chain bit is used to identify the TRBs that
 comprise a TD. Refer to section 4.11.7 for more information on Link
 TRB placement within a TD. On a Command Ring this bit is ignored by
 the xHC.


 I think that we should add XHCI_TRB_3_CHAIN_BIT to line 1895.
 How do you think?


 Hi Kohji,

 The double word written at line 1895 does not set the chain bit because
 this
 is the end of a transfer descriptor, TD. I'm unsure how hardware interprets
 this bit, if setting the bit on the previous TRB makes the next one connect
 to
 the previous one, or the other way around. If setting this bit makes the
 TRB
 connect to the previous one, you are correct. Else the current code is
 correct.

 Hi, HPS,

 Thank you for your comment.

 I think that this (line 1895) is not the end of a transfer descriptor.
 When the device driver needs a Zero Length Packet, this is not the
 end. And, If xfer has nframes, this is not the end, too.

 Regards,
   Kohji Okuno

 
 Hi Kohji,
 
 Yes, you are right that if nframes is greater than one, and/or if a ZLP needs
 to be sent this is not the end of the USB transfers. Are we sure that if the
 XHCI_TRB_3_CHAIN_BIT is added at line 1895, that we will receive a completion
 TRB-event for each of the nframes, or will the chain bit result in loss of TRB
 completion events?
 
 Does setting this bit have any impact on performance?
 
 Thank you!

 --HPS

Hi HPS,

I don't know about any impact on performance.
But, in linux, link trb has CHAIN BIT if necessary, I think.

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: spec violation of xHCI?

2013-12-11 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
Date: Wed, 11 Dec 2013 13:50:50 +0100
 On 12/11/13 13:44, Hans Petter Selasky wrote:
 On 12/11/13 12:12, Kohji Okuno wrote:
 On 12/11/13 11:12, Kohji Okuno wrote:
 Hi,

 I think the xHCI host controller driver has a spec violation.

 Could you refer to
 ``Table 126: Offset 0Ch – Link TRB Field Definitions''
 in  xHCI_Specification_for_USB.pdf(Revision 1.0)?

 The following is an excerpt about the CHAIN ​​BIT.

 Chain bit (CH). Set to ‘1’ by software to associate this TRB with
 the next TRB on the Ring. A Transfer Descriptor (TD) is defined as
 one or more TRBs. The Chain bit is used to identify the TRBs that
 comprise a TD. Refer to section 4.11.7 for more information on Link
 TRB placement within a TD. On a Command Ring this bit is ignored by
 the xHC.


 I think that we should add XHCI_TRB_3_CHAIN_BIT to line 1895.
 How do you think?


 Hi Kohji,

 The double word written at line 1895 does not set the chain bit
 because this
 is the end of a transfer descriptor, TD. I'm unsure how hardware
 interprets
 this bit, if setting the bit on the previous TRB makes the next one
 connect to
 the previous one, or the other way around. If setting this bit makes
 the TRB
 connect to the previous one, you are correct. Else the current code is
 correct.

 Hi, HPS,

 Thank you for your comment.

 I think that this (line 1895) is not the end of a transfer descriptor.
 When the device driver needs a Zero Length Packet, this is not the
 end. And, If xfer has nframes, this is not the end, too.

 Regards,
   Kohji Okuno


 Hi Kohji,

 Yes, you are right that if nframes is greater than one, and/or if a ZLP
 needs to be sent this is not the end of the USB transfers. Are we sure
 that if the XHCI_TRB_3_CHAIN_BIT is added at line 1895, that we will
 receive a completion TRB-event for each of the nframes, or will the
 chain bit result in loss of TRB completion events?

 Does setting this bit have any impact on performance?

 Thank you!

 --HPS
 
 Some more thoughts:
 
 The code in question handle all four USB transfer types. Are you saying that
 the CHAIN bit should be set for isochronous transfers too, so all the packets
 send in all the intervals are chained together? Or is this only for BULK
 traffic you want to add the CHAIN bit?
 
 Thank you!
 
 --HPS

Hi HPS,

All link trbs which are not the end need CHAIN bit, I think.
But, this is errata in xHCI ver 0.95. So, linux has quirk for chain
bit. Could you check linux codes?

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: spec violation of xHCI?

2013-12-11 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
Date: Wed, 11 Dec 2013 15:04:42 +0100
 On 12/11/13 14:06, Kohji Okuno wrote:

 Hi HPS,

 All link trbs which are not the end need CHAIN bit, I think.
 But, this is errata in xHCI ver 0.95. So, linux has quirk for chain
 bit. Could you check linux codes?

 Regards,
   Kohji Okuno
 
 Hi Kohji,
 
 I went through the Linux codes a bit, and I see they have some quirks for the
 chaining bit. Unfortunately Linux does the queuing quite differently than in
 FreeBSD and Shara Sharp which is the author of that code, stated recently a
 need for rewrite of the TRB/TD stuff in Linux, so I'm not sure if that means
 there are more bugs in there or not. Let me explain a bit how things work in
 FreeBSD and why I did not put the chaining bit in line 1895 which you suggest.
 
 In my design the chaining bit should not be set at line 1895, because if you
 receive a short packet and nframes  1, the XHCI should not go to the end of
 the frame list, but rather the next frame, nframes + 1.
 
 If the single short OK flag is set on a BULK transfer, yes, it would be
 correct to set the chaining bit here, but it is not required, because we are
 already are handling activation of the next frame in the function
 xhci_activate_transfer() and xhci_skip_transfer(). Transfer here means
 zero or more TRBs. We use the cycle bit on the TRB to single step the frames
 in software, although you are right that we might optimise this by setting the
 chaining bit instead for the BULK case so that we don't need software
 intervention to handle the job.
 
 If the multi short OK flag is set, multiple short terminated frames can be
 received and then the chaining bit should not be set.
 
 Are you seeing a real problem because of the chain bit not being set, or is
 this more the result of code review?
 
 Thank you for the interest in my XHCI driver.
 
 --HPS

Hi HPS,

Unfortunately, I can not explain in detail. But, I encountered a real
problem for ZLP. And, when I added CHAIN bit, this problem was
resolved.

When a device driver needs force_short(ZLP), your device driver
creates TRB in the followings.

NORMAL_TRB- LINK_TRB - NORMAL_TRB - LINK_TRB   = Kick DOORBELL
(with payload)   (#1)  (ZLP)(#2)

In this case, I think LINK_TRB #1 needs chain bit.

Regards,
 Kohji Okuno

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: spec violation of xHCI?

2013-12-11 Thread Kohji Okuno
From: Hans Petter Selasky h...@bitfrost.no
Date: Thu, 12 Dec 2013 08:15:02 +0100
 On 12/12/13 01:59, Kohji Okuno wrote:
 From: Hans Petter Selasky h...@bitfrost.no
 Date: Wed, 11 Dec 2013 15:04:42 +0100
 On 12/11/13 14:06, Kohji Okuno wrote:

 Hi HPS,

 All link trbs which are not the end need CHAIN bit, I think.
 But, this is errata in xHCI ver 0.95. So, linux has quirk for chain
 bit. Could you check linux codes?

 Regards,
Kohji Okuno

 Hi Kohji,

 I went through the Linux codes a bit, and I see they have some quirks for
 the
 chaining bit. Unfortunately Linux does the queuing quite differently than
 in
 FreeBSD and Shara Sharp which is the author of that code, stated recently a
 need for rewrite of the TRB/TD stuff in Linux, so I'm not sure if that
 means
 there are more bugs in there or not. Let me explain a bit how things work
 in
 FreeBSD and why I did not put the chaining bit in line 1895 which you
 suggest.

 In my design the chaining bit should not be set at line 1895, because if
 you
 receive a short packet and nframes  1, the XHCI should not go to the end
 of
 the frame list, but rather the next frame, nframes + 1.

 If the single short OK flag is set on a BULK transfer, yes, it would be
 correct to set the chaining bit here, but it is not required, because we
 are
 already are handling activation of the next frame in the function
 xhci_activate_transfer() and xhci_skip_transfer(). Transfer here means
 zero or more TRBs. We use the cycle bit on the TRB to single step the
 frames
 in software, although you are right that we might optimise this by setting
 the
 chaining bit instead for the BULK case so that we don't need software
 intervention to handle the job.

 If the multi short OK flag is set, multiple short terminated frames can be
 received and then the chaining bit should not be set.

 Are you seeing a real problem because of the chain bit not being set, or is
 this more the result of code review?

 Thank you for the interest in my XHCI driver.

 --HPS

 Hi HPS,

 Unfortunately, I can not explain in detail. But, I encountered a real
 problem for ZLP. And, when I added CHAIN bit, this problem was
 resolved.

 When a device driver needs force_short(ZLP), your device driver
 creates TRB in the followings.

 NORMAL_TRB- LINK_TRB - NORMAL_TRB - LINK_TRB   = Kick DOORBELL
 (with payload)   (#1)  (ZLP)(#2)

 In this case, I think LINK_TRB #1 needs chain bit.
 
 Hi Kohji,
 
 Did you check using a USB analyzer what the difference is when setting the
 CHAIN bit and not setting the chain bit?
 
 I would guess that if you set the CHAIN-bit in this case, no ZLP will be sent,
 because the TRB is associated with the previous one.
 
 What endpoint type is this? BULK/CONTROL/INTR/ISOC
 
 What direction is this? IN or OUT?
 
 --HPS

Hi HPS,

The endpoint type is BULK, and the direction is OUT.

I checked by using a USB analyzer.  When I did not set CHAIN bit in
LINK TRB, my host controller sent illegal packets sometimes. 
But, ZLPs were sent.

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Are pthread_setcancelstate() and pthread_setcanceltype() cancellation points?

2013-06-18 Thread Kohji Okuno
Hi,

I have a question.

Are pthread_setcancelstate() and pthread_setcanceltype() cancellation
points?

I refered to the following URL.

http://pubs.opengroup.org/onlinepubs/7908799/xsh/threads.html

This document shows that cancellation points in the pthread library
are only pthread_cond_timedwait(), pthread_cond_wait(), pthread_join()
and pthread_testcancel().

But, current implementation in FreeBSD is the following.
(Please take notice of (*) marks).

Would you check this?


lib/libthr/thread/thr_cancel.c:
77  int
78  _pthread_setcancelstate(int state, int *oldstate)
79  {
80  struct pthread *curthread = _get_curthread();
81  int oldval;
82  
83  oldval = curthread-cancel_enable;
84  switch (state) {
85  case PTHREAD_CANCEL_DISABLE:
86  curthread-cancel_enable = 0;
87  break;
88  case PTHREAD_CANCEL_ENABLE:
89  curthread-cancel_enable = 1;
90 (*)  testcancel(curthread);
91  break;
92  default:
93  return (EINVAL);
94  }
95  
96  if (oldstate) {
97  *oldstate = oldval ? PTHREAD_CANCEL_ENABLE :
98  PTHREAD_CANCEL_DISABLE;
99  }
100 return (0);
101 }
102 
103 int
104 _pthread_setcanceltype(int type, int *oldtype)
105 {
106 struct pthread  *curthread = _get_curthread();
107 int oldval;
108 
109 oldval = curthread-cancel_async;
110 switch (type) {
111 case PTHREAD_CANCEL_ASYNCHRONOUS:
112 curthread-cancel_async = 1;
113 (*) testcancel(curthread);
114 break;
115 case PTHREAD_CANCEL_DEFERRED:
116 curthread-cancel_async = 0;
117 break;
118 default:
119 return (EINVAL);
120 }
121 
122 if (oldtype) {
123 *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS :
124 PTHREAD_CANCEL_DEFERRED;
125 }
126 return (0);
127 }


Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Are pthread_setcancelstate() and pthread_setcanceltype() cancellation points?

2013-06-18 Thread Kohji Okuno
Hi,

This is newer document.

http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_05_02

 Hi,
 
 I have a question.
 
 Are pthread_setcancelstate() and pthread_setcanceltype() cancellation
 points?
 
 I refered to the following URL.
 
 http://pubs.opengroup.org/onlinepubs/7908799/xsh/threads.html
 
 This document shows that cancellation points in the pthread library
 are only pthread_cond_timedwait(), pthread_cond_wait(), pthread_join()
 and pthread_testcancel().
 
 But, current implementation in FreeBSD is the following.
 (Please take notice of (*) marks).
 
 Would you check this?
 
 
 lib/libthr/thread/thr_cancel.c:
 77int
 78_pthread_setcancelstate(int state, int *oldstate)
 79{
 80struct pthread *curthread = _get_curthread();
 81int oldval;
 82
 83oldval = curthread-cancel_enable;
 84switch (state) {
 85case PTHREAD_CANCEL_DISABLE:
 86curthread-cancel_enable = 0;
 87break;
 88case PTHREAD_CANCEL_ENABLE:
 89curthread-cancel_enable = 1;
 90 (*)testcancel(curthread);
 91break;
 92default:
 93return (EINVAL);
 94}
 95
 96if (oldstate) {
 97*oldstate = oldval ? PTHREAD_CANCEL_ENABLE :
 98PTHREAD_CANCEL_DISABLE;
 99}
 100   return (0);
 101   }
 102   
 103   int
 104   _pthread_setcanceltype(int type, int *oldtype)
 105   {
 106   struct pthread  *curthread = _get_curthread();
 107   int oldval;
 108   
 109   oldval = curthread-cancel_async;
 110   switch (type) {
 111   case PTHREAD_CANCEL_ASYNCHRONOUS:
 112   curthread-cancel_async = 1;
 113 (*)   testcancel(curthread);
 114   break;
 115   case PTHREAD_CANCEL_DEFERRED:
 116   curthread-cancel_async = 0;
 117   break;
 118   default:
 119   return (EINVAL);
 120   }
 121   
 122   if (oldtype) {
 123   *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS :
 124   PTHREAD_CANCEL_DEFERRED;
 125   }
 126   return (0);
 127   }
 
 
 Regards,
  Kohji Okuno
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Are pthread_setcancelstate() and pthread_setcanceltype() cancellation points?

2013-06-18 Thread Kohji Okuno
Hi, Konstantin,

Thank you for your prompt response.

 The reason for the testcancel() calls there is that async cancellation
 is defined as to be acted upon at any time after the cancellation is
 enabled.  If we have pending cancellation request, the async cancellation
 must proceed after the pthread_setcancelstate(PTHREAD_CANCEL_ENABLE).
 
 I see a bug there, namely, we should not process the cancellation if
 the type is deferred.  Is this is real issue you are concerned with ?

I think your change is right. 

I found this issue in my sample source. My sample source in
8.1-RELEASE worked good, but it caused dead lock in current, since
my_mutex did not release. This change was committed after 8.1-RELEASE.

void
my_cleanup(void *arg)
{
  int oldstate;
  pthread_mutex_lock(my_mutex);
  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, oldstate);
   ...

  pthread_setcancelstate(oldstate, NULL);
  pthread_mutex_unlock(my_mutex);

}

And I investigated about glibc. 
In glibc, if PTHREAD_CANCEL_ENABLE  ASYNCHRONOUS then __do_cancel()
is executed in pthread_setcancelstate().


glibc-2.17/nptl/pthread_setcancelstate.c:
 24 int
 25 __pthread_setcancelstate (state, oldstate)
 26  int state;
 27  int *oldstate;
 28 {
 29   volatile struct pthread *self;
 30 
 31   if (state  PTHREAD_CANCEL_ENABLE || state  PTHREAD_CANCEL_DISABLE)
 32 return EINVAL;
 33 
 34   self = THREAD_SELF;
 35 
 36   int oldval = THREAD_GETMEM (self, cancelhandling);
 37   while (1)
 38 {
 39   int newval = (state == PTHREAD_CANCEL_DISABLE
 40 ? oldval | CANCELSTATE_BITMASK
 41 : oldval  ~CANCELSTATE_BITMASK);
 42 
 43   /* Store the old value.  */
 44   if (oldstate != NULL)
 45 *oldstate = ((oldval  CANCELSTATE_BITMASK)
 46  ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
 47 
 48   /* Avoid doing unnecessary work.  The atomic operation can
 49  potentially be expensive if the memory has to be locked and
 50  remote cache lines have to be invalidated.  */
 51   if (oldval == newval)
 52 break;
 53 
 54   /* Update the cancel handling word.  This has to be done
 55  atomically since other bits could be modified as well.  */
 56   int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
 57   oldval);
 58   if (__builtin_expect (curval == oldval, 1))
 59 {
 60   if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
 61 __do_cancel ();
 62 
 63   break;
 64 }
 65 
 66   /* Prepare for the next round.  */
 67   oldval = curval;
 68 }
 69 
 70   return 0;
 71 }


Many thanks,
 Kohji Okuno

 On Tue, Jun 18, 2013 at 06:15:56PM +0900, Kohji Okuno wrote:
 Hi,
 
 This is newer document.
 
 http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_05_02
 
  Hi,
  
  I have a question.
  
  Are pthread_setcancelstate() and pthread_setcanceltype() cancellation
  points?
  
  I refered to the following URL.
  
  http://pubs.opengroup.org/onlinepubs/7908799/xsh/threads.html
  
  This document shows that cancellation points in the pthread library
  are only pthread_cond_timedwait(), pthread_cond_wait(), pthread_join()
  and pthread_testcancel().
  
  But, current implementation in FreeBSD is the following.
  (Please take notice of (*) marks).
  
  Would you check this?
 The reason for the testcancel() calls there is that async cancellation
 is defined as to be acted upon at any time after the cancellation is
 enabled.  If we have pending cancellation request, the async cancellation
 must proceed after the pthread_setcancelstate(PTHREAD_CANCEL_ENABLE).
 
 I see a bug there, namely, we should not process the cancellation if
 the type is deferred.  Is this is real issue you are concerned with ?
 
 diff --git a/lib/libthr/thread/thr_cancel.c b/lib/libthr/thread/thr_cancel.c
 index 89f0ee1..beae707 100644
 --- a/lib/libthr/thread/thr_cancel.c
 +++ b/lib/libthr/thread/thr_cancel.c
 @@ -87,7 +87,8 @@ _pthread_setcancelstate(int state, int *oldstate)
   break;
   case PTHREAD_CANCEL_ENABLE:
   curthread-cancel_enable = 1;
 - testcancel(curthread);
 + if (curthread-cancel_async)
 + testcancel(curthread);
   break;
   default:
   return (EINVAL);
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: deadlock between g_event and a thread on removing a device.

2013-01-23 Thread Kohji Okuno
Hi Konstantin,

Thank you for your comment.

I don't have any solution for this issue.
And when a device is removed suddenly, there are other problems, I think.


 On Fri, Jan 18, 2013 at 02:45:38PM +0900, Kohji Okuno wrote:
 Hi,
 
 When I removed a device (ex. /dev/da0), I have encounterd a
 dead-lock between ``g_event'' thread and a thread that is opening
 device file (I call this thread as A).
 
 Would you refer the following?
 
 When the device is removed between dev_refthread() and g_dev_open(),
 thread A incremented dev-si_threadcount, but can't acquire
 topology_lock.
 
 On the other hand, g_event is waiting to set dev-si_threadcount to 0
 with topology_lock.
 
 Regards,
  Kohji Okuno
 
 
  Thread A 
 ...
 devfs_open()
 {
   ...
   dsw = dev_refthread(dev, ref); = increment dev-si_threadcount
   ...
   error = dsw-d_open(...);   = call g_dev_open()
   ...
   dev_relthread(dev, ref);= decrement dev-si_threadcount
 }
 
 g_dev_open()
 {
   ...
   g_topology_lock();  = Thread A couldn't acquire 
   ...topology_lock.
 }
 
  g_event 
 g_run_events()
 {
...
g_topology_lock(); = g_event acuired topology_lock here.
...
one_event()
...
 }
 
 one_event()
 g_orphan_register()
 g_dev_orphan()
 destroy_dev()
 destroy_dev()
 destroy_devl()
 {
   ...
   while (dev-si_threadcount != 0) { = this count was incremented by Thread 
 A
 /* Use unique dummy wait ident */
 msleep(csw, devmtx, PRIBIO, devdrn, hz / 10);
   }
   ...
 }
 
 Yes, you are absolutely right.
 
 I believe there were some patches floating around which changed the
 destroy_dev() call in the g_dev_orphan() to destroy_dev_sched(). I do
 not remember who was the author.
 
 My reply was that naive substitution of the destroy_dev() to
 destroy_dev_sched() is racy, because some requests might still come
 in after the call to destroy_dev_sched(). Despite destroy_dev_sched()
 setting the CDP_SCHED_DTR flag on the devfs node, some thread might
 already entered the cdevsw method. I do not believe that there was
 further progress there.
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


deadlock between g_event and a thread on removing a device.

2013-01-17 Thread Kohji Okuno
Hi,

When I removed a device (ex. /dev/da0), I have encounterd a
dead-lock between ``g_event'' thread and a thread that is opening
device file (I call this thread as A).

Would you refer the following?

When the device is removed between dev_refthread() and g_dev_open(),
thread A incremented dev-si_threadcount, but can't acquire
topology_lock.

On the other hand, g_event is waiting to set dev-si_threadcount to 0
with topology_lock.

Regards,
 Kohji Okuno


 Thread A 
...
devfs_open()
{
  ...
  dsw = dev_refthread(dev, ref); = increment dev-si_threadcount
  ...
  error = dsw-d_open(...);   = call g_dev_open()
  ...
  dev_relthread(dev, ref);= decrement dev-si_threadcount
}

g_dev_open()
{
  ...
  g_topology_lock();  = Thread A couldn't acquire 
  ...topology_lock.
}

 g_event 
g_run_events()
{
   ...
   g_topology_lock(); = g_event acuired topology_lock here.
   ...
   one_event()
   ...
}

one_event()
g_orphan_register()
g_dev_orphan()
destroy_dev()
destroy_dev()
destroy_devl()
{
  ...
  while (dev-si_threadcount != 0) { = this count was incremented by Thread A
/* Use unique dummy wait ident */
msleep(csw, devmtx, PRIBIO, devdrn, hz / 10);
  }
  ...
}
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


arm: cpu_switch() has bug?

2013-01-09 Thread Kohji Okuno
Hi,

I have doubt if cpu_switch() of arm has a bug.

In swtch.S:L.334, if newtd-td_pcb (this is in stack pointer for
kernel) has an address accessed first for the old(current) thread,
data_abort_fault may occur.

When data_abort_fault occurs, data_abort_handler() tries to solve this
address from kernel_map. In this time, curthread and curpcb are
already updated in swtch.S:L.223-231. As this result,
data_abort_handler() will occur data_abort_fault in trap.c:L.301, again.

When I check, in other CPUs, after updating the root pointer of MMU,
curthread and curpcb are updated.

Would you please check this?

Thanks,
 Kohji Okuno


arm/arm/swtch.S:

215 ENTRY(cpu_switch)
216 stmfd   sp!, {r4-r7, lr}
217 mov r6, r2 /* Save the mutex */
218 
219 .Lswitch_resume:
220 /* rem: r0 = old lwp */
221 /* rem: interrupts are disabled */
222 
223 /* Process is now on a processor. */
224 /* We have a new curthread now so make a note it */
225 GET_CURTHREAD_PTR(r7)
226 str r1, [r7]
227 
228 /* Hook in a new pcb */
229 GET_PCPU(r7)
230 ldr r2, [r1, #TD_PCB]
231 str r2, [r7, #PC_CURPCB]
232 
233 /* rem: r1 = new process */
234 /* rem: interrupts are enabled */

  SNIP 

298 /* rem: r2 = old PCB */
299 /* rem: r9 = new PCB */
300 /* rem: interrupts are enabled */
301 
302 #ifdef ARM_VFP_SUPPORT
303 /*
304  * vfp_store will clear pcpu-pc_vfpcthread, save 
305  * registers and state, and modify the control as needed.
306  * a future exception will bounce the backup settings in the fp 
unit.
307  * XXX vfp_store can't change r4
308  */
309 GET_PCPU(r7)
310 ldr r8, [r7, #(PC_VFPCTHREAD)]
311 cmp r4, r8  /* old thread used vfp? 
*/
312 bne 1f  /* no, don't save */
313 cmp r1, r4  /* same thread ? */
314 beq 1f  /* yes, skip vfp store 
*/
315 #ifdef SMP
316 ldr r8, [r7, #(PC_CPU)] /* last used on this 
cpu? */
317 ldr r3, [r2, #(PCB_VFPCPU)]
318 cmp r8, r3  /* last cpu to use these registers? */
319 bne 1f  /* no. these values are stale */
320 #endif
321 add r0, r2, #(PCB_VFPSTATE)
322 bl  _C_LABEL(vfp_store)
323 1:
324 #endif  /* ARM_VFP_SUPPORT */
325 
326 /* r1 now free! */
327 
328 /* Third phase : restore saved context */
329 
330 /* rem: r2 = old PCB */
331 /* rem: r9 = new PCB */
332 /* rem: interrupts are enabled */
333 
334 ldr r5, [r9, #(PCB_DACR)]   /* r5 = new DACR */
335 mov r2, #DOMAIN_CLIENT
336 cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel 
thread? */
337 beq .Lcs_context_switched/* Yup. Don't flush cache 
*/
338 mrc p15, 0, r0, c3, c0, 0   /* r0 = old DACR */


arm/arm/trap.c

224 void
225 data_abort_handler(trapframe_t *tf)
226 {
227 struct vm_map *map;
228 struct pcb *pcb;
229 struct thread *td;
230 u_int user, far, fsr;
231 vm_prot_t ftype;
232 void *onfault;
233 vm_offset_t va;
234 int error = 0;
235 struct ksig ksig;
236 struct proc *p;
237 
238 
239 /* Grab FAR/FSR before enabling interrupts */
240 far = cpu_faultaddress();
241 fsr = cpu_faultstatus();
242 #if 0
243 printf(data abort: %p (from %p %p)\n, (void*)far, 
(void*)tf-tf_pc,
244 (void*)tf-tf_svc_lr);
245 #endif
246 
247 /* Update vmmeter statistics */
248 #if 0
249 vmexp.traps++;
250 #endif
251 
252 td = curthread;
253 p = td-td_proc;
254 
255 PCPU_INC(cnt.v_trap);
256 /* Data abort came from user mode? */
257 user = TRAP_USERMODE(tf);
258 
259 if (user) {
260 td-td_pticks = 0;
261 td-td_frame = tf;  
262 if (td-td_ucred != td-td_proc-p_ucred)
263 cred_update_thread(td);
264 
265 }
266 /* Grab the current pcb */
267 pcb = td-td_pcb;

 SNIP 

299 
300 /* fusubailout is used by [fs]uswintr to avoid page faulting */
301 if (__predict_false(pcb-pcb_onfault == fusubailout

About 802.1Q tag

2012-11-25 Thread Kohji Okuno
Hi,

Would someone check the following code?

If the hardware do not process an 802.1Q tag, the kernel repacks mbuf
in line 578-580. But, `struct ether_header *eh' was assigned at line 484.

And, in line 611-637, because of the kernel refers old eh pointer, the
kernel will misjudges its ether packet.

I think that `eh = mtod(m, struct ether_header *);' is needed after
line 580.

Thanks,
 Kohji Okuno

sys/net/if_ethersubr.c:
448 static void
449 ether_input_internal(struct ifnet *ifp, struct mbuf *m)
450 {
451 struct ether_header *eh;

484 eh = mtod(m, struct ether_header *);

554 /*
555  * If the hardware did not process an 802.1Q tag, do this now,
556  * to allow 802.1P priority frames to be passed to the main 
input
557  * path correctly.
558  * TODO: Deal with Q-in-Q frames, but not arbitrary nesting 
levels.
559  */
560 if ((m-m_flags  M_VLANTAG) == 0  etype == ETHERTYPE_VLAN) {

578 bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,
579 ETHER_HDR_LEN - ETHER_TYPE_LEN);
580 m_adj(m, ETHER_VLAN_ENCAP_LEN);
581 }

610 
611 #if defined(INET) || defined(INET6)
612 /*
613  * Clear M_PROMISC on frame so that carp(4) will see it when the
614  * mbuf flows up to Layer 3.
615  * FreeBSD's implementation of carp(4) uses the inprotosw
616  * to dispatch IPPROTO_CARP. carp(4) also allocates its own
617  * Ethernet addresses of the form 00:00:5e:00:01:xx, which
618  * is outside the scope of the M_PROMISC test below.
619  * TODO: Maintain a hash table of ethernet addresses other than
620  * ether_dhost which may be active on this ifp.
621  */
622 if (ifp-if_carp  (*carp_forus_p)(ifp, eh-ether_dhost)) {
623 m-m_flags = ~M_PROMISC;
624 } else
625 #endif
626 {
627 /*
628  * If the frame received was not for our MAC address, 
set the
629  * M_PROMISC flag on the mbuf chain. The frame may need 
to
630  * be seen by the rest of the Ethernet input path in 
case of
631  * re-entry (e.g. bridge, vlan, netgraph) but should 
not be
632  * seen by upper protocol layers.
633  */
634 if (!ETHER_IS_MULTICAST(eh-ether_dhost) 
635 bcmp(IF_LLADDR(ifp), eh-ether_dhost, 
ETHER_ADDR_LEN) != 0)
636 m-m_flags |= M_PROMISC;
637 }
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


The current libc/locale/toupper.c is mistaken

2012-05-10 Thread Kohji Okuno
Hi,

I think that libc/locale/toupper.c is mistaken.
Could you check it?

@@ -51,7 +51,7 @@ ___toupper_l(c, l)
 {
size_t lim;
FIX_LOCALE(l);
-   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__maplower_ext;
+   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__mapupper_ext;
_RuneEntry *base, *re;
 
if (c  0 || c == EOF)

Best regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: The current libc/locale/toupper.c is mistaken

2012-05-10 Thread Kohji Okuno
Hi Eric,

 I'm left wondering how this was not caught by the libc++ test
 suite. The current toupper.c shouldn't pass
 http://llvm.org/svn/llvm-project/libcxx/trunk/test/localization/locales/locale.convenience/conversions/conversions.character/toupper.pass.cpp

This test suite checks only popular characters.
__mapupper_ext is used in case of special characters.

For example, Turkish 'i' (0x0131) should convert 'I' (0x49).

Regards,
 Kohji Okuno


 Den 10/05/2012 kl. 12.03 skrev Dimitry Andric:
 
 On 2012-05-10 11:02, Kohji Okuno wrote:
 I think that libc/locale/toupper.c is mistaken.
 Could you check it?
 
 @@ -51,7 +51,7 @@ ___toupper_l(c, l)
 {
size_t lim;
FIX_LOCALE(l);
 -   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__maplower_ext;
 +   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__mapupper_ext;
_RuneEntry *base, *re;
 
if (c  0 || c == EOF)
 
 Yes, this definitely looks like a copy/paste error, introduced here:
 
 http://svnweb.freebsd.org/base/head/lib/libc/locale/toupper.c?r1=165903r2=227753
 
 I'll commit the fix tonight (CEST), if David isn't faster than me. :)
 
 I'm left wondering how this was not caught by the libc++ test suite. The 
 current toupper.c shouldn't pass 
 http://llvm.org/svn/llvm-project/libcxx/trunk/test/localization/locales/locale.convenience/conversions/conversions.character/toupper.pass.cpp
 
 Thanks,
 Erik___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: The current libc/locale/toupper.c is mistaken

2012-05-10 Thread Kohji Okuno
Hi David,

From: David Chisnall thera...@freebsd.org

 If you have a test case, I can commit it to the libc++ test suite.
 
 David

I attached my test source.
This test program shoud output as below.

towupper_l
0049, 0049
0131, 0049
0130, 0130
0069, 0049

towlower_l
0049, 0069
0131, 0131
0130, 0069
0069, 0069

But, when I use original toupper.c, this proguram output as below.

towupper_l
0049, 0049
0131, 0131
0130, 0069
0069, 0049

towlower_l
0049, 0069
0131, 0131
0130, 0069
0069, 0069

Regards,
 Kohji Okuno

 
 On 10 May 2012, at 21:42, Kohji Okuno wrote:
 
 Hi Eric,
 
 I'm left wondering how this was not caught by the libc++ test
 suite. The current toupper.c shouldn't pass
 http://llvm.org/svn/llvm-project/libcxx/trunk/test/localization/locales/locale.convenience/conversions/conversions.character/toupper.pass.cpp
 
 This test suite checks only popular characters.
 __mapupper_ext is used in case of special characters.
 
 For example, Turkish 'i' (0x0131) should convert 'I' (0x49).
 
 Regards,
 Kohji Okuno
 
 
 Den 10/05/2012 kl. 12.03 skrev Dimitry Andric:
 
 On 2012-05-10 11:02, Kohji Okuno wrote:
 I think that libc/locale/toupper.c is mistaken.
 Could you check it?
 
 @@ -51,7 +51,7 @@ ___toupper_l(c, l)
 {
   size_t lim;
   FIX_LOCALE(l);
 -   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__maplower_ext;
 +   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__mapupper_ext;
   _RuneEntry *base, *re;
 
   if (c  0 || c == EOF)
 
 Yes, this definitely looks like a copy/paste error, introduced here:
 
 http://svnweb.freebsd.org/base/head/lib/libc/locale/toupper.c?r1=165903r2=227753
 
 I'll commit the fix tonight (CEST), if David isn't faster than me. :)
 
 I'm left wondering how this was not caught by the libc++ test suite. The 
 current toupper.c shouldn't pass 
 http://llvm.org/svn/llvm-project/libcxx/trunk/test/localization/locales/locale.convenience/conversions/conversions.character/toupper.pass.cpp
 
 Thanks,
 Erik___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
 
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: The current libc/locale/toupper.c is mistaken

2012-05-10 Thread Kohji Okuno
Hi,

I'm sorry. I forgot to attach a file.

Regards,
 Kohji Okuno

 Hi David,
 
 From: David Chisnall thera...@freebsd.org
 
 If you have a test case, I can commit it to the libc++ test suite.
 
 David
 
 I attached my test source.
 This test program shoud output as below.
 
 towupper_l
 0049, 0049
 0131, 0049
 0130, 0130
 0069, 0049
 
 towlower_l
 0049, 0069
 0131, 0131
 0130, 0069
 0069, 0069
 
 But, when I use original toupper.c, this proguram output as below.
 
 towupper_l
 0049, 0049
 0131, 0131
 0130, 0069
 0069, 0049
 
 towlower_l
 0049, 0069
 0131, 0131
 0130, 0069
 0069, 0069
 
 Regards,
  Kohji Okuno
 
 
 On 10 May 2012, at 21:42, Kohji Okuno wrote:
 
 Hi Eric,
 
 I'm left wondering how this was not caught by the libc++ test
 suite. The current toupper.c shouldn't pass
 http://llvm.org/svn/llvm-project/libcxx/trunk/test/localization/locales/locale.convenience/conversions/conversions.character/toupper.pass.cpp
 
 This test suite checks only popular characters.
 __mapupper_ext is used in case of special characters.
 
 For example, Turkish 'i' (0x0131) should convert 'I' (0x49).
 
 Regards,
 Kohji Okuno
 
 
 Den 10/05/2012 kl. 12.03 skrev Dimitry Andric:
 
 On 2012-05-10 11:02, Kohji Okuno wrote:
 I think that libc/locale/toupper.c is mistaken.
 Could you check it?
 
 @@ -51,7 +51,7 @@ ___toupper_l(c, l)
 {
   size_t lim;
   FIX_LOCALE(l);
 -   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__maplower_ext;
 +   _RuneRange *rr = XLOCALE_CTYPE(l)-runes-__mapupper_ext;
   _RuneEntry *base, *re;
 
   if (c  0 || c == EOF)
 
 Yes, this definitely looks like a copy/paste error, introduced here:
 
 http://svnweb.freebsd.org/base/head/lib/libc/locale/toupper.c?r1=165903r2=227753
 
 I'll commit the fix tonight (CEST), if David isn't faster than me. :)
 
 I'm left wondering how this was not caught by the libc++ test suite. The 
 current toupper.c shouldn't pass 
 http://llvm.org/svn/llvm-project/libcxx/trunk/test/localization/locales/locale.convenience/conversions/conversions.character/toupper.pass.cpp
 
 Thanks,
 Erik___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
 
 ___
 freebsd-current@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-current
 To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
#include stdlib.h
#include stdio.h
#include locale.h
#include wctype.h
#include xlocale.h

int
main()
{
int i;
wint_t test[] = {0x0049, 0x0131, 0x0130, 0x0069};
wint_t ret;
locale_t x;
x = newlocale(0x1f, tr_TR, NULL);

printf(towupper_l\n);
for (i = 0; i  sizeof(test)/sizeof(wint_t); i++) {
ret = towupper_l(test[i], x);
printf(%04x, %04x\n, test[i], ret);
}
printf(\n);

printf(towlower_l\n);
for (i = 0; i  sizeof(test)/sizeof(wint_t); i++) {
ret = towlower_l(test[i], x);
printf(%04x, %04x\n, test[i], ret);
}

exit(0);
}
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Re: Is UPS_PORT_POWER wrong?

2012-01-28 Thread Kohji Okuno
Hi HPS,

Do you have better idea?

From: Kohji Okuno okuno.ko...@jp.panasonic.com
Date: Tue, 24 Jan 2012 09:53:29 +0900 (JST)

 Hi HPS,
 
 On Monday 23 January 2012 09:12:46 Kohji Okuno wrote:
 Hi HPS,
 
 I think that UPS_PORT_POWER and UPS_PORT_LINK_STATE overlap.
 And, in xhci.c you set UPS_PORT_POWER as folows.
 
 When UPS_PORT_POWER is set, UPS_PORT_LINK_STATE_GET() macro will
 return incorrect value.
 
 if (v  XHCI_PS_PP) {
 /*
  * The USB 3.0 RH is using the
  * USB 2.0's power bit
  */
 i |= UPS_PORT_POWER;
 }
 
 
 Hi,
 
 The USB 3.0 root HUB is special because it defines FULL/HIGH and LOW speed, 
 so 
 I had to merge that into the port status register of the XHCI root HUB like 
 this:
 
 0: CONNECT_STATUS
 1: PORT_ENABLED
 2: SUSPEND
 3: OVERCURRENT_INDICATOR
 4: LINK STATE (USB 3.0)
 5: -
 6: -
 7: -
 8: PORT_POWER (USB 2.0)
 # Bit 9+10 have 4 combinations which are defined: FS, LW, HS, SS
 9: LOW_SPEED (USB 2.0)
 10: HIGH_SPEED (USB 2.0)
 11: not implemented
 12: PORT_INDICATOR
 13:
 14:
 15: MODE_DEVICE (FreeBSD specific)
 
 If you have a better idea, it is possible to change this.
 
 I have a idea.
 
 -#define UPS_PORT_LINK_STATE_GET(x)  (((x)  5)  0xF)
 -#define UPS_PORT_LINK_STATE_SET(x)  (((x)  0xF)  5)
 +#define UPS_PORT_LINK_STATE_GET(x)  x)  5)  0x7)|(((x)  11)  
 0x8))
 +#define UPS_PORT_LINK_STATE_SET(x)  x)  0x7)  5)|(((x)  0x8)  
 11))
 +#define UPS_PORT_LS_SS  0x4000  /* currently FreeBSD 
 specific */
 
 But, this is not cool.
 
 Regards,
  Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Is UPS_PORT_POWER wrong?

2012-01-23 Thread Kohji Okuno
Hi HPS,

I think that UPS_PORT_POWER and UPS_PORT_LINK_STATE overlap.
And, in xhci.c you set UPS_PORT_POWER as folows.

When UPS_PORT_POWER is set, UPS_PORT_LINK_STATE_GET() macro will
return incorrect value.

if (v  XHCI_PS_PP) {
/*
 * The USB 3.0 RH is using the
 * USB 2.0's power bit
 */
i |= UPS_PORT_POWER;
}

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Is UPS_PORT_POWER wrong?

2012-01-23 Thread Kohji Okuno
Hi HPS,

 On Monday 23 January 2012 09:12:46 Kohji Okuno wrote:
 Hi HPS,
 
 I think that UPS_PORT_POWER and UPS_PORT_LINK_STATE overlap.
 And, in xhci.c you set UPS_PORT_POWER as folows.
 
 When UPS_PORT_POWER is set, UPS_PORT_LINK_STATE_GET() macro will
 return incorrect value.
 
 if (v  XHCI_PS_PP) {
 /*
  * The USB 3.0 RH is using the
  * USB 2.0's power bit
  */
 i |= UPS_PORT_POWER;
 }
 
 
 Hi,
 
 The USB 3.0 root HUB is special because it defines FULL/HIGH and LOW speed, 
 so 
 I had to merge that into the port status register of the XHCI root HUB like 
 this:
 
 0: CONNECT_STATUS
 1: PORT_ENABLED
 2: SUSPEND
 3: OVERCURRENT_INDICATOR
 4: LINK STATE (USB 3.0)
 5: -
 6: -
 7: -
 8: PORT_POWER (USB 2.0)
 # Bit 9+10 have 4 combinations which are defined: FS, LW, HS, SS
 9: LOW_SPEED (USB 2.0)
 10: HIGH_SPEED (USB 2.0)
 11: not implemented
 12: PORT_INDICATOR
 13:
 14:
 15: MODE_DEVICE (FreeBSD specific)
 
 If you have a better idea, it is possible to change this.

I have a idea.

-#define UPS_PORT_LINK_STATE_GET(x)  (((x)  5)  0xF)
-#define UPS_PORT_LINK_STATE_SET(x)  (((x)  0xF)  5)
+#define UPS_PORT_LINK_STATE_GET(x)  x)  5)  0x7)|(((x)  11)  
0x8))
+#define UPS_PORT_LINK_STATE_SET(x)  x)  0x7)  5)|(((x)  0x8)  
11))
+#define UPS_PORT_LS_SS  0x4000  /* currently FreeBSD specific 
*/

But, this is not cool.

Regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Can you use a USB3.0 hub?

2012-01-12 Thread Kohji Okuno
Hi HPS,

From: Hans Petter Selasky hsela...@c2i.net
Subject: Re: Can you use a USB3.0 hub?
Date: Thu, 12 Jan 2012 22:23:22 +0100

 On Thursday 12 January 2012 07:15:17 Kohji Okuno wrote:
 Hi,
 
 Can you use a USB3.0 hub?
 
 I tried a USB3.0 hub (BUFFALO BSH4A04U3BK).
 And I used 8-stable and PCI-E card (BUFFALO IFC-PCIE2U3)
 
 The hub is for only japanese market.
 The card is NEC’s 720200 chip
 http://www.buffalotech.com/products/accessories/interface-card-adapters/usb
 -30-pci-express-interface-card/
 
 
 The kernel could not recognize USB3.0 HDD that connected to this hub
 as the following log. But, the kernel could reconize USB2.0 HDD that
 connected to this hub.
 
 Regards,
  Kohji Okuno
 
 Hi,
 
 There is a problem with USB 3.0 HUBs, most likely something related to the 
 XHCI route string or USB HUB set depth.
 
 I don't have a USB 3.0 analyzer, so I cannot find this out quickly. If you 
 could help debug, would be great. Here is a patch which you can put on top of 
 8/9- or 10- stable:
 
 http://svn.freebsd.org/changeset/base/230032
 
 It fixes a few issues, but not all.

I think your commit is wrong about UPS_PORT_POWER_SS.

- #define UPS_PORT_POWER_SS   0x0200  /* super-speed only */
  #define UPS_LOW_SPEED   0x0200

+ #define UPS_PORT_POWER_SS   0x2000  /* super-speed only */
  #define UPS_LOW_SPEED   0x0200

Now, usb3.0 HDD was not able to recognize.
I have USB 3.0 analyzer(LeCroy Voyager), so I can help debug.

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

Can you use a USB3.0 hub?

2012-01-11 Thread Kohji Okuno
Hi,

Can you use a USB3.0 hub?

I tried a USB3.0 hub (BUFFALO BSH4A04U3BK).
And I used 8-stable and PCI-E card (BUFFALO IFC-PCIE2U3)

The hub is for only japanese market.
The card is NEC’s 720200 chip
http://www.buffalotech.com/products/accessories/interface-card-adapters/usb-30-pci-express-interface-card/


The kernel could not recognize USB3.0 HDD that connected to this hub
as the following log. But, the kernel could reconize USB2.0 HDD that
connected to this hub.

Regards,
 Kohji Okuno

-- log 
xhci0: XHCI (generic) USB 3.0 controller mem 0xf7ffe000-0xf7ff irq 28 at d
evice 0.0 on pci1
xhci0: [ITHREAD]
xhci0: 32 byte context size.
usbus0 on xhci0
  ...

ugen0.2: VIA Labs, Inc. at usbus0
uhub11: VIA Labs, Inc. 4-Port USB 3.0 Hub, class 9/0, rev 3.00/3.74, addr 1 on
 usbus0
uhub11: 4 ports with 4 removable, self powered
usb_alloc_device: set address 3 failed (USB_ERR_IOERROR, ignored)
usbd_req_re_enumerate: addr=3, set address failed! (USB_ERR_IOERROR, ignored)
usbd_req_re_enumerate: addr=3, set address failed! (USB_ERR_IOERROR, ignored)
ugen0.3: Unknown at usbus0 (disconnected)
uhub_reattach_port: could not allocate new device
uhub_reattach_port: device problem (USB_ERR_STALLED), disabling port 4
ugen0.3: vendor 0x2109 at usbus0
uhub12: vendor 0x2109 USB2.0 Hub, class 9/0, rev 2.00/2.74, addr 2 on usbus0
uhub12: 4 ports with 4 removable, self powered
usb_alloc_device: set address 4 failed (USB_ERR_IOERROR, ignored)
usbd_req_re_enumerate: addr=4, set address failed! (USB_ERR_IOERROR, ignored)
usbd_req_re_enumerate: addr=4, set address failed! (USB_ERR_IOERROR, ignored)
ugen0.4: Unknown at usbus0 (disconnected)
uhub_reattach_port: could not allocate new device
uhub_reattach_port: device problem (USB_ERR_STALLED), disabling port 4
usb_alloc_device: set address 4 failed (USB_ERR_IOERROR, ignored)
usbd_req_re_enumerate: addr=4, set address failed! (USB_ERR_IOERROR, ignored)
usbd_req_re_enumerate: addr=4, set address failed! (USB_ERR_IOERROR, ignored)
ugen0.4: Unknown at usbus0 (disconnected)
uhub_reattach_port: could not allocate new device
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org

about XHCI_PS_PP

2011-12-13 Thread Kohji Okuno
Hi Selasky,

I think XHCI_PS_PP is wrong.

- #define XHCI_PS_PP  0x0100  /* RW - port power */
+ #define XHCI_PS_PP  0x0200  /* RW - port power */

Could you check it?

Best regards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Bug: devfs is sure to have the bug.

2011-08-08 Thread Kohji Okuno
Hi Kostic and Jaakko,

 On Fri, Aug 05, 2011 at 06:45:22PM +0300, Jaakko Heinonen wrote:
 On 2011-08-03, Kostik Belousov wrote:
  On Wed, Aug 03, 2011 at 02:44:23PM +0900, Kohji Okuno wrote:
devfs_populate(), and the context holds only dm-dm_lock in
devfs_populate().

On the other hand, devfs_generation is incremented in devfs_create()
and devfs_destroy() the context holds only devmtx in devfs_create()
and devfs_destroy().

If a context executes devfs_create() when other context is executing
(***), then dm-dm_generation is updated incorrect value.
As a result, we can not open the last detected device (we receive 
ENOENT).
  
  I think the problem you described is real, and suggested change is right.
  Initially, I thought that we should work with devfs_generation as with
  the atomic type due to unlocked access in the devfs_populate(), but then
  convinced myself that this is not needed.
  
  But also, I think there is another half of the problem. Namely,
  devfs_lookup() calls devfs_populate_vp(), and then does lookup with the
  help of devfs_lookupx(). We will miss the generation update
  happen after the drop of the dm_lock in devfs_populate_vp() to reacquire
  the directory vnode lock.
 
 I don't understand this. devfs_generation is not protected with dm_lock
 in devfs_create() and devfs_destroy(). On the other hand if you mean
 that another thread calls devfs_populate() while we drop dm_lock in
 devfs_populate_vp(), isn't the mount point up to date when we re-lock
 dm_lock?
 Yes, I was not quite exact in describing what I mean, and the reference
 to dm_lock drop is both vague and not correct.
 
 I am after the fact that we do allow the situation where it is externally
 visible that new cdev node was successfully created before the lookup
 returns ENOENT for the path of the node.
 
 
  @@ -630,13 +630,15 @@ devfs_populate_loop(struct devfs_mount *dm, int 
  cleanup)
   void
   devfs_populate(struct devfs_mount *dm)
   {
  +  unsigned gen;
   
 sx_assert(dm-dm_lock, SX_XLOCKED);
  -  if (dm-dm_generation == devfs_generation)
  +  gen = devfs_generation;
  +  if (dm-dm_generation == gen)
 return;
 while (devfs_populate_loop(dm, 0))
 continue;
  -  dm-dm_generation = devfs_generation;
  +  dm-dm_generation = gen;
   }
 
 After this change dm-dm_generation may be stale although the mount
 point is up to date? This is probably harmless, though.
 This must be harmless, in the worst case it will cause more calls to
 the populate. In fact, this even allows the dm_generation to roll backward,
 which is again harmless.

After all, do we only have to fix only devfs_populate()?
I think that there is no problem while I am testing the 8.1-RELEASE
environment that fix only devfs_populate().

Many thanks,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Bug: devfs is sure to have the bug.

2011-08-04 Thread Kohji Okuno
Hello Kostik,

 On Thu, Aug 04, 2011 at 11:41:39AM +0900, Kohji Okuno wrote:
 Hello Kostik,
 
 From: Kostik Belousov kostik...@gmail.com
 Subject: Re: Bug: devfs is sure to have the bug.
 Date: Wed, 3 Aug 2011 16:50:44 +0300
  I think the problem you described is real, and suggested change is right.
  Initially, I thought that we should work with devfs_generation as with
  the atomic type due to unlocked access in the devfs_populate(), but then
  convinced myself that this is not needed.
  
  But also, I think there is another half of the problem. Namely,
  devfs_lookup() calls devfs_populate_vp(), and then does lookup with the
  help of devfs_lookupx(). We will miss the generation update
  happen after the drop of the dm_lock in devfs_populate_vp() to reacquire
  the directory vnode lock.
  
  I propose the change below, consisting of your fix and also retry of
  population and lookup in case generations do not match for ENOENT
 case.
  
  diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
  index d72ada0..8ff9bc2 100644
  --- a/sys/fs/devfs/devfs_devs.c
  +++ b/sys/fs/devfs/devfs_devs.c
  @@ -63,7 +63,7 @@ static MALLOC_DEFINE(M_CDEVP, DEVFS1, DEVFS cdev_priv 
  storage);
   
   static SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, DEVFS 
  filesystem);
   
  -static unsigned devfs_generation;
  +unsigned devfs_generation;
   SYSCTL_UINT(_vfs_devfs, OID_AUTO, generation, CTLFLAG_RD,
 devfs_generation, 0, DEVFS generation number);
   
  @@ -630,13 +630,15 @@ devfs_populate_loop(struct devfs_mount *dm, int 
  cleanup)
   void
   devfs_populate(struct devfs_mount *dm)
   {
  +  unsigned gen;
   
 sx_assert(dm-dm_lock, SX_XLOCKED);
  -  if (dm-dm_generation == devfs_generation)
  +  gen = devfs_generation;
  +  if (dm-dm_generation == gen)
 return;
 while (devfs_populate_loop(dm, 0))
 continue;
  -  dm-dm_generation = devfs_generation;
  +  dm-dm_generation = gen;
   }
   
   /*
  diff --git a/sys/fs/devfs/devfs_int.h b/sys/fs/devfs/devfs_int.h
  index cdc6aba..cb01ad1 100644
  --- a/sys/fs/devfs/devfs_int.h
  +++ b/sys/fs/devfs/devfs_int.h
  @@ -71,6 +71,8 @@ struct cdev_priv {
   
   #define   cdev2priv(c)member2struct(cdev_priv, cdp_c, c)
   
  +extern unsigned devfs_generation;
  +
   struct cdev   *devfs_alloc(int);
   int   devfs_dev_exists(const char *);
   void  devfs_free(struct cdev *);
  diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
  index 955bd8b..2603caa 100644
  --- a/sys/fs/devfs/devfs_vnops.c
  +++ b/sys/fs/devfs/devfs_vnops.c
  @@ -188,7 +188,7 @@ devfs_clear_cdevpriv(void)
* On success devfs_populate_vp() returns with dmp-dm_lock held.
*/
   static int
  -devfs_populate_vp(struct vnode *vp)
  +devfs_populate_vp(struct vnode *vp, int dm_locked)
   {
 struct devfs_dirent *de;
 struct devfs_mount *dmp;
  @@ -199,7 +199,8 @@ devfs_populate_vp(struct vnode *vp)
 dmp = VFSTODEVFS(vp-v_mount);
 locked = VOP_ISLOCKED(vp);
   
  -  sx_xlock(dmp-dm_lock);
  +  if (!dm_locked)
  +  sx_xlock(dmp-dm_lock);
 DEVFS_DMP_HOLD(dmp);
   
 /* Can't call devfs_populate() with the vnode lock held. */
  @@ -242,7 +243,7 @@ devfs_vptocnp(struct vop_vptocnp_args *ap)
   
 dmp = VFSTODEVFS(vp-v_mount);
   
  -  error = devfs_populate_vp(vp);
  +  error = devfs_populate_vp(vp, 0);
 if (error != 0)
 return (error);
   
  @@ -643,7 +644,7 @@ devfs_getattr(struct vop_getattr_args *ap)
 struct devfs_mount *dmp;
 struct cdev *dev;
   
  -  error = devfs_populate_vp(vp);
  +  error = devfs_populate_vp(vp, 0);
 if (error != 0)
 return (error);
   
  @@ -903,7 +904,7 @@ devfs_lookupx(struct vop_lookup_args *ap, int 
  *dm_unlock)
   
 if (cdev == NULL)
 sx_xlock(dmp-dm_lock);
  -  else if (devfs_populate_vp(dvp) != 0) {
  +  else if (devfs_populate_vp(dvp, 0) != 0) {
 *dm_unlock = 0;
 sx_xlock(dmp-dm_lock);
 if (DEVFS_DMP_DROP(dmp)) {
  @@ -966,19 +967,30 @@ devfs_lookupx(struct vop_lookup_args *ap, int 
  *dm_unlock)
   static int
   devfs_lookup(struct vop_lookup_args *ap)
   {
  -  int j;
 struct devfs_mount *dmp;
  -  int dm_unlock;
  +  int error, dm_unlock;
   
  -  if (devfs_populate_vp(ap-a_dvp) != 0)
  +  dm_unlock = 0;
  +retry:
  +  if (devfs_populate_vp(ap-a_dvp, dm_unlock) != 0)
 return (ENOTDIR);
   
 dmp = VFSTODEVFS(ap-a_dvp-v_mount);
 dm_unlock = 1;
  -  j = devfs_lookupx(ap, dm_unlock);
  -  if (dm_unlock == 1)
  +  error = devfs_lookupx(ap, dm_unlock);
  +  if (error == ENOENT) {
  +  if (dm_unlock)
  +  sx_assert(dmp-dm_lock, SA_XLOCKED);
  +  else {
  +  sx_xlock(dmp-dm_lock);
  +  dm_unlock = 1;
  +  }
  +  if (devfs_generation != dmp-dm_generation)
  +  goto retry;
  +  }
  +  if (dm_unlock

Re: Bug: devfs is sure to have the bug.

2011-08-04 Thread Kohji Okuno
Hello Kostik,

  On Thu, Aug 04, 2011 at 11:41:39AM +0900, Kohji Okuno wrote:
  But, now I'm using 8.1-RELEASE. May I have advice about 8.X ?
  Do you mean a patch for the stable/8 ? I believe it is enough to
  apply rev. 211628 to stable/8, then the patch I posted yesterday
  should be compilable.
 
 I'm sorry.
 I need a patch for 8.1-RELEASE. Could you propose patch?
 Did you tried to apply the 211628 and the patch I mailed, to 8.1 ?
 I am not very interested in porting this stuff for such old system.
 On the other hand, I am unaware of large changes in devfs between
 8.1 and latest stable.

No. Because the difference was large as you were poingint out, I did
not your patch. Now, I'm trying the following patch.

 devfs_populate(struct devfs_mount *dm)
 {
 
+#if 1
+   unsigned gen;
+   sx_assert(dm-dm_lock, SX_XLOCKED);
+   gen = devfs_generation;
+   if (dm-dm_generation == gen)
+   return;
+   while (devfs_populate_loop(dm, 0))
+   continue;
+   dm-dm_generation = gen;
+#else
sx_assert(dm-dm_lock, SX_XLOCKED);
if (dm-dm_generation == devfs_generation)
return;
while (devfs_populate_loop(dm, 0))
continue;
dm-dm_generation = devfs_generation;
+#endif
 }
 
 /*
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Bug: devfs is sure to have the bug.

2011-08-03 Thread Kohji Okuno
Hello Kostik,

From: Kostik Belousov kostik...@gmail.com
Subject: Re: Bug: devfs is sure to have the bug.
Date: Wed, 3 Aug 2011 16:50:44 +0300
Message-ID: 20110803135044.gm17...@deviant.kiev.zoral.com.ua

 On Wed, Aug 03, 2011 at 02:44:23PM +0900, Kohji Okuno wrote:
 Hello,
 
  Hello,
  
  I think that devfs is sure to have the bug.
  I found that I couldn't open /dev/XXX though the kernel detected XXX
  device.
  
  
  dm-dm_generation is updated with devfs_generation in
  devfs_populate(), and the context holds only dm-dm_lock in
  devfs_populate().
  
  On the other hand, devfs_generation is incremented in devfs_create()
  and devfs_destroy() the context holds only devmtx in devfs_create()
  and devfs_destroy().
  
  If a context executes devfs_create() when other context is executing
  (***), then dm-dm_generation is updated incorrect value.
  As a result, we can not open the last detected device (we receive ENOENT).
  
  I think that we should change the lock method.
  May I have advice?
  
  void
  devfs_populate(struct devfs_mount *dm)
  {
  
  sx_assert(dm-dm_lock, SX_XLOCKED);
  if (dm-dm_generation == devfs_generation)
  return;
  while (devfs_populate_loop(dm, 0))
  continue;
  (***)
  dm-dm_generation = devfs_generation;
  }
  
  void
  devfs_create(struct cdev *dev)
  {
  struct cdev_priv *cdp;
  
  mtx_assert(devmtx, MA_OWNED);
  cdp = cdev2priv(dev);
  cdp-cdp_flags |= CDP_ACTIVE;
  cdp-cdp_inode = alloc_unrl(devfs_inos);
  dev_refl(dev);
  TAILQ_INSERT_TAIL(cdevp_list, cdp, cdp_list);
  devfs_generation++;
  }
  
  void
  devfs_destroy(struct cdev *dev)
  {
  struct cdev_priv *cdp;
  
  mtx_assert(devmtx, MA_OWNED);
  cdp = cdev2priv(dev);
  cdp-cdp_flags = ~CDP_ACTIVE;
  devfs_generation++;
  }
  
  Thanks.
 
 I propose the solution. May I have advice?
 
 void
 devfs_populate(struct devfs_mount *dm)
 {
 
 sx_assert(dm-dm_lock, SX_XLOCKED);
 #if 1 /* I propose... */
 int tmp_generation;
 retry:
 tmp_generation = devfs_generation;
 if (dm-dm_generation == tmp_generation)
 return;
 while (devfs_populate_loop(dm, 0))
 continue;
 if (tmp_generation != devfs_generation)
 goto retry;
 dm-dm_generation = tmp_generation;
 #else /* Original */
 if (dm-dm_generation == devfs_generation)
 return;
 while (devfs_populate_loop(dm, 0))
 continue;
 dm-dm_generation = devfs_generation;
 #endif
 }
 
 I think the problem you described is real, and suggested change is right.
 Initially, I thought that we should work with devfs_generation as with
 the atomic type due to unlocked access in the devfs_populate(), but then
 convinced myself that this is not needed.
 
 But also, I think there is another half of the problem. Namely,
 devfs_lookup() calls devfs_populate_vp(), and then does lookup with the
 help of devfs_lookupx(). We will miss the generation update
 happen after the drop of the dm_lock in devfs_populate_vp() to reacquire
 the directory vnode lock.
 
 I propose the change below, consisting of your fix and also retry of
 population and lookup in case generations do not match for ENOENT
case.
 
 diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
 index d72ada0..8ff9bc2 100644
 --- a/sys/fs/devfs/devfs_devs.c
 +++ b/sys/fs/devfs/devfs_devs.c
 @@ -63,7 +63,7 @@ static MALLOC_DEFINE(M_CDEVP, DEVFS1, DEVFS cdev_priv 
 storage);
  
  static SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, DEVFS filesystem);
  
 -static unsigned devfs_generation;
 +unsigned devfs_generation;
  SYSCTL_UINT(_vfs_devfs, OID_AUTO, generation, CTLFLAG_RD,
   devfs_generation, 0, DEVFS generation number);
  
 @@ -630,13 +630,15 @@ devfs_populate_loop(struct devfs_mount *dm, int cleanup)
  void
  devfs_populate(struct devfs_mount *dm)
  {
 + unsigned gen;
  
   sx_assert(dm-dm_lock, SX_XLOCKED);
 - if (dm-dm_generation == devfs_generation)
 + gen = devfs_generation;
 + if (dm-dm_generation == gen)
   return;
   while (devfs_populate_loop(dm, 0))
   continue;
 - dm-dm_generation = devfs_generation;
 + dm-dm_generation = gen;
  }
  
  /*
 diff --git a/sys/fs/devfs/devfs_int.h b/sys/fs/devfs/devfs_int.h
 index cdc6aba..cb01ad1 100644
 --- a/sys/fs/devfs/devfs_int.h
 +++ b/sys/fs/devfs/devfs_int.h
 @@ -71,6 +71,8 @@ struct cdev_priv {
  
  #define  cdev2priv(c)member2struct(cdev_priv, cdp_c, c)
  
 +extern unsigned devfs_generation;
 +
  struct cdev  *devfs_alloc(int);
  int  devfs_dev_exists(const char *);
  void devfs_free(struct cdev *);
 diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
 index 955bd8b..2603caa 100644
 --- a/sys/fs/devfs/devfs_vnops.c
 +++ b/sys/fs/devfs/devfs_vnops.c
 @@ -188,7 +188,7

Bug: devfs is sure to have the bug.

2011-08-02 Thread Kohji Okuno
Hello,

I think that devfs is sure to have the bug.
I found that I couldn't open /dev/XXX though the kernel detected XXX
device.


dm-dm_generation is updated with devfs_generation in
devfs_populate(), and the context holds only dm-dm_lock in
devfs_populate().

On the other hand, devfs_generation is incremented in devfs_create()
and devfs_destroy() the context holds only devmtx in devfs_create()
and devfs_destroy().

If a context executes devfs_create() when other context is executing
(***), then dm-dm_generation is updated incorrect value.
As a result, we can not open the last detected device (we receive ENOENT).

I think that we should change the lock method.
May I have advice?

void
devfs_populate(struct devfs_mount *dm)
{

sx_assert(dm-dm_lock, SX_XLOCKED);
if (dm-dm_generation == devfs_generation)
return;
while (devfs_populate_loop(dm, 0))
continue;
(***)
dm-dm_generation = devfs_generation;
}

void
devfs_create(struct cdev *dev)
{
struct cdev_priv *cdp;

mtx_assert(devmtx, MA_OWNED);
cdp = cdev2priv(dev);
cdp-cdp_flags |= CDP_ACTIVE;
cdp-cdp_inode = alloc_unrl(devfs_inos);
dev_refl(dev);
TAILQ_INSERT_TAIL(cdevp_list, cdp, cdp_list);
devfs_generation++;
}

void
devfs_destroy(struct cdev *dev)
{
struct cdev_priv *cdp;

mtx_assert(devmtx, MA_OWNED);
cdp = cdev2priv(dev);
cdp-cdp_flags = ~CDP_ACTIVE;
devfs_generation++;
}

Thanks.
--
 Kohji Okuno (okuno.ko...@jp.panasonic.com)
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Bug: devfs is sure to have the bug.

2011-08-02 Thread Kohji Okuno
Hello,

 Hello,
 
 I think that devfs is sure to have the bug.
 I found that I couldn't open /dev/XXX though the kernel detected XXX
 device.
 
 
 dm-dm_generation is updated with devfs_generation in
 devfs_populate(), and the context holds only dm-dm_lock in
 devfs_populate().
 
 On the other hand, devfs_generation is incremented in devfs_create()
 and devfs_destroy() the context holds only devmtx in devfs_create()
 and devfs_destroy().
 
 If a context executes devfs_create() when other context is executing
 (***), then dm-dm_generation is updated incorrect value.
 As a result, we can not open the last detected device (we receive ENOENT).
 
 I think that we should change the lock method.
 May I have advice?
 
 void
 devfs_populate(struct devfs_mount *dm)
 {
 
 sx_assert(dm-dm_lock, SX_XLOCKED);
 if (dm-dm_generation == devfs_generation)
 return;
 while (devfs_populate_loop(dm, 0))
 continue;
 (***)
 dm-dm_generation = devfs_generation;
 }
 
 void
 devfs_create(struct cdev *dev)
 {
 struct cdev_priv *cdp;
 
 mtx_assert(devmtx, MA_OWNED);
 cdp = cdev2priv(dev);
 cdp-cdp_flags |= CDP_ACTIVE;
 cdp-cdp_inode = alloc_unrl(devfs_inos);
 dev_refl(dev);
 TAILQ_INSERT_TAIL(cdevp_list, cdp, cdp_list);
 devfs_generation++;
 }
 
 void
 devfs_destroy(struct cdev *dev)
 {
 struct cdev_priv *cdp;
 
 mtx_assert(devmtx, MA_OWNED);
 cdp = cdev2priv(dev);
 cdp-cdp_flags = ~CDP_ACTIVE;
 devfs_generation++;
 }
 
 Thanks.

I propose the solution. May I have advice?

void
devfs_populate(struct devfs_mount *dm)
{

sx_assert(dm-dm_lock, SX_XLOCKED);
#if 1 /* I propose... */
int tmp_generation;
retry:
tmp_generation = devfs_generation;
if (dm-dm_generation == tmp_generation)
return;
while (devfs_populate_loop(dm, 0))
continue;
if (tmp_generation != devfs_generation)
goto retry;
dm-dm_generation = tmp_generation;
#else /* Original */
if (dm-dm_generation == devfs_generation)
return;
while (devfs_populate_loop(dm, 0))
continue;
dm-dm_generation = devfs_generation;
#endif
}

Thanks,
  Kohji Okuno (okuno.ko...@jp.panasonic.com)
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Bug about devfs?

2011-07-13 Thread Kohji Okuno
Hello,

 From: Kostik Belousov kostik...@gmail.com
 Date: Tue, 12 Jul 2011 17:57:53 +0300
 On Tue, Jul 12, 2011 at 03:02:44PM +0200, Attilio Rao wrote:
 2011/7/12 Kostik Belousov kostik...@gmail.com:
  On Tue, Jul 12, 2011 at 07:10:28PM +0900, Kohji Okuno wrote:
  Hello,
 
  I think that devfs has a problem.
  I encountered the problem that open(/dev/AAA) returned ENOENT.
  Of course, /dev/AAA exists.
 
  ENOENT was created by the point(***) in devfs_allocv().
  I think that the race condition had occurred between process A and
  vnlru kernel thread.
 
  Please check the following.
 
  If vnlru set VI_DOOMED to vp-v_iflag but vnlru didn't still execute
  VOP_RECLAIM(), process A cat get valid vp from de-de_vnode.
  But, vget() will return ENOENT, because vp-v_iflag has VI_DOOMED.
 
  When I set the break point to (***), I checked that de-de_vnode and
  vp-v_data were NULL.
 
 
  process A:                            vnlru:
 
  devfs_allocv() {
                                        vgonel(vp) {
     ...                                           ...
                                          vp-v_iflag |= VI_DOOMED;
    mtx_lock(devfs_de_interlock);         ...
    vp = de-de_vnode;
    if (vp != NULL) {                     VI_UNLOCK(vp);
                            _/ ...
    VI_LOCK(vp); /              if (VOP_RECLAIM(vp, td))
    mtx_unlock(devfs_de_interlock);       ...
     ...                                \         devfs_reclaim(ap) {
    error = vget(vp,...);                \
     ...                                  \__   
  mtx_lock(devfs_de_interlock);
    if (devfs_allocv_drop_refs(...)) {        de = vp-v_data;
      ...                                           if (de != NULL) {
    }                                         de-de_vnode = NULL;
    else if (error) {                         vp-v_data = NULL;
      ...                                           }
      rturn (error); (***)                  
  mtx_unlock(devfs_de_interlock);
    }                                         ...
                                          }
 
 
 
  I think that devfs_allocv() should be fixed as below.
  How do you think?
 
  devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode 
  **vpp)
  {
          int error;
        struct vnode *vp;
        struct cdev *dev;
        struct devfs_mount *dmp;
 
        dmp = VFSTODEVFS(mp);
  +#if 1
  + retry:
  +#endif
          if (de-de_flags  DE_DOOMED) {
 
             ...
 
          mtx_lock(devfs_de_interlock);
          vp = de-de_vnode;
          if (vp != NULL) {
                  VI_LOCK(vp);
                  mtx_unlock(devfs_de_interlock);
                  sx_xunlock(dmp-dm_lock);
                  error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, curthread);
                  sx_xlock(dmp-dm_lock);
                  if (devfs_allocv_drop_refs(0, dmp, de)) {
                          if (error == 0)
                                  vput(vp);
                          return (ENOENT);
                  }
                  else if (error) {
  +#if 1
  +                     if (error == ENOENT)
  +                             goto retry;
  +#endif
                        sx_xunlock(dmp-dm_lock);
                        return (error);
                }
 
  Thank you for the report.
 
  The proposed change would revert r179247, which also caused some issues.
  Are you able to reproduce the problem ?
 
  Could you try the following patch ? I cannot reproduce your situation,
  so the patch is untested by me.
 
  diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
  index bf6dab8..bbbfff4 100644
  --- a/sys/fs/devfs/devfs_vnops.c
  +++ b/sys/fs/devfs/devfs_vnops.c
  @@ -397,6 +397,7 @@ devfs_allocv(struct devfs_dirent *de, struct mount 
  *mp, int lockmode,
                 sx_xunlock(dmp-dm_lock);
                 return (ENOENT);
         }
  +loop:
         DEVFS_DE_HOLD(de);
         DEVFS_DMP_HOLD(dmp);
         mtx_lock(devfs_de_interlock);
  @@ -412,7 +413,16 @@ devfs_allocv(struct devfs_dirent *de, struct mount 
  *mp, int lockmode,
                                 vput(vp);
                         return (ENOENT);
                 }
  -               else if (error) {
  +               else if (error != 0) {
  +                       if (error == ENOENT) {
  +                               mtx_lock(devfs_de_interlock);
  +                               while (de-de_vnode != NULL) {
  +                                       msleep(de-de_vnode,
  +                                           devfs_de_interlock, 0, 
  dvall, 0);
  +                               }
  +                               mtx_unlock(devfs_de_interlock);
  +                               goto loop;
  +                       }
                         sx_xunlock(dmp-dm_lock);
                         return (error);
                 }
  @@ -1259,6 +1269,7 @@ devfs_reclaim(struct vop_reclaim_args *ap)
         if (de != NULL

Bug about devfs?

2011-07-12 Thread Kohji Okuno
Hello,

I think that devfs has a problem.
I encountered the problem that open(/dev/AAA) returned ENOENT.
Of course, /dev/AAA exists.

ENOENT was created by the point(***) in devfs_allocv().
I think that the race condition had occurred between process A and
vnlru kernel thread.

Please check the following.

If vnlru set VI_DOOMED to vp-v_iflag but vnlru didn't still execute
VOP_RECLAIM(), process A cat get valid vp from de-de_vnode.
But, vget() will return ENOENT, because vp-v_iflag has VI_DOOMED.

When I set the break point to (***), I checked that de-de_vnode and
vp-v_data were NULL.


process A:  vnlru:

devfs_allocv() {
vgonel(vp) {
   ... ...
  vp-v_iflag |= VI_DOOMED;
  mtx_lock(devfs_de_interlock);   ...
  vp = de-de_vnode;  
  if (vp != NULL) {   VI_UNLOCK(vp);
_/ ...
  VI_LOCK(vp); /  if (VOP_RECLAIM(vp, td))
  mtx_unlock(devfs_de_interlock); ...
   ...  \ devfs_reclaim(ap) {
  error = vget(vp,...);  \  
   ...\__   mtx_lock(devfs_de_interlock); 
  if (devfs_allocv_drop_refs(...)) {de = vp-v_data;
... if (de != NULL) {
  }   de-de_vnode = NULL;  
  else if (error) {   vp-v_data = NULL;
... }
rturn (error); (***)mtx_unlock(devfs_de_interlock);
  }   ...
  }



I think that devfs_allocv() should be fixed as below.
How do you think?

devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp)
{
int error;
struct vnode *vp;
struct cdev *dev;
struct devfs_mount *dmp;
 
dmp = VFSTODEVFS(mp);
+#if 1
+ retry:
+#endif
if (de-de_flags  DE_DOOMED) {

   ...

mtx_lock(devfs_de_interlock);
vp = de-de_vnode;
if (vp != NULL) {
VI_LOCK(vp);
mtx_unlock(devfs_de_interlock);
sx_xunlock(dmp-dm_lock);
error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, curthread);
sx_xlock(dmp-dm_lock);
if (devfs_allocv_drop_refs(0, dmp, de)) {
if (error == 0)
vput(vp);
return (ENOENT);
}
else if (error) {
+#if 1
+   if (error == ENOENT)
+   goto retry;
+#endif
sx_xunlock(dmp-dm_lock);
return (error);
}


Thanks,
 Kohji Okuno.

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: Bug about devfs?

2011-07-12 Thread Kohji Okuno
Hello, 

From: Kostik Belousov kostik...@gmail.com
Subject: Re: Bug about devfs?
Date: Tue, 12 Jul 2011 14:19:25 +0300
Message-ID: 20110712111925.gh43...@deviant.kiev.zoral.com.ua
 Thank you for the report.
 
 The proposed change would revert r179247, which also caused some issues.
 Are you able to reproduce the problem ?
 
 Could you try the following patch ? I cannot reproduce your situation,
 so the patch is untested by me.

Thank you for quick your comment.

I think that your change is beter than mine.
I will test it, and I will report the result.


 On Tue, Jul 12, 2011 at 07:10:28PM +0900, Kohji Okuno wrote:
 Hello,
 
 I think that devfs has a problem.
 I encountered the problem that open(/dev/AAA) returned ENOENT.
 Of course, /dev/AAA exists.
 
 ENOENT was created by the point(***) in devfs_allocv().
 I think that the race condition had occurred between process A and
 vnlru kernel thread.
 
 Please check the following.
 
 If vnlru set VI_DOOMED to vp-v_iflag but vnlru didn't still execute
 VOP_RECLAIM(), process A cat get valid vp from de-de_vnode.
 But, vget() will return ENOENT, because vp-v_iflag has VI_DOOMED.
 
 When I set the break point to (***), I checked that de-de_vnode and
 vp-v_data were NULL.
 
 
 process A:   vnlru:
 
 devfs_allocv() {
  vgonel(vp) {
...  ...
vp-v_iflag |= VI_DOOMED;
   mtx_lock(devfs_de_interlock);...
   vp = de-de_vnode;   
   if (vp != NULL) {VI_UNLOCK(vp);
  _/ ...
   VI_LOCK(vp); /  if (VOP_RECLAIM(vp, td))
   mtx_unlock(devfs_de_interlock);  ...
...   \ devfs_reclaim(ap) {
   error = vget(vp,...);   \  
... \__   
 mtx_lock(devfs_de_interlock); 
   if (devfs_allocv_drop_refs(...)) {de = vp-v_data;
 ...  if (de != NULL) {
   }de-de_vnode = NULL;  
   else if (error) {vp-v_data = NULL;
 ...  }
 rturn (error); (***) mtx_unlock(devfs_de_interlock);
   }...
}
 
 
 
 I think that devfs_allocv() should be fixed as below.
 How do you think?
 
 devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp)
 {
 int error;
  struct vnode *vp;
  struct cdev *dev;
  struct devfs_mount *dmp;
  
  dmp = VFSTODEVFS(mp);
 +#if 1
 + retry:
 +#endif
 if (de-de_flags  DE_DOOMED) {
 
...
 
 mtx_lock(devfs_de_interlock);
 vp = de-de_vnode;
 if (vp != NULL) {
 VI_LOCK(vp);
 mtx_unlock(devfs_de_interlock);
 sx_xunlock(dmp-dm_lock);
 error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, curthread);
 sx_xlock(dmp-dm_lock);
 if (devfs_allocv_drop_refs(0, dmp, de)) {
 if (error == 0)
 vput(vp);
 return (ENOENT);
 }
 else if (error) {
 +#if 1
 +if (error == ENOENT)
 +goto retry;
 +#endif
  sx_xunlock(dmp-dm_lock);
  return (error);
  }
 
 Thank you for the report.
 
 The proposed change would revert r179247, which also caused some issues.
 Are you able to reproduce the problem ?
 
 Could you try the following patch ? I cannot reproduce your situation,
 so the patch is untested by me.
 
 diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
 index bf6dab8..bbbfff4 100644
 --- a/sys/fs/devfs/devfs_vnops.c
 +++ b/sys/fs/devfs/devfs_vnops.c
 @@ -397,6 +397,7 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, 
 int lockmode,
   sx_xunlock(dmp-dm_lock);
   return (ENOENT);
   }
 +loop:
   DEVFS_DE_HOLD(de);
   DEVFS_DMP_HOLD(dmp);
   mtx_lock(devfs_de_interlock);
 @@ -412,7 +413,16 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, 
 int lockmode,
   vput(vp);
   return (ENOENT);
   }
 - else if (error) {
 + else if (error != 0) {
 + if (error == ENOENT) {
 + mtx_lock(devfs_de_interlock);
 + while (de-de_vnode != NULL) {
 + msleep(de-de_vnode,
 + devfs_de_interlock, 0, dvall, 0);
 + }
 + mtx_unlock(devfs_de_interlock);
 + goto loop

Re: Bug about devfs?

2011-07-12 Thread Kohji Okuno
Hello,

From: Kostik Belousov kostik...@gmail.com
Date: Tue, 12 Jul 2011 17:57:53 +0300
 On Tue, Jul 12, 2011 at 03:02:44PM +0200, Attilio Rao wrote:
 2011/7/12 Kostik Belousov kostik...@gmail.com:
  On Tue, Jul 12, 2011 at 07:10:28PM +0900, Kohji Okuno wrote:
  Hello,
 
  I think that devfs has a problem.
  I encountered the problem that open(/dev/AAA) returned ENOENT.
  Of course, /dev/AAA exists.
 
  ENOENT was created by the point(***) in devfs_allocv().
  I think that the race condition had occurred between process A and
  vnlru kernel thread.
 
  Please check the following.
 
  If vnlru set VI_DOOMED to vp-v_iflag but vnlru didn't still execute
  VOP_RECLAIM(), process A cat get valid vp from de-de_vnode.
  But, vget() will return ENOENT, because vp-v_iflag has VI_DOOMED.
 
  When I set the break point to (***), I checked that de-de_vnode and
  vp-v_data were NULL.
 
 
  process A:                            vnlru:
 
  devfs_allocv() {
                                        vgonel(vp) {
     ...                                           ...
                                          vp-v_iflag |= VI_DOOMED;
    mtx_lock(devfs_de_interlock);         ...
    vp = de-de_vnode;
    if (vp != NULL) {                     VI_UNLOCK(vp);
                            _/ ...
    VI_LOCK(vp); /              if (VOP_RECLAIM(vp, td))
    mtx_unlock(devfs_de_interlock);       ...
     ...                                \         devfs_reclaim(ap) {
    error = vget(vp,...);                \
     ...                                  \__   
  mtx_lock(devfs_de_interlock);
    if (devfs_allocv_drop_refs(...)) {        de = vp-v_data;
      ...                                           if (de != NULL) {
    }                                         de-de_vnode = NULL;
    else if (error) {                         vp-v_data = NULL;
      ...                                           }
      rturn (error); (***)                  mtx_unlock(devfs_de_interlock);
    }                                         ...
                                          }
 
 
 
  I think that devfs_allocv() should be fixed as below.
  How do you think?
 
  devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode 
  **vpp)
  {
          int error;
        struct vnode *vp;
        struct cdev *dev;
        struct devfs_mount *dmp;
 
        dmp = VFSTODEVFS(mp);
  +#if 1
  + retry:
  +#endif
          if (de-de_flags  DE_DOOMED) {
 
             ...
 
          mtx_lock(devfs_de_interlock);
          vp = de-de_vnode;
          if (vp != NULL) {
                  VI_LOCK(vp);
                  mtx_unlock(devfs_de_interlock);
                  sx_xunlock(dmp-dm_lock);
                  error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, curthread);
                  sx_xlock(dmp-dm_lock);
                  if (devfs_allocv_drop_refs(0, dmp, de)) {
                          if (error == 0)
                                  vput(vp);
                          return (ENOENT);
                  }
                  else if (error) {
  +#if 1
  +                     if (error == ENOENT)
  +                             goto retry;
  +#endif
                        sx_xunlock(dmp-dm_lock);
                        return (error);
                }
 
  Thank you for the report.
 
  The proposed change would revert r179247, which also caused some issues.
  Are you able to reproduce the problem ?
 
  Could you try the following patch ? I cannot reproduce your situation,
  so the patch is untested by me.
 
  diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
  index bf6dab8..bbbfff4 100644
  --- a/sys/fs/devfs/devfs_vnops.c
  +++ b/sys/fs/devfs/devfs_vnops.c
  @@ -397,6 +397,7 @@ devfs_allocv(struct devfs_dirent *de, struct mount 
  *mp, int lockmode,
                 sx_xunlock(dmp-dm_lock);
                 return (ENOENT);
         }
  +loop:
         DEVFS_DE_HOLD(de);
         DEVFS_DMP_HOLD(dmp);
         mtx_lock(devfs_de_interlock);
  @@ -412,7 +413,16 @@ devfs_allocv(struct devfs_dirent *de, struct mount 
  *mp, int lockmode,
                                 vput(vp);
                         return (ENOENT);
                 }
  -               else if (error) {
  +               else if (error != 0) {
  +                       if (error == ENOENT) {
  +                               mtx_lock(devfs_de_interlock);
  +                               while (de-de_vnode != NULL) {
  +                                       msleep(de-de_vnode,
  +                                           devfs_de_interlock, 0, 
  dvall, 0);
  +                               }
  +                               mtx_unlock(devfs_de_interlock);
  +                               goto loop;
  +                       }
                         sx_xunlock(dmp-dm_lock);
                         return (error);
                 }
  @@ -1259,6 +1269,7 @@ devfs_reclaim(struct vop_reclaim_args *ap)
         if (de != NULL

Re: About 32bit binary on amd64

2010-05-24 Thread Kohji Okuno
Thank you for your comments.

In my usage, it works good by the patch appended to this mail.

 On May 24, 2010, at 2:49 AM, pluknet wrote:
 
 On 24 May 2010 08:49, Kohji Okuno okuno.ko...@jp.panasonic.com wrote:
 Hi all,
 
 I want to compile 32bit binary on amd64, but I met with the problem.
 Could you teach me the best solution, please?
 
 
 My environment is FreeBSD 8.1-PRERELEASE #0: Tue May 18 12:01:26 JST 2010.
 
 I compiled and executed test.c as below on amd64.
 
 [...]
 
 % gcc -m32 -B/usr/lib32 test.c
 % ./a.out
 mmap: Invalid argument
 
 AFAIK, it still doesn't work on FreeBSD. You need something like 32bit
 chroot environment.
 There's also about:
 http://www.freebsd.org/projects/ideas/#p-freebsd-amd64-gcc-m32
 
 -m32 is busted on FreeBSD; I don't remember the full details but I think it 
 had something to do with the linking stage of things...
 Thanks,
 -Garrett
diff -Nur machine.org/_inttypes.h machine/_inttypes.h
--- machine.org/_inttypes.h	2009-08-03 17:13:06.0 +0900
+++ machine/_inttypes.h	2010-05-24 10:16:12.130753024 +0900
@@ -37,6 +37,9 @@
  * $FreeBSD: src/sys/amd64/include/_inttypes.h,v 1.3.34.1 2009/08/03 08:13:06 kensmith Exp $
  */
 
+#ifdef __i386__
+#include machine/_inttypes32.h
+#else
 #ifndef _MACHINE_INTTYPES_H_
 #define _MACHINE_INTTYPES_H_
 
@@ -218,3 +221,4 @@
 #define	SCNxPTR		lx	/* uintptr_t */
 
 #endif /* !_MACHINE_INTTYPES_H_ */
+#endif /* __i386__ */
diff -Nur machine.org/_inttypes32.h machine/_inttypes32.h
--- machine.org/_inttypes32.h	1970-01-01 09:00:00.0 +0900
+++ machine/_inttypes32.h	2010-05-24 10:17:17.382704652 +0900
@@ -0,0 +1,220 @@
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *must display the following acknowledgement:
+ *This product includes software developed by the NetBSD
+ *Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $
+ * $FreeBSD: src/sys/i386/include/_inttypes.h,v 1.2.36.1 2009/08/03 08:13:06 kensmith Exp $
+ */
+
+#ifndef _MACHINE_INTTYPES_H_
+#define _MACHINE_INTTYPES_H_
+
+/*
+ * Macros for format specifiers.
+ */
+
+/* fprintf(3) macros for signed integers. */
+
+#define	PRId8		d	/* int8_t */
+#define	PRId16		d	/* int16_t */
+#define	PRId32		d	/* int32_t */
+#define	PRId64		lld	/* int64_t */
+#define	PRIdLEAST8	d	/* int_least8_t */
+#define	PRIdLEAST16	d	/* int_least16_t */
+#define	PRIdLEAST32	d	/* int_least32_t */
+#define	PRIdLEAST64	lld	/* int_least64_t */
+#define	PRIdFAST8	d	/* int_fast8_t */
+#define	PRIdFAST16	d	/* int_fast16_t */
+#define	PRIdFAST32	d	/* int_fast32_t */
+#define	PRIdFAST64	lld	/* int_fast64_t */
+#define	PRIdMAX		jd	/* intmax_t */
+#define	PRIdPTR		d	/* intptr_t */
+
+#define	PRIi8		i	/* int8_t */
+#define	PRIi16		i	/* int16_t */
+#define	PRIi32		i	/* int32_t */
+#define	PRIi64		lli	/* int64_t */
+#define	PRIiLEAST8	i	/* int_least8_t  */
+#define	PRIiLEAST16	i	/* int_least16_t */
+#define	PRIiLEAST32	i	/* int_least32_t */
+#define	PRIiLEAST64	lli	/* int_least64_t */
+#define	PRIiFAST8	i	/* int_fast8_t */
+#define	PRIiFAST16	i	/* int_fast16_t */
+#define	PRIiFAST32	i	/* int_fast32_t */
+#define	PRIiFAST64	lli	/* int_fast64_t */
+#define	PRIiMAX		ji	/* intmax_t */
+#define	PRIiPTR		i	/* intptr_t

About 32bit binary on amd64

2010-05-23 Thread Kohji Okuno
Hi all,

I want to compile 32bit binary on amd64, but I met with the problem.
Could you teach me the best solution, please?


My environment is FreeBSD 8.1-PRERELEASE #0: Tue May 18 12:01:26 JST 2010.

I compiled and executed test.c as below on amd64.

-- begin -- test.c --
#include stdlib.h
#include stdio.h
#include sys/mman.h
#include unistd.h

int main()
{
void *ptr;
ptr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
if (ptr == MAP_FAILED) {
perror(mmap); exit(1);
}
printf(%lx\n, (unsigned long)ptr);
munmap(ptr, 4096);

exit(0);
}
-- end -- test.c 

% gcc -m32 -B/usr/lib32 test.c
% ./a.out
mmap: Invalid argument


I disassembled a.out. I think that 'movl $0x0,0x18(%esp)' is needed.
This error is occured by 'off_t offset'.

 80484ce:   83 ec 34sub$0x34,%esp
 80484d1:   c7 44 24 14 00 00 00movl   $0x0,0x14(%esp)
 80484d8:   00
 80484d9:   c7 44 24 10 ff ff ffmovl   $0x,0x10(%esp)
 80484e0:   ff
 80484e1:   c7 44 24 0c 00 10 00movl   $0x1000,0xc(%esp)
 80484e8:   00
 80484e9:   c7 44 24 08 03 00 00movl   $0x3,0x8(%esp)
 80484f0:   00
 80484f1:   c7 44 24 04 00 10 00movl   $0x1000,0x4(%esp)
 80484f8:   00
 80484f9:   c7 04 24 00 00 00 00movl   $0x0,(%esp)
 8048500:   e8 43 fe ff ff  call   8048348 m...@plt


I found this solution.

I modified machine depended header as below.
# cd /usr/include/machine
# cp /usr/src/sys/i386/include/_types.h _types32.h
# patch  _types.h.diff

-- begin -- _types.h.diff 
--- _types.h.org2010-05-24 13:34:55.406874258 +0900
+++ _types.h2010-05-24 13:35:33.790522354 +0900
@@ -36,6 +36,10 @@
  * $FreeBSD: src/sys/amd64/include/_types.h,v 1.12.2.1 2009/08/03 08:13:06 
kensmith Exp $
  */
 
+#ifdef __i386__
+#include machine/_types32.h
+#else
+
 #ifndef _MACHINE__TYPES_H_
 #define_MACHINE__TYPES_H_
 
@@ -115,3 +119,4 @@
 #endif
 
 #endif /* !_MACHINE__TYPES_H_ */
+#endif /* __i386__ */
-- end -- _types.h.diff --

In this case, 'off_t offset' is set correctly as below.

 80484d1:   c7 44 24 14 00 00 00movl   $0x0,0x14(%esp)
 80484d8:   00
 80484d9:   c7 44 24 18 00 00 00movl   $0x0,0x18(%esp)
 80484e0:   00
 80484e1:   c7 44 24 10 ff ff ffmovl   $0x,0x10(%esp)
 80484e8:   ff
 80484e9:   c7 44 24 0c 00 10 00movl   $0x1000,0xc(%esp)
 80484f0:   00
 80484f1:   c7 44 24 08 03 00 00movl   $0x3,0x8(%esp)
 80484f8:   00
 80484f9:   c7 44 24 04 00 10 00movl   $0x1000,0x4(%esp)
 8048500:   00
 8048501:   c7 04 24 00 00 00 00movl   $0x0,(%esp)
 8048508:   e8 3b fe ff ff  call   8048348 m...@plt



How should we deal with this problem?

Best reards,
 Kohji Okuno
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org