* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Florian Weimer @ 2015-07-21 8:01 UTC (permalink / raw)
To: Mathieu Desnoyers, Linus Torvalds
Cc: Andy Lutomirski, Ben Maurer, Ingo Molnar, libc-alpha,
Andrew Morton, linux-api, Ondřej Bílka, rostedt,
Paul E. McKenney, Josh Triplett, Paul Turner, Andrew Hunter,
Peter Zijlstra
In-Reply-To: <2010227315.699.1437438300542.JavaMail.zimbra-vg+e7yoeK/dWk0Htik3J/w@public.gmane.org>
On 07/21/2015 02:25 AM, Mathieu Desnoyers wrote:
> But I'm inclined to think that some aspect of the question eludes me,
> especially given the amount of interest generated by the gs-segment
> selector approach. What am I missing ?
%gs is not explicitly mentioned in the x86_64 psABI. This probably led
to the assumption that it's unused. I think that's not the right
conclusion to draw.
--
Florian Weimer / Red Hat Product Security
^ permalink raw reply
* Re: [PATCH v4 3/5] pagemap: rework hugetlb and thp report
From: Naoya Horiguchi @ 2015-07-21 8:00 UTC (permalink / raw)
To: Konstantin Khlebnikov
Cc: linux-mm@kvack.org, Andrew Morton, Kirill A. Shutemov,
Mark Williamson, linux-kernel@vger.kernel.org,
linux-api@vger.kernel.org
In-Reply-To: <20150714153738.29844.39039.stgit@buzz>
On Tue, Jul 14, 2015 at 06:37:39PM +0300, Konstantin Khlebnikov wrote:
> This patch moves pmd dissection out of reporting loop: huge pages
> are reported as bunch of normal pages with contiguous PFNs.
>
> Add missing "FILE" bit in hugetlb vmas.
>
> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
With reflecting Kirill's comment about #ifdef, I'm OK for this patch.
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Florian Weimer @ 2015-07-21 7:55 UTC (permalink / raw)
To: josh-iaAMLnmF4UmaiuxdJuQwMA, Andy Lutomirski
Cc: Ben Maurer, Ingo Molnar, libc-alpha, linux-api, Andrew Morton,
Ondřej Bílka, rostedt, Linus Torvalds,
Mathieu Desnoyers, Paul E. McKenney, Lai Jiangshan, Paul Turner,
Andrew Hunter, Peter Zijlstra
In-Reply-To: <20150720200753.GA22333@cloud>
On 07/20/2015 10:07 PM, josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org wrote:
> On Mon, Jul 20, 2015 at 10:41:09AM -0700, Andy Lutomirski wrote:
>> On Mon, Jul 20, 2015 at 8:32 AM, Florian Weimer <fweimer-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>> On 07/20/2015 05:31 PM, Andy Lutomirski wrote:
>>>> On Jul 20, 2015 1:35 AM, "Florian Weimer" <fweimer-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>>>>
>>>>> On 07/18/2015 01:33 AM, Andy Lutomirski wrote:
>>>>>
>>>>>> I think the API should be "set gsbase to x + y*(cpu number)". On
>>>>>> x86_64, userspace just allocates a big swath of virtual space and
>>>>>> populates it as needed.
>>>>>
>>>>> This will break WINE and similar applications which use %gs today.
>>>>
>>>> Presumably WINE could just opt not to use this facility, just like
>>>> WINE will have to opt out of whatever the enterprise people who want
>>>> WRGSBASE were thinking of doing with it.
>>>
>>> How is this possible if it's process-global attribute and glibc or some
>>> library in the process starts using it?
>>>
>>
>> glibc will have to expose a way to turn it off, I guess. (ELF flag?)
>
> Or a way to turn it on.
How is this supposed to work? Who should turn it on?
It totally breaks encapsulation. We don't need any additional problems
like that.
--
Florian Weimer / Red Hat Product Security
^ permalink raw reply
* Re: [PATCH v4 2/5] pagemap: switch to the new format and do some cleanup
From: Naoya Horiguchi @ 2015-07-21 7:44 UTC (permalink / raw)
To: Konstantin Khlebnikov
Cc: linux-mm@kvack.org, Andrew Morton, Kirill A. Shutemov,
Mark Williamson, linux-kernel@vger.kernel.org,
linux-api@vger.kernel.org
In-Reply-To: <20150714153737.29844.33895.stgit@buzz>
On Tue, Jul 14, 2015 at 06:37:37PM +0300, Konstantin Khlebnikov wrote:
> This patch removes page-shift bits (scheduled to remove since 3.11) and
> completes migration to the new bit layout. Also it cleans messy macro.
>
> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Ondřej Bílka @ 2015-07-21 7:30 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Linus Torvalds, Andy Lutomirski, Ben Maurer, Ingo Molnar,
libc-alpha, Andrew Morton, linux-api, rostedt, Paul E. McKenney,
Florian Weimer, Josh Triplett, Lai Jiangshan, Paul Turner,
Andrew Hunter, Peter Zijlstra
In-Reply-To: <2010227315.699.1437438300542.JavaMail.zimbra-vg+e7yoeK/dWk0Htik3J/w@public.gmane.org>
On Tue, Jul 21, 2015 at 12:25:00AM +0000, Mathieu Desnoyers wrote:
> >> Does it solve the Wine problem? If Wine uses gs for something and
> >> calls a function that does this, Wine still goes boom, right?
> >
> > So the advantage of just making a global segment descriptor available
> > is that it's not *that* expensive to just save/restore segments. So
> > either wine could do it, or any library users would do it.
> >
> > But anyway, I'm not sure this is a good idea. The advantage of it is
> > that the kernel support really is _very_ minimal.
>
> Considering that we'd at least also want this feature on ARM and
> PowerPC 32/64, and that the gs segment selector approach clashes with
> existing apps (wine), I'm not sure that implementing a gs segment
> selector based approach to cpu number caching would lead to an overall
> decrease in complexity if it leads to performance similar to those of
> portable approaches.
>
> I'm perfectly fine with architecture-specific tweaks that lead to
> fast-path speedups, but if we have to bite the bullet and implement
> an approach based on TLS and registering a memory area at thread start
> through a system call on other architectures anyway, it might end up
> being less complex to add a new system call on x86 too, especially if
> fast path overhead is similar.
>
> But I'm inclined to think that some aspect of the question eludes me,
> especially given the amount of interest generated by the gs-segment
> selector approach. What am I missing ?
>
As I wrote before you don't have to bite bullet as I said before. It
suffices to create 128k element array with cpu for each tid, make that
mmapable file and userspace could get cpu with nearly same performance
without hacks.
^ permalink raw reply
* Re: [PATCH v3 01/10] mm/hugetlb: add cache of descriptors to resv_map for region_add
From: Naoya Horiguchi @ 2015-07-21 4:16 UTC (permalink / raw)
To: Mike Kravetz
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
linux-api@vger.kernel.org, Dave Hansen, David Rientjes,
Hugh Dickins, Davidlohr Bueso, Aneesh Kumar, Hillf Danton,
Christoph Hellwig, Andrew Morton, Michal Hocko
In-Reply-To: <55AD34D4.2020804@oracle.com>
On Mon, Jul 20, 2015 at 10:50:12AM -0700, Mike Kravetz wrote:
...
> > ...
> >> @@ -3236,11 +3360,14 @@ retry:
> >> * any allocations necessary to record that reservation occur outside
> >> * the spinlock.
> >> */
> >> - if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED))
> >> + if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) {
> >> if (vma_needs_reservation(h, vma, address) < 0) {
> >> ret = VM_FAULT_OOM;
> >> goto backout_unlocked;
> >> }
> >> + /* Just decrements count, does not deallocate */
> >> + vma_abort_reservation(h, vma, address);
> >> + }
> >
> > This is not "abort reservation" operation, but you use "abort reservation"
> > routine, which might confusing and makes future maintenance hard. I think
> > this should be done in a simplified variant of vma_commit_reservation()
> > (maybe just an alias of your vma_abort_reservation()) or fast path in
> > vma_commit_reservation().
>
> I am struggling a bit with the names of these routines. The
> routines in question are:
>
> vma_needs_reservation - This is a wrapper for region_chg(), so the
> return value is the number of regions needed for the page.
> Since there is only one page, the routine effectively
> becomes a boolean. Hence the name "needs".
>
> vma_commit_reservation - This is a wrapper for region_add(). It
> must be called after a prior call to vma_needs_reservation
> and after actual allocation of the page.
>
> We need a way to handle the case where vma_needs_reservation has
> been called, but the page allocation is not successful. I chose
> the name vma_abort_reservation, but as noted (even in my comments)
> it is not an actual abort.
>
> I am not sure if you are suggesting vma_commit_reservation() should
> handle this as a special case. I think a separately named routine which
> indicates and end of the reservation/allocation process would be
> easier to understand.
>
> What about changing the name vma_abort_reservation() to
> vma_end_reservation()? This would indicate that the reservation/
> allocation process is ended.
OK, vma_end_reservation() sounds nice to me.
> > Thanks,
> > Naoya Horiguchi
>
> Thank you for your reviews.
You're welcome :)
Naoya Horiguchi
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* RE: [PATCH v3 00/10] hugetlbfs: add fallocate support
From: Hillf Danton @ 2015-07-21 3:08 UTC (permalink / raw)
To: 'Mike Kravetz', linux-mm, linux-kernel, linux-api
Cc: 'Dave Hansen', 'Naoya Horiguchi',
'David Rientjes', 'Hugh Dickins',
'Davidlohr Bueso', 'Aneesh Kumar',
'Christoph Hellwig', 'Andrew Morton',
'Michal Hocko'
In-Reply-To: <1436761268-6397-1-git-send-email-mike.kravetz@oracle.com>
>
> Only change in this revision is the fix to the self-discovered
> issue in region_chg(). Functional and stress tests passing.
> Full changelog below.
>
> As suggested during the RFC process, tests have been proposed to
> libhugetlbfs as described at:
> http://librelist.com/browser//libhugetlbfs/2015/6/25/patch-tests-add-tests-for-fallocate-system-call/
> fallocate(2) man page modifications are also necessary to specify
> that fallocate for hugetlbfs only operates on whole pages. This
> change will be submitted once the code has stabilized and been
> proposed for merging.
>
> hugetlbfs is used today by applications that want a high degree of
> control over huge page usage. Often, large hugetlbfs files are used
> to map a large number huge pages into the application processes.
> The applications know when page ranges within these large files will
> no longer be used, and ideally would like to release them back to
> the subpool or global pools for other uses. The fallocate() system
> call provides an interface for preallocation and hole punching within
> files. This patch set adds fallocate functionality to hugetlbfs.
>
> v3:
> Fixed issue with region_chg to recheck if there are sufficient
> entries in the cache after acquiring lock.
> v2:
> Fixed leak in resv_map_release discovered by Hillf Danton.
> Used LONG_MAX as indicator of truncate function for region_del.
> v1:
> Add a cache of region descriptors to the resv_map for use by
> region_add in case hole punch deletes entries necessary for
> a successful operation.
> RFC v4:
> Removed alloc_huge_page/hugetlb_reserve_pages race patches as already
> in mmotm
> Moved hugetlb_fix_reserve_counts in series as suggested by Naoya Horiguchi
> Inline'ed hugetlb_fault_mutex routines as suggested by Davidlohr Bueso and
> existing code changed to use new interfaces as suggested by Naoya
> fallocate preallocation code cleaned up and made simpler
> Modified alloc_huge_page to handle special case where allocation is
> for a hole punched area with spool reserves
> RFC v3:
> Folded in patch for alloc_huge_page/hugetlb_reserve_pages race
> in current code
> fallocate allocation and hole punch is synchronized with page
> faults via existing mutex table
> hole punch uses existing hugetlb_vmtruncate_list instead of more
> generic unmap_mapping_range for unmapping
> Error handling for the case when region_del() fauils
> RFC v2:
> Addressed alignment and error handling issues noticed by Hillf Danton
> New region_del() routine for region tracking/resv_map of ranges
> Fixed several issues found during more extensive testing
> Error handling in region_del() when kmalloc() fails stills needs
> to be addressed
> madvise remove support remains
>
> Mike Kravetz (10):
> mm/hugetlb: add cache of descriptors to resv_map for region_add
> mm/hugetlb: add region_del() to delete a specific range of entries
> mm/hugetlb: expose hugetlb fault mutex for use by fallocate
> hugetlbfs: hugetlb_vmtruncate_list() needs to take a range to delete
> hugetlbfs: truncate_hugepages() takes a range of pages
> mm/hugetlb: vma_has_reserves() needs to handle fallocate hole punch
> mm/hugetlb: alloc_huge_page handle areas hole punched by fallocate
> hugetlbfs: New huge_add_to_page_cache helper routine
> hugetlbfs: add hugetlbfs_fallocate()
> mm: madvise allow remove operation for hugetlbfs
>
> fs/hugetlbfs/inode.c | 281 +++++++++++++++++++++++++++++---
> include/linux/hugetlb.h | 17 +-
> mm/hugetlb.c | 423 ++++++++++++++++++++++++++++++++++++++----------
> mm/madvise.c | 2 +-
> 4 files changed, 619 insertions(+), 104 deletions(-)
>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH] selftests/futex: Fix futex_cmp_requeue_pi() error handling
From: Shuah Khan @ 2015-07-21 0:34 UTC (permalink / raw)
To: Darren Hart, Linux Kernel Mailing List
Cc: David Binderman, Linux API Mailing List
In-Reply-To: <e45eef3361e23760f2fa8750d0468d7ec021db6d.1437432376.git.dvhart@infradead.org>
On 07/20/2015 04:48 PM, Darren Hart wrote:
> An earlier (pre-kernel-integration) refactoring of this code mistakenly
> replaced the error condition, <, with a >. Use < to detect an error as
> opposed to a successful requeue or signal race.
>
> Reported-by: David Binderman <dcb314@hotmail.com>
> Cc: Shuah Khan <shuahkh@osg.samsung.com>
> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
> ---
> .../selftests/futex/functional/futex_requeue_pi_signal_restart.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
> index 7f0c756..3d7dc6a 100644
> --- a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
> +++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
> @@ -191,7 +191,7 @@ int main(int argc, char *argv[])
> if (res > 0) {
> atomic_set(&requeued, 1);
> break;
> - } else if (res > 0) {
> + } else if (res < 0) {
> error("FUTEX_CMP_REQUEUE_PI failed\n", errno);
> ret = RET_ERROR;
> break;
>
Daren,
That is quick. Applied to linux-kselftest fixes for 4.2
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
^ permalink raw reply
* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Mathieu Desnoyers @ 2015-07-21 0:25 UTC (permalink / raw)
To: Linus Torvalds
Cc: Andy Lutomirski, Ben Maurer, Ingo Molnar, libc-alpha,
Andrew Morton, linux-api, Ondřej Bílka, rostedt,
Paul E. McKenney, Florian Weimer, Josh Triplett, Lai Jiangshan,
Paul Turner, Andrew Hunter, Peter Zijlstra
In-Reply-To: <CA+55aFwLZLeeN7UN82dyt=emQcNBc8qZPJAw5iqtAbBwFA7FPQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
----- On Jul 20, 2015, at 6:39 PM, Linus Torvalds torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org wrote:
> On Mon, Jul 20, 2015 at 2:09 PM, Andy Lutomirski <luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org> wrote:
>>
>> Annoying problem one: the segment base field is only 32 bits in the GDT.
>
> Ok. So if we go this way, we'd make the rule be something like "the
> segment base is the CPU number shifted up by the page size", and then
> you'd have to add some magic offset that we'd declare as the "per-cpu
> page offset".
>
>>> - user space can just load the segment selector in %gs
>>
>> IIRC this is very expensive -- 40 cycles or so. At this point
>> userspace might as well just use a real lock cmpxchg.
>
> So cmpxchg may be as many cycles, but
>
> (a) you can choose to load the segment just once, and do several
> operations with it
>
> (b) often - but admittedly not always - the real cost of a
> non-cpu-local local and cmpxchg tends to be the cacheline ping-pong,
> not the CPU cycles.
>
> so I agree, loading a segment isn't free. But it's not *that*
> expensive, and you could always decide to keep the segment loaded and
> just do
>
> - read segment selector
> - if NUL segment, reload it.
>
> although that only works if you own the segment entirely and can keep
> it as the percpu segment (ie obviously not the Wine case, for
> example).
>
>> Does it solve the Wine problem? If Wine uses gs for something and
>> calls a function that does this, Wine still goes boom, right?
>
> So the advantage of just making a global segment descriptor available
> is that it's not *that* expensive to just save/restore segments. So
> either wine could do it, or any library users would do it.
>
> But anyway, I'm not sure this is a good idea. The advantage of it is
> that the kernel support really is _very_ minimal.
Considering that we'd at least also want this feature on ARM and
PowerPC 32/64, and that the gs segment selector approach clashes with
existing apps (wine), I'm not sure that implementing a gs segment
selector based approach to cpu number caching would lead to an overall
decrease in complexity if it leads to performance similar to those of
portable approaches.
I'm perfectly fine with architecture-specific tweaks that lead to
fast-path speedups, but if we have to bite the bullet and implement
an approach based on TLS and registering a memory area at thread start
through a system call on other architectures anyway, it might end up
being less complex to add a new system call on x86 too, especially if
fast path overhead is similar.
But I'm inclined to think that some aspect of the question eludes me,
especially given the amount of interest generated by the gs-segment
selector approach. What am I missing ?
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply
* Re: [RFC ebeam PATCH 2/2] input: misc: New USB eBeam input driver
From: Dmitry Torokhov @ 2015-07-20 23:09 UTC (permalink / raw)
To: Greg KH
Cc: Yann Cantin, linux-input, linux-usb, linux-kernel, linux-api,
jkosina
In-Reply-To: <20150720224033.GA23884@kroah.com>
On Mon, Jul 20, 2015 at 03:40:33PM -0700, Greg KH wrote:
> On Mon, Jul 20, 2015 at 03:26:40PM -0700, Dmitry Torokhov wrote:
> > On Mon, Jul 20, 2015 at 02:59:56PM -0700, Greg KH wrote:
> > > On Mon, Jul 20, 2015 at 11:03:19PM +0200, Yann Cantin wrote:
> > > > Signed-off-by: Yann Cantin <yann.cantin@laposte.net>
> > >
> > > > +
> > > > + /* sysfs setup */
> > > > + err = sysfs_create_group(&intf->dev.kobj, &ebeam_attr_group);
> > >
> > > Ick, you just added the sysfs files to the USB device, not your input
> > > device, are you sure you tested this?
> > >
> > > And there should be a race-free way to add an attribute group to an
> > > input device, as this is, you are adding them to the device _after_ it
> > > is created, so userspace will not see them at creation time, causing a
> > > race.
> >
> > No, there are no driver-specific attributed on input devices themselves,
> > they belong to the actual hardware devices. The input devices only
> > export standard attributes applicable to every and all input devices
> > in the system.
>
> Then the Documentation in this patch better be fixed up, as it points to
> the input device as having these sysfs files :)
>
> But as these are input device attributes, and not USB device interface
> attributes, putting them on the USB interface doesn't make much sense,
> and as I pointed out, is racy. Why can't input devices have
> driver-specific attributes? Why does input devices add their own
> attributes sometimes (like in psmouse, which does so in a racy way) yet
> this driver shouldn't do that?
>
> Hm, nevermind about psmouse, that happens on the parent device too it
> seems (a serio device), not the input device, so it is "consistent", but
> not something I really like...
I think it is historical as quite often they (attributes) affect the
hardware itself, not behavior of input interface. And so they were
always placed on hardware level, not input device level.
Anyway, I do not think you are going to win your war on sysfs attributes
created post-device creation. We just need to recognize that there are
attributes that are created by the driver when it is bound to the
device. Maybe we need to revisit the idea about emitting special uevent
when driver is fully bound to a device and interested userspace can
start using it.
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH] selftests/futex: Fix futex_cmp_requeue_pi() error handling
From: Darren Hart @ 2015-07-20 22:48 UTC (permalink / raw)
To: Linux Kernel Mailing List
Cc: Shuah Khan, David Binderman, Linux API Mailing List
An earlier (pre-kernel-integration) refactoring of this code mistakenly
replaced the error condition, <, with a >. Use < to detect an error as
opposed to a successful requeue or signal race.
Reported-by: David Binderman <dcb314-PkbjNfxxIARBDgjK7y7TUQ@public.gmane.org>
Cc: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
Signed-off-by: Darren Hart <dvhart-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
.../selftests/futex/functional/futex_requeue_pi_signal_restart.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
index 7f0c756..3d7dc6a 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
@@ -191,7 +191,7 @@ int main(int argc, char *argv[])
if (res > 0) {
atomic_set(&requeued, 1);
break;
- } else if (res > 0) {
+ } else if (res < 0) {
error("FUTEX_CMP_REQUEUE_PI failed\n", errno);
ret = RET_ERROR;
break;
--
2.1.4
--
Darren Hart
Intel Open Source Technology Center
^ permalink raw reply related
* Re: [RFC ebeam PATCH 2/2] input: misc: New USB eBeam input driver
From: Greg KH @ 2015-07-20 22:40 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Yann Cantin, linux-input, linux-usb, linux-kernel, linux-api,
jkosina
In-Reply-To: <20150720222640.GD30252@dtor-ws>
On Mon, Jul 20, 2015 at 03:26:40PM -0700, Dmitry Torokhov wrote:
> On Mon, Jul 20, 2015 at 02:59:56PM -0700, Greg KH wrote:
> > On Mon, Jul 20, 2015 at 11:03:19PM +0200, Yann Cantin wrote:
> > > Signed-off-by: Yann Cantin <yann.cantin@laposte.net>
> >
> > > +
> > > + /* sysfs setup */
> > > + err = sysfs_create_group(&intf->dev.kobj, &ebeam_attr_group);
> >
> > Ick, you just added the sysfs files to the USB device, not your input
> > device, are you sure you tested this?
> >
> > And there should be a race-free way to add an attribute group to an
> > input device, as this is, you are adding them to the device _after_ it
> > is created, so userspace will not see them at creation time, causing a
> > race.
>
> No, there are no driver-specific attributed on input devices themselves,
> they belong to the actual hardware devices. The input devices only
> export standard attributes applicable to every and all input devices
> in the system.
Then the Documentation in this patch better be fixed up, as it points to
the input device as having these sysfs files :)
But as these are input device attributes, and not USB device interface
attributes, putting them on the USB interface doesn't make much sense,
and as I pointed out, is racy. Why can't input devices have
driver-specific attributes? Why does input devices add their own
attributes sometimes (like in psmouse, which does so in a racy way) yet
this driver shouldn't do that?
Hm, nevermind about psmouse, that happens on the parent device too it
seems (a serio device), not the input device, so it is "consistent", but
not something I really like...
thanks,
greg k-h
^ permalink raw reply
* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Linus Torvalds @ 2015-07-20 22:39 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Ben Maurer, Ingo Molnar, libc-alpha, Andrew Morton, linux-api,
Ondřej Bílka, rostedt, Mathieu Desnoyers,
Paul E. McKenney, Florian Weimer, Josh Triplett, Lai Jiangshan,
Paul Turner, Andrew Hunter, Peter Zijlstra
In-Reply-To: <CALCETrUZ8vB30rdmeoV4JKPUsRnVPvoxXRJ47CEFud2aSF2=Ew@mail.gmail.com>
On Mon, Jul 20, 2015 at 2:09 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>
> Annoying problem one: the segment base field is only 32 bits in the GDT.
Ok. So if we go this way, we'd make the rule be something like "the
segment base is the CPU number shifted up by the page size", and then
you'd have to add some magic offset that we'd declare as the "per-cpu
page offset".
>> - user space can just load the segment selector in %gs
>
> IIRC this is very expensive -- 40 cycles or so. At this point
> userspace might as well just use a real lock cmpxchg.
So cmpxchg may be as many cycles, but
(a) you can choose to load the segment just once, and do several
operations with it
(b) often - but admittedly not always - the real cost of a
non-cpu-local local and cmpxchg tends to be the cacheline ping-pong,
not the CPU cycles.
so I agree, loading a segment isn't free. But it's not *that*
expensive, and you could always decide to keep the segment loaded and
just do
- read segment selector
- if NUL segment, reload it.
although that only works if you own the segment entirely and can keep
it as the percpu segment (ie obviously not the Wine case, for
example).
> Does it solve the Wine problem? If Wine uses gs for something and
> calls a function that does this, Wine still goes boom, right?
So the advantage of just making a global segment descriptor available
is that it's not *that* expensive to just save/restore segments. So
either wine could do it, or any library users would do it.
But anyway, I'm not sure this is a good idea. The advantage of it is
that the kernel support really is _very_ minimal.
Linus
^ permalink raw reply
* Re: [RFC ebeam PATCH 2/2] input: misc: New USB eBeam input driver
From: Dmitry Torokhov @ 2015-07-20 22:26 UTC (permalink / raw)
To: Greg KH
Cc: Yann Cantin, linux-input, linux-usb, linux-kernel, linux-api,
jkosina
In-Reply-To: <20150720215956.GA21796@kroah.com>
On Mon, Jul 20, 2015 at 02:59:56PM -0700, Greg KH wrote:
> On Mon, Jul 20, 2015 at 11:03:19PM +0200, Yann Cantin wrote:
> > Signed-off-by: Yann Cantin <yann.cantin@laposte.net>
>
> > +
> > + /* sysfs setup */
> > + err = sysfs_create_group(&intf->dev.kobj, &ebeam_attr_group);
>
> Ick, you just added the sysfs files to the USB device, not your input
> device, are you sure you tested this?
>
> And there should be a race-free way to add an attribute group to an
> input device, as this is, you are adding them to the device _after_ it
> is created, so userspace will not see them at creation time, causing a
> race.
No, there are no driver-specific attributed on input devices themselves,
they belong to the actual hardware devices. The input devices only
export standard attributes applicable to every and all input devices
in the system.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [RFC ebeam PATCH 2/2] input: misc: New USB eBeam input driver
From: Greg KH @ 2015-07-20 21:59 UTC (permalink / raw)
To: Yann Cantin
Cc: linux-input, linux-usb, linux-kernel, linux-api, dmitry.torokhov,
jkosina
In-Reply-To: <1437426199-29866-3-git-send-email-yann.cantin@laposte.net>
On Mon, Jul 20, 2015 at 11:03:19PM +0200, Yann Cantin wrote:
> Signed-off-by: Yann Cantin <yann.cantin@laposte.net>
You need some kind of text in the changelog here...
> ---
> Documentation/ABI/testing/sysfs-driver-ebeam | 53 ++
> drivers/input/misc/Kconfig | 22 +
> drivers/input/misc/Makefile | 1 +
> drivers/input/misc/ebeam.c | 777 +++++++++++++++++++++++++++
> 4 files changed, 853 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-driver-ebeam
> create mode 100644 drivers/input/misc/ebeam.c
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ebeam b/Documentation/ABI/testing/sysfs-driver-ebeam
> new file mode 100644
> index 0000000..6873db5
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-driver-ebeam
> @@ -0,0 +1,53 @@
> +What: /sys/class/input/inputXX/device/min_x
> + /sys/class/input/inputXX/device/min_y
> + /sys/class/input/inputXX/device/max_x
> + /sys/class/input/inputXX/device/max_y
> +Date: Jul 2015
> +Kernel Version: 4.1
> +Contact: yann.cantin@laposte.net
> + linux-usb@vger.kernel.org
> +Description:
> + Reading from these files return the actually used range values of
> + the reported coordinates.
> + Writing to these files preset these range values.
> + See below for the calibration procedure.
> +
> +What: /sys/class/input/inputXX/device/h[1..9]
> +Date: Jul 2015
> +Kernel Version: 4.1
> +Contact: yann.cantin@laposte.net
> + linux-usb@vger.kernel.org
> +Description:
> + Reading from these files return the 3x3 transformation matrix elements
> + actually used, in row-major.
> + Writing to these files preset these elements values.
> + See below for the calibration procedure.
> +
> +What: /sys/class/input/inputXX/device/calibrated
> +Date: Jul 2015
> +Kernel Version: 4.1
> +Contact: yann.cantin@laposte.net
> + linux-usb@vger.kernel.org
> +Description:
> + Reading from this file :
> + - Return 0 if the driver is in "un-calibrated" mode : it actually send
> + raw coordinates in the device's internal coordinates system.
> + - Return 1 if the driver is in "calibrated" mode : it send computed coordinates
> + that (hopefully) matches the screen's coordinates system.
> + Writing 1 to this file enable the "calibrated" mode, 0 reset the driver in
> + "un-calibrated" mode.
> +
> +Calibration procedure :
> +
> +When loaded, the driver is in "un-calibrated" mode : it send device's raw coordinates
> +in the [0..65535]x[0..65535] range, the transformation matrix is the identity.
> +
> +A calibration program have to compute a homography transformation matrix that convert
> +the device's raw coordinates to the matching screen's ones.
> +It then write to the appropriate sysfs files the computed values, pre-setting the
> +driver's parameters : xy range, and the matrix's elements.
> +When all values are passed, it write 1 to the calibrated sysfs file to enable the "calibrated" mode.
> +
> +Warning : The parameters aren't used until 1 is writen to the calibrated sysfs file.
> +
> +Writing 0 to the calibrated sysfs file reset the driver in "un-calibrated" mode.
What tool(s) use these sysfs files? Don't we already have "normal"
events for these types of things such that we don't have to make up new
sysfs files for these?
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index d4f0a81..22c46a4 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -103,6 +103,28 @@ config INPUT_E3X0_BUTTON
> To compile this driver as a module, choose M here: the
> module will be called e3x0_button.
>
> +config INPUT_EBEAM_USB
> + tristate "USB eBeam driver"
> + depends on USB_ARCH_HAS_HCD
> + select USB
> + help
> + Say Y here if you have a USB eBeam pointing device and want to
> + use it without any proprietary user space tools.
> +
> + Have a look at <http://ebeam.tuxfamily.org/> for
> + a usage description and the required user-space tools.
> +
> + Supported devices :
> + - Luidia eBeam Classic Projection and eBeam Edge Projection
> + - Nec NP01Wi1 & NP01Wi2 interactive solution
> +
> + Supposed working devices, need test, may lack functionality :
> + - Luidia eBeam Edge Whiteboard and eBeam Engage
> + - Hitachi Starboard FX-63, FX-77, FX-82, FX-77GII
> +
> + To compile this driver as a module, choose M here: the
> + module will be called ebeam.
> +
> config INPUT_PCSPKR
> tristate "PC Speaker support"
> depends on PCSPKR_PLATFORM
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index 53df07d..125f8a9 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o
> obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o
> obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
> obj-$(CONFIG_INPUT_E3X0_BUTTON) += e3x0-button.o
> +obj-$(CONFIG_INPUT_EBEAM_USB) += ebeam.o
> obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o
> obj-$(CONFIG_INPUT_DRV2665_HAPTICS) += drv2665.o
> obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o
> diff --git a/drivers/input/misc/ebeam.c b/drivers/input/misc/ebeam.c
> new file mode 100644
> index 0000000..79cac51
> --- /dev/null
> +++ b/drivers/input/misc/ebeam.c
> @@ -0,0 +1,777 @@
> +/******************************************************************************
> + *
> + * eBeam driver
> + *
> + * Copyright (C) 2012-2015 Yann Cantin (yann.cantin@laposte.net)
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * based on
> + *
> + * usbtouchscreen.c by Daniel Ritz <daniel.ritz@gmx.ch>
> + * aiptek.c (sysfs/settings) by Chris Atenasio <chris@crud.net>
> + * Bryan W. Headley <bwheadley@earthlink.net>
> + *
> + *****************************************************************************/
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/math64.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/usb.h>
> +#include <linux/usb/input.h>
> +#include <asm/unaligned.h>
> +
> +#define DRIVER_AUTHOR "Yann Cantin <yann.cantin@laposte.net>"
> +#define DRIVER_DESC "USB eBeam Driver"
> +
> +/* Common values for eBeam devices */
> +#define REPT_SIZE 8 /* packet size */
> +#define MIN_RAW_X 0 /* raw coordinates ranges */
> +#define MAX_RAW_X 0xFFFF
> +#define MIN_RAW_Y 0
> +#define MAX_RAW_Y 0xFFFF
> +
> +/* Electronics For Imaging, Inc */
> +#define USB_VENDOR_ID_EFI 0x2650
> +
> +/* eBeam hardware : */
> +/* Luidia Classic and Edge */
> +/* Nec NP01Wi1 & NP01Wi2 */
> +#define USB_DEVICE_ID_EFI_EBEAM_USB1 0x1311
> +/* From https://github.com/dpiquet */
> +/* Need confirmation */
> +#define USB_DEVICE_ID_EFI_EBEAM_USB2 0x1315
> +#define USB_DEVICE_ID_EFI_EBEAM_BT_USB1 0x1313
> +#define USB_DEVICE_ID_EFI_EBEAM_BT_USB2 0x1320
> +
> +#define EBEAM_BTN_TIP 0x1 /* tip */
> +#define EBEAM_BTN_LIT 0x2 /* little */
> +#define EBEAM_BTN_BIG 0x4 /* big */
> +
> +/* ebeam settings */
> +struct ebeam_settings {
> + int min_x; /* computed coordinates ranges for the input layer */
> + int max_x;
> + int min_y;
> + int max_y;
> +
> + /* H matrix */
> + s64 h1;
> + s64 h2;
> + s64 h3;
> + s64 h4;
> + s64 h5;
> + s64 h6;
> + s64 h7;
> + s64 h8;
> + s64 h9;
> +};
> +
> +/* ebeam device */
> +struct ebeam_device {
> + unsigned char *data;
> + dma_addr_t data_dma;
> + unsigned char *buffer;
> + int buf_len;
> + struct urb *irq;
> + struct usb_interface *interface;
> + struct input_dev *input;
> + char name[128];
> + char phys[64];
> + void *priv;
> +
> + struct ebeam_settings cursetting; /* device's current settings */
> + struct ebeam_settings newsetting; /* ... and new ones */
> +
> + bool calibrated; /* false : send raw */
> + /* true : send computed */
> +
> + u16 raw_x; /* raw coordinates */
> + u16 raw_y;
> + int x; /* computed coordinates */
> + int y;
> + int btn_map; /* internal buttons map */
> +};
> +
> +/* device types */
> +enum {
> + DEVTYPE_EBEAM,
> +};
> +
> +static const struct usb_device_id ebeam_devices[] = {
> + {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB1),
> + .driver_info = DEVTYPE_EBEAM},
> + {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB2),
> + .driver_info = DEVTYPE_EBEAM},
> + {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB1),
> + .driver_info = DEVTYPE_EBEAM},
> + {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB2),
> + .driver_info = DEVTYPE_EBEAM},
> + {}
> +};
> +
> +static void ebeam_init_settings(struct ebeam_device *ebeam)
> +{
> + ebeam->calibrated = false;
> +
> + /* Init (x,y) min/max to raw ones */
> + ebeam->cursetting.min_x = ebeam->newsetting.min_x = MIN_RAW_X;
> + ebeam->cursetting.max_x = ebeam->newsetting.max_x = MAX_RAW_X;
> + ebeam->cursetting.min_y = ebeam->newsetting.min_y = MIN_RAW_Y;
> + ebeam->cursetting.max_y = ebeam->newsetting.max_y = MAX_RAW_Y;
> +
> + /* Safe values for the H matrix (Identity) */
> + ebeam->cursetting.h1 = ebeam->newsetting.h1 = 1;
> + ebeam->cursetting.h2 = ebeam->newsetting.h2 = 0;
> + ebeam->cursetting.h3 = ebeam->newsetting.h3 = 0;
> +
> + ebeam->cursetting.h4 = ebeam->newsetting.h4 = 0;
> + ebeam->cursetting.h5 = ebeam->newsetting.h5 = 1;
> + ebeam->cursetting.h6 = ebeam->newsetting.h6 = 0;
> +
> + ebeam->cursetting.h7 = ebeam->newsetting.h7 = 0;
> + ebeam->cursetting.h8 = ebeam->newsetting.h8 = 0;
> + ebeam->cursetting.h9 = ebeam->newsetting.h9 = 1;
> +}
> +
> +static void ebeam_setup_input(struct ebeam_device *ebeam,
> + struct input_dev *input_dev)
> +{
> + unsigned long flags;
> +
> + /* Take event lock while modifying parameters */
> + spin_lock_irqsave(&input_dev->event_lock, flags);
> +
> + /* Properties */
> + set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
> +
> + /* Events generated */
> + set_bit(EV_KEY, input_dev->evbit);
> + set_bit(EV_ABS, input_dev->evbit);
> +
> + /* Keys */
> + set_bit(BTN_LEFT, input_dev->keybit);
> + set_bit(BTN_MIDDLE, input_dev->keybit);
> + set_bit(BTN_RIGHT, input_dev->keybit);
> +
> + /* Axis */
> + if (!ebeam->calibrated) {
> + ebeam->cursetting.min_x = MIN_RAW_X;
> + ebeam->cursetting.max_x = MAX_RAW_X;
> + ebeam->cursetting.min_y = MIN_RAW_Y;
> + ebeam->cursetting.max_y = MAX_RAW_Y;
> + }
> +
> + input_set_abs_params(input_dev, ABS_X,
> + ebeam->cursetting.min_x, ebeam->cursetting.max_x,
> + 0, 0);
> + input_set_abs_params(input_dev, ABS_Y,
> + ebeam->cursetting.min_y, ebeam->cursetting.max_y,
> + 0, 0);
> +
> + spin_unlock_irqrestore(&input_dev->event_lock, flags);
> +}
> +
> +/*******************************************************************************
> + * sysfs part
> + */
> +
> +/*
> + * screen min/max and H matrix coefs
> + * _get return *current* value
> + * _set set new value
> + */
> +#define DEVICE_MINMAX_ATTR(MM) \
> +static ssize_t ebeam_##MM##_get(struct device *dev, \
> + struct device_attribute *attr, \
> + char *buf) \
> +{ \
> + struct ebeam_device *ebeam = dev_get_drvdata(dev); \
> + \
> + return snprintf(buf, PAGE_SIZE, "%d\n", ebeam->cursetting.MM); \
> +} \
> +static ssize_t ebeam_##MM##_set(struct device *dev, \
> + struct device_attribute *attr, \
> + const char *buf, \
> + size_t count) \
> +{ \
> + struct ebeam_device *ebeam = dev_get_drvdata(dev); \
> + int err, MM; \
> + \
> + err = kstrtoint(buf, 10, &MM); \
> + if (err) \
> + return err; \
> + \
> + ebeam->newsetting.MM = MM; \
> + return count; \
> +} \
> +static DEVICE_ATTR(MM, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, \
> + ebeam_##MM##_get, \
> + ebeam_##MM##_set)
DEVICE_ATTR_RW()?
> +
> +DEVICE_MINMAX_ATTR(min_x);
> +DEVICE_MINMAX_ATTR(max_x);
> +DEVICE_MINMAX_ATTR(min_y);
> +DEVICE_MINMAX_ATTR(max_y);
> +
> +#define DEVICE_H_ATTR(SET_ID) \
> +static ssize_t ebeam_h##SET_ID##_get(struct device *dev, \
> + struct device_attribute *attr, \
> + char *buf) \
> +{ \
> + struct ebeam_device *ebeam = dev_get_drvdata(dev); \
> + \
> + return snprintf(buf, PAGE_SIZE, "%lld\n", ebeam->cursetting.h##SET_ID);\
> +} \
> +static ssize_t ebeam_h##SET_ID##_set(struct device *dev, \
> + struct device_attribute *attr, \
> + const char *buf, \
> + size_t count) \
> +{ \
> + struct ebeam_device *ebeam = dev_get_drvdata(dev); \
> + int err; \
> + u64 h; \
> + \
> + err = kstrtoll(buf, 10, &h); \
> + if (err) \
> + return err; \
> + \
> + ebeam->newsetting.h##SET_ID = h; \
> + return count; \
> +} \
> +static DEVICE_ATTR(h##SET_ID, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, \
> + ebeam_h##SET_ID##_get, \
> + ebeam_h##SET_ID##_set)
DEVICE_ATTR_RW()?
> +
> +DEVICE_H_ATTR(1);
> +DEVICE_H_ATTR(2);
> +DEVICE_H_ATTR(3);
> +DEVICE_H_ATTR(4);
> +DEVICE_H_ATTR(5);
> +DEVICE_H_ATTR(6);
> +DEVICE_H_ATTR(7);
> +DEVICE_H_ATTR(8);
> +DEVICE_H_ATTR(9);
> +
> +/*
> + * sysfs calibrated
> + * Once H matrix coefs are set, writing 1 to this file triggers
> + * coordinates mapping.
> + * Anything else reset the device to un-calibrated mode,
> + * storing cursetting in newsetting.
> +*/
> +static ssize_t ebeam_calibrated_get(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct ebeam_device *ebeam = dev_get_drvdata(dev);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", ebeam->calibrated);
> +}
> +
> +static ssize_t ebeam_calibrated_set(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf,
> + size_t count)
> +{
> + struct ebeam_device *ebeam = dev_get_drvdata(dev);
> + int err, c;
> +
> + err = kstrtoint(buf, 10, &c);
> + if (err)
> + return err;
> +
> + if (c == 1) {
> + memcpy(&ebeam->cursetting, &ebeam->newsetting,
> + sizeof(struct ebeam_settings));
> + ebeam->calibrated = true;
> + ebeam_setup_input(ebeam, ebeam->input);
> + } else {
> + memcpy(&ebeam->newsetting, &ebeam->cursetting,
> + sizeof(struct ebeam_settings));
> + ebeam->calibrated = false;
> + ebeam_setup_input(ebeam, ebeam->input);
> + }
> +
> + return count;
> +}
> +
> +static DEVICE_ATTR(calibrated, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
> + ebeam_calibrated_get, ebeam_calibrated_set);
DEVICE_ATTR_RW()?
> +
> +static struct attribute *ebeam_attrs[] = {
> + &dev_attr_min_x.attr,
> + &dev_attr_min_y.attr,
> + &dev_attr_max_x.attr,
> + &dev_attr_max_y.attr,
> + &dev_attr_h1.attr,
> + &dev_attr_h2.attr,
> + &dev_attr_h3.attr,
> + &dev_attr_h4.attr,
> + &dev_attr_h5.attr,
> + &dev_attr_h6.attr,
> + &dev_attr_h7.attr,
> + &dev_attr_h8.attr,
> + &dev_attr_h9.attr,
> + &dev_attr_calibrated.attr,
> + NULL
> +};
> +
> +static const struct attribute_group ebeam_attr_group = {
> + .attrs = ebeam_attrs,
> +};
> +
> +/* IRQ */
> +static int ebeam_read_data(struct ebeam_device *ebeam, unsigned char *pkt)
> +{
> +
> +/*
> + * Packet description : 8 bytes
> + *
> + * nop packet : FF FF FF FF FF FF FF FF
> + *
> + * pkt[0] : Sensors
> + * bit 1 : ultrasound signal (guessed)
> + * bit 2 : IR signal (tested with a remote...) ;
> + * readings OK : 0x03 (anything else is a show-stopper)
> + *
> + * pkt[1] : raw_x low
> + * pkt[2] : raw_x high
> + *
> + * pkt[3] : raw_y low
> + * pkt[4] : raw_y high
> + *
> + * pkt[5] : fiability ?
> + * often 0xC0
> + * > 0x80 : OK
> + *
> + * pkt[6] :
> + * buttons state (low 4 bits)
> + * 0x1 = no buttons
> + * bit 0 : tip (WARNING inversed : 0=pressed)
> + * bit 1 : ? (always 0 during tests)
> + * bit 2 : little (1=pressed)
> + * bit 3 : big (1=pressed)
> + *
> + * pointer ID : (high 4 bits)
> + * Tested : 0x6=wand ;
> + * Guessed : 0x1=red ; 0x2=blue ; 0x3=green ; 0x4=black ;
> + * 0x5=eraser
> + * bit 4 : pointer ID
> + * bit 5 : pointer ID
> + * bit 6 : pointer ID
> + * bit 7 : pointer ID
> + *
> + *
> + * pkt[7] : fiability ?
> + * often 0xFF
> + *
> + */
> +
> + /* Filtering bad/nop packet */
> + if (pkt[0] != 0x03)
> + return 0;
> +
> + ebeam->raw_x = get_unaligned_le16(&pkt[1]);
> + ebeam->raw_y = get_unaligned_le16(&pkt[3]);
> +
> + ebeam->btn_map = (!(pkt[6] & 0x1)) |
> + ((pkt[6] & 0x4) >> 1) |
> + ((pkt[6] & 0x8) >> 1);
> +
> + return 1;
> +}
> +
> +/*
> + * IRQ
> + * compute screen coordinates from raw
> + * Overflow and negative values are ignored
> + */
> +static bool ebeam_calculate_xy(struct ebeam_device *ebeam)
> +{
> + /* 64-bits divisions handled by div64_s64 */
> +
> + s64 scale;
> +
> + if (!ebeam->calibrated) {
> + ebeam->x = ebeam->raw_x;
> + ebeam->y = ebeam->raw_y;
> + } else {
> + scale = ebeam->cursetting.h7 * ebeam->raw_x +
> + ebeam->cursetting.h8 * ebeam->raw_y +
> + ebeam->cursetting.h9;
> +
> + /* Who want a division by zero in kernel ? */
> + if (scale == 0) {
> + dev_err(&(ebeam->interface)->dev,
> + "%s - Division by zero, wrong calibration.\n",
> + __func__);
> + dev_err(&(ebeam->interface)->dev,
> + "%s - Resetting to un-calibrated mode.\n",
> + __func__);
> + ebeam->calibrated = false;
> + return 0;
> + }
> +
> + /*
> + * We *must* round the result, but can't do (int) (v1/v2 + 0.5)
> + *
> + * (int) (v1/v2 + 0.5) <=> (int) ( (2*v1 + v2)/(2*v2) )
> + */
> + ebeam->x =
> + (int)div64_s64((((ebeam->cursetting.h1 * ebeam->raw_x +
> + ebeam->cursetting.h2 * ebeam->raw_y +
> + ebeam->cursetting.h3) << 1) + scale),
> + (scale << 1));
> + ebeam->y =
> + (int)div64_s64((((ebeam->cursetting.h4 * ebeam->raw_x +
> + ebeam->cursetting.h5 * ebeam->raw_y +
> + ebeam->cursetting.h6) << 1) + scale),
> + (scale << 1));
> +
> + /* check range */
> + if ((ebeam->x < ebeam->cursetting.min_x) ||
> + (ebeam->x > ebeam->cursetting.max_x) ||
> + (ebeam->y < ebeam->cursetting.min_y) ||
> + (ebeam->y > ebeam->cursetting.max_y))
> + return 0;
> + }
> +
> + return 1;
> +}
> +
> +/* IRQ */
> +static void ebeam_report_input(struct ebeam_device *ebeam)
> +{
> + input_report_key(ebeam->input, BTN_LEFT,
> + (ebeam->btn_map & EBEAM_BTN_TIP));
> + input_report_key(ebeam->input, BTN_MIDDLE,
> + (ebeam->btn_map & EBEAM_BTN_LIT));
> + input_report_key(ebeam->input, BTN_RIGHT,
> + (ebeam->btn_map & EBEAM_BTN_BIG));
> +
> + input_report_abs(ebeam->input, ABS_X, ebeam->x);
> + input_report_abs(ebeam->input, ABS_Y, ebeam->y);
> +
> + input_sync(ebeam->input);
> +}
> +
> +/* IRQ */
> +static void ebeam_process_pkt(struct ebeam_device *ebeam,
> + unsigned char *pkt, int len)
> +{
> + if (!ebeam_read_data(ebeam, pkt))
> + return;
> +
> + if (!ebeam_calculate_xy(ebeam))
> + return;
> +
> + ebeam_report_input(ebeam);
> +}
> +
> +/* IRQ
> + * handler */
> +static void ebeam_irq(struct urb *urb)
> +{
> + struct ebeam_device *ebeam = urb->context;
> + struct device *dev = &ebeam->interface->dev;
> + int retval;
> +
> + switch (urb->status) {
> + case 0:
> + /* success */
> + break;
> + case -ETIME:
> + /* this urb is timing out */
> + dev_dbg(dev,
> + "%s - urb timed out - was the device unplugged?\n",
> + __func__);
> + return;
> + case -ECONNRESET:
> + case -ENOENT:
> + case -ESHUTDOWN:
> + case -EPIPE:
> + /* this urb is terminated, clean up */
> + dev_dbg(dev, "%s - urb shutting down with status: %d\n",
> + __func__, urb->status);
> + return;
> + default:
> + dev_dbg(dev, "%s - nonzero urb status received: %d\n",
> + __func__, urb->status);
> + goto exit;
> + }
> +
> + ebeam_process_pkt(ebeam, ebeam->data, urb->actual_length);
> +
> +exit:
> + usb_mark_last_busy(interface_to_usbdev(ebeam->interface));
> + retval = usb_submit_urb(urb, GFP_ATOMIC);
> + if (retval)
> + dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
> + __func__, retval);
> +}
> +
> +static int ebeam_open(struct input_dev *input)
> +{
> + struct ebeam_device *ebeam = input_get_drvdata(input);
> + int r;
> +
> + ebeam->irq->dev = interface_to_usbdev(ebeam->interface);
> +
> + r = usb_autopm_get_interface(ebeam->interface) ? -EIO : 0;
> + if (r < 0)
> + goto out;
> +
> + if (usb_submit_urb(ebeam->irq, GFP_KERNEL)) {
> + r = -EIO;
> + goto out_put;
> + }
> +
> + ebeam->interface->needs_remote_wakeup = 1;
> +out_put:
> + usb_autopm_put_interface(ebeam->interface);
> +out:
> + return r;
> +}
> +
> +static void ebeam_close(struct input_dev *input)
> +{
> + struct ebeam_device *ebeam = input_get_drvdata(input);
> + int r;
> +
> + r = usb_autopm_get_interface(ebeam->interface);
> +
> + usb_kill_urb(ebeam->irq);
> + ebeam->interface->needs_remote_wakeup = 0;
> +
> + if (!r)
> + usb_autopm_put_interface(ebeam->interface);
> +}
> +
> +static int ebeam_suspend(struct usb_interface *intf, pm_message_t message)
> +{
> + struct ebeam_device *ebeam = usb_get_intfdata(intf);
> +
> + usb_kill_urb(ebeam->irq);
> +
> + return 0;
> +}
> +
> +static int ebeam_resume(struct usb_interface *intf)
> +{
> + struct ebeam_device *ebeam = usb_get_intfdata(intf);
> + struct input_dev *input = ebeam->input;
> + int result = 0;
> +
> + mutex_lock(&input->mutex);
> + if (input->users)
> + result = usb_submit_urb(ebeam->irq, GFP_NOIO);
> + mutex_unlock(&input->mutex);
> +
> + return result;
> +}
> +
> +static void ebeam_free_buffers(struct usb_device *udev,
> + struct ebeam_device *ebeam)
> +{
> + usb_free_coherent(udev, REPT_SIZE, ebeam->data, ebeam->data_dma);
> + kfree(ebeam->buffer);
> +}
> +
> +static struct usb_endpoint_descriptor
> +*ebeam_get_input_endpoint(struct usb_host_interface *interface)
> +{
> + int i;
> +
> + for (i = 0; i < interface->desc.bNumEndpoints; i++)
> + if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
> + return &interface->endpoint[i].desc;
> +
> + return NULL;
> +}
> +
> +static int ebeam_probe(struct usb_interface *intf,
> + const struct usb_device_id *id)
> +{
> + struct ebeam_device *ebeam;
> + struct input_dev *input_dev;
> + struct usb_endpoint_descriptor *endpoint;
> + struct usb_device *udev = interface_to_usbdev(intf);
> + int err = -ENOMEM;
> +
> + endpoint = ebeam_get_input_endpoint(intf->cur_altsetting);
> + if (!endpoint)
> + return -ENXIO;
> +
> + ebeam = kzalloc(sizeof(struct ebeam_device), GFP_KERNEL);
> + input_dev = input_allocate_device();
> + if (!ebeam || !input_dev)
> + goto out_free;
> +
> + ebeam_init_settings(ebeam);
> +
> + ebeam->data = usb_alloc_coherent(udev, REPT_SIZE,
> + GFP_KERNEL, &ebeam->data_dma);
> + if (!ebeam->data)
> + goto out_free;
> +
> + ebeam->irq = usb_alloc_urb(0, GFP_KERNEL);
> + if (!ebeam->irq) {
> + dev_dbg(&intf->dev,
> + "%s - usb_alloc_urb failed: ebeam->irq\n", __func__);
> + goto out_free_buffers;
> + }
> +
> + ebeam->interface = intf;
> + ebeam->input = input_dev;
> +
> + /* setup name */
> + snprintf(ebeam->name, sizeof(ebeam->name),
> + "USB eBeam %04x:%04x",
> + le16_to_cpu(udev->descriptor.idVendor),
> + le16_to_cpu(udev->descriptor.idProduct));
> +
> + if (udev->manufacturer || udev->product) {
> + strlcat(ebeam->name, " (", sizeof(ebeam->name));
> +
> + if (udev->manufacturer)
> + strlcat(ebeam->name,
> + udev->manufacturer,
> + sizeof(ebeam->name));
> +
> + if (udev->product) {
> + if (udev->manufacturer)
> + strlcat(ebeam->name, " ", sizeof(ebeam->name));
> + strlcat(ebeam->name,
> + udev->product,
> + sizeof(ebeam->name));
> + }
> +
> + if (strlcat(ebeam->name, ")", sizeof(ebeam->name))
> + >= sizeof(ebeam->name)) {
> + /* overflowed, closing ) anyway */
> + ebeam->name[sizeof(ebeam->name) - 2] = ')';
> + }
> + }
> +
> + /* usb tree */
> + usb_make_path(udev, ebeam->phys, sizeof(ebeam->phys));
> + strlcat(ebeam->phys, "/input0", sizeof(ebeam->phys));
> +
> + /* input setup */
> + input_dev->name = ebeam->name;
> + input_dev->phys = ebeam->phys;
> + usb_to_input_id(udev, &input_dev->id);
> + input_dev->dev.parent = &intf->dev;
> +
> + input_set_drvdata(input_dev, ebeam);
> +
> + input_dev->open = ebeam_open;
> + input_dev->close = ebeam_close;
> +
> + /* usb urb setup */
> + if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
> + usb_fill_int_urb(ebeam->irq,
> + udev,
> + usb_rcvintpipe(udev,
> + endpoint->bEndpointAddress),
> + ebeam->data,
> + REPT_SIZE,
> + ebeam_irq,
> + ebeam,
> + endpoint->bInterval);
> + else
> + usb_fill_bulk_urb(ebeam->irq,
> + udev,
> + usb_rcvbulkpipe(udev,
> + endpoint->bEndpointAddress),
> + ebeam->data,
> + REPT_SIZE,
> + ebeam_irq,
> + ebeam);
> +
> + ebeam->irq->dev = udev;
> + ebeam->irq->transfer_dma = ebeam->data_dma;
> + ebeam->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> +
> + /* usb final setup */
> + usb_set_intfdata(intf, ebeam);
> +
> + /* sysfs setup */
> + err = sysfs_create_group(&intf->dev.kobj, &ebeam_attr_group);
Ick, you just added the sysfs files to the USB device, not your input
device, are you sure you tested this?
And there should be a race-free way to add an attribute group to an
input device, as this is, you are adding them to the device _after_ it
is created, so userspace will not see them at creation time, causing a
race.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH] toshiba_acpi: Add /dev/toshiba_acpi device
From: Azael Avalos @ 2015-07-20 21:55 UTC (permalink / raw)
To: Darren Hart
Cc: Jonathan Corbet, Jonathan Buzzard, linux-doc,
linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org,
linux-api
In-Reply-To: <20150720213631.GA34611@vmdeb7>
Hi Darren,
2015-07-20 15:36 GMT-06:00 Darren Hart <dvhart@infradead.org>:
> On Thu, Jul 16, 2015 at 05:32:44PM -0600, Azael Avalos wrote:
>> There were previous attempts to "merge" the toshiba SMM module to the
>> toshiba_acpi one, they were trying to imitate what the old toshiba
>> module does, however, some models (TOS1900 devices) come with a
>> "crippled" implementation and do not provide all the "features" a
>> "genuine" Toshiba BIOS does.
>>
>> This patch adds a new device called toshiba_acpi, which aim is to
>> enable userspace to access the SMM on Toshiba laptops via ACPI calls.
>>
>> Creating a new convenience _IOWR command to access the SCI functions
>> by opening/closing the SCI internally to avoid buggy BIOS, while at
>> the same time providing backwards compatibility.
>>
>> Older programs who wish to access the SMM on newer models can do it
>> without much code change, as the toshiba.h header was modified to
>> reflect these changes as well as adds all the toshiba_acpi paths
>> and commands.
>
> To clarify, the newer models didn't work at all previously, so this is not
> changing the user:kernel interface, but rather enabling it on newer machines,
> and programs wishing to take advantage of that can do so with minimal change.
>
> Correct?
Yes, the only real (or new) change here is the introduction of the IOCTL
"TOSHIBA_ACPI_SCI", which was added to circumvent buggy or "incomplete"
BIOSes found (so far) on TOS1900 devices.
Any new (or old) program that want to access the SMM can do so by pointing
their path to /dev/toshiba_acpi instead of /dev/toshiba, however, it is strongly
recommended to use the new IOCTL for any SCI command to avoid any buggy
BIOS.
>
> --
> Darren Hart
> Intel Open Source Technology Center
Cheers
Azael
--
-- El mundo apesta y vosotros apestais tambien --
^ permalink raw reply
* Re: [PATCH] toshiba_acpi: Add /dev/toshiba_acpi device
From: Darren Hart @ 2015-07-20 21:36 UTC (permalink / raw)
To: Azael Avalos
Cc: Jonathan Corbet, Jonathan Buzzard, linux-doc, linux-kernel,
platform-driver-x86, linux-api
In-Reply-To: <1437089564-4242-1-git-send-email-coproscefalo@gmail.com>
On Thu, Jul 16, 2015 at 05:32:44PM -0600, Azael Avalos wrote:
> There were previous attempts to "merge" the toshiba SMM module to the
> toshiba_acpi one, they were trying to imitate what the old toshiba
> module does, however, some models (TOS1900 devices) come with a
> "crippled" implementation and do not provide all the "features" a
> "genuine" Toshiba BIOS does.
>
> This patch adds a new device called toshiba_acpi, which aim is to
> enable userspace to access the SMM on Toshiba laptops via ACPI calls.
>
> Creating a new convenience _IOWR command to access the SCI functions
> by opening/closing the SCI internally to avoid buggy BIOS, while at
> the same time providing backwards compatibility.
>
> Older programs who wish to access the SMM on newer models can do it
> without much code change, as the toshiba.h header was modified to
> reflect these changes as well as adds all the toshiba_acpi paths
> and commands.
To clarify, the newer models didn't work at all previously, so this is not
changing the user:kernel interface, but rather enabling it on newer machines,
and programs wishing to take advantage of that can do so with minimal change.
Correct?
--
Darren Hart
Intel Open Source Technology Center
^ permalink raw reply
* Re: [PATCH v8 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
From: Stephen Boyd @ 2015-07-20 21:20 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Greg Kroah-Hartman, Rob Herring, Mark Brown,
s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
wxt-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1437403445-4348-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 07/20/2015 07:44 AM, Srinivas Kandagatla wrote:
> This patch adds QFPROM support driver which is used by other drivers
> like thermal sensor and cpufreq.
>
> On MSM parts there are some efuses (called qfprom) these fuses store
> things like calibration data, speed bins.. etc. Drivers like cpufreq,
> thermal sensors would read out this data for configuring the driver.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
One comment below, otherwise
Reviewed-by: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
> new file mode 100644
> index 0000000..ba5e2b4
> --- /dev/null
> +++ b/drivers/nvmem/qfprom.c
> @@ -0,0 +1,86 @@
> +/*
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
This include is used?
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH v8 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
From: Stephen Boyd @ 2015-07-20 21:11 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Greg Kroah-Hartman, Rob Herring, Mark Brown,
s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
wxt-TNX95d0MmH7DzftRWevZcw, Maxime Ripard
In-Reply-To: <1437403392-4136-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 07/20/2015 07:43 AM, Srinivas Kandagatla wrote:
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> new file mode 100644
> index 0000000..bde5528
> --- /dev/null
> +++ b/drivers/nvmem/core.c
> @@ -0,0 +1,384 @@
>
> +
> +static int nvmem_add_cells(struct nvmem_device *nvmem,
> + const struct nvmem_config *cfg)
> +{
> + struct nvmem_cell **cells;
> + const struct nvmem_cell_info *info = cfg->cells;
> + int i, rval;
> +
> + cells = kzalloc(sizeof(*cells) * cfg->ncells, GFP_KERNEL);
kcalloc?
> + if (!cells)
> + return -ENOMEM;
> +
> + for (i = 0; i < cfg->ncells; i++) {
> + cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
> + if (!cells[i]) {
> + rval = -ENOMEM;
> + goto err;
> + }
> +
> + rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
> + if (IS_ERR_VALUE(rval)) {
> + kfree(cells[i]);
> + goto err;
> + }
> +
> + nvmem_cell_add(cells[i]);
> + }
> +
> + nvmem->ncells = cfg->ncells;
> + /* remove tmp array */
> + kfree(cells);
> +
> + return 0;
> +err:
> + while (--i)
> + nvmem_cell_drop(cells[i]);
> +
> + return rval;
> +}
> +
> +/**
> + * nvmem_register() - Register a nvmem device for given nvmem_config.
> + * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
> + *
> + * @config: nvmem device configuration with which nvmem device is created.
> + *
> + * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
> + * on success.
> + */
> +
Why the newline?
> +struct nvmem_device *nvmem_register(const struct nvmem_config *config)
> +{
> + struct nvmem_device *nvmem;
> + struct device_node *np;
> + struct regmap *rm;
> + int rval;
> +
> + if (!config->dev)
> + return ERR_PTR(-EINVAL);
> +
> + rm = dev_get_regmap(config->dev, NULL);
> + if (!rm) {
> + dev_err(config->dev, "Regmap not found\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
> + if (!nvmem)
> + return ERR_PTR(-ENOMEM);
> +
> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
> + if (nvmem->id < 0) {
> + kfree(nvmem);
> + return ERR_PTR(nvmem->id);
Oops, we already freed nvmem.
> + }
> +
> + nvmem->regmap = rm;
> + nvmem->owner = config->owner;
> + nvmem->stride = regmap_get_reg_stride(rm);
> + nvmem->word_size = regmap_get_val_bytes(rm);
> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
> + nvmem->dev.type = &nvmem_provider_type;
> + nvmem->dev.bus = &nvmem_bus_type;
> + nvmem->dev.parent = config->dev;
> + np = config->dev->of_node;
> + nvmem->dev.of_node = np;
> + dev_set_name(&nvmem->dev, "%s%d",
> + config->name ? : "nvmem", config->id);
> +
> + nvmem->read_only = np ? of_property_read_bool(np, "read-only") : 0;
of_property_read_bool(NULL, ..) "does the right thing" and returns false
already.
> +
> + nvmem->read_only |= config->read_only;
> +
> + device_initialize(&nvmem->dev);
> +
> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
> +
> + rval = device_add(&nvmem->dev);
> + if (rval) {
> + ida_simple_remove(&nvmem_ida, nvmem->id);
> + kfree(nvmem);
> + return ERR_PTR(rval);
> + }
> +
> + if (device_create_bin_file(&nvmem->dev,
> + nvmem->read_only ? &bin_attr_ro_nvmem :
> + &bin_attr_rw_nvmem))
> + dev_warn(&nvmem->dev, "Failed to create sysfs binary file\n");
Why can't we have device_add() add the binary file attribute too?
> +
> + if (config->cells)
> + nvmem_add_cells(nvmem, config);
> +
> + return nvmem;
> +}
> +EXPORT_SYMBOL_GPL(nvmem_register);
> +
> +/**
> + * nvmem_unregister() - Unregister previously registered nvmem device
> + *
> + * @nvmem: Pointer to previously registered nvmem device.
> + *
> + * Return: Will be an negative on error or a zero on success.
> + */
> +int nvmem_unregister(struct nvmem_device *nvmem)
> +{
> + mutex_lock(&nvmem_mutex);
> + if (nvmem->users) {
> + mutex_unlock(&nvmem_mutex);
> + return -EBUSY;
> + }
> + mutex_unlock(&nvmem_mutex);
This lock doesn't seem to be doing anything in this patch? Perhaps it
should be added in the second patch where consumers start making it useful?
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [RFC PATCH] getcpu_cache system call: caching current CPU number (x86)
From: Andy Lutomirski @ 2015-07-20 21:09 UTC (permalink / raw)
To: Linus Torvalds
Cc: Ben Maurer, Ingo Molnar, libc-alpha, Andrew Morton, linux-api,
Ondřej Bílka, rostedt, Mathieu Desnoyers,
Paul E. McKenney, Florian Weimer, Josh Triplett, Lai Jiangshan,
Paul Turner, Andrew Hunter, Peter Zijlstra
In-Reply-To: <CA+55aFzMJkzydXb7uVv1iSUnp=539d43ghQaonGdzMoF7QLZBA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Mon, Jul 20, 2015 at 1:50 PM, Linus Torvalds
<torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> wrote:
>
> On Jul 20, 2015 10:41 AM, "Andy Lutomirski" <luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org> wrote:
>>
>> glibc will have to expose a way to turn it off, I guess. (ELF flag?)
>
> Ugh. That just sounds nasty.
>
> I'm on mobile, so can't check right now, but don't we already have a per-cpu
> gdt? We could just make a very simple rule:
>
> - create a single gdt entry with a segment that is per-cpu and points to one
> single read-only page in kernel space that contains the virtual address of
> that segment in vmalloc space (and maybe we can have the CPU number there
> somewhere, and extend it to something else later)
Annoying problem one: the segment base field is only 32 bits in the GDT.
>
> - make the rule be that if you hold that segment in %fs or %gs in your user
> space state, it gets cleared when the thread is scheduled out.
That sounds a bit evil, but okay.
>
> What does this get you?
>
> It basically means that:
>
> - user space can just load the segment selector in %gs
>
IIRC this is very expensive -- 40 cycles or so. At this point
userspace might as well just use a real lock cmpxchg.
> - user space can load the virtual address of the segment base into a bar
> register, and use that to calculate a pointer to regular data structures.
>
> - user space can use that "reverse offset" to access any data it wants, and
> access that data with a gs override.
>
> - if the user space thread is scheduled, that access will fault with a GP
> fault, because %gs became NUL.
Cute.
>
> So basically you can do any memory access you want, and you'll be guaranteed
> that it will be done "atomically" on the same CPU you did the segment load
> on, or it will fault because you got scheduled away.
>
> And it's very cheap for both kernel and user space. One extra gdt entry (not
> per process or anything like that - it's system global, although different
> cpus all end up with different entries), and for each cpu one virtually
> mapped page. And all user space needs to do is to do a segment load.
>
> No system calls, no nothing.
>
> Would that be useful?
>
Does it solve the Wine problem? If Wine uses gs for something and
calls a function that does this, Wine still goes boom, right?
Could Wine just save and restore gs on calls into and out of Windows
code? That would solve all the problems, right?
--Andy
^ permalink raw reply
* Re: [linux-4.2-rc3/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c:194: bad if condition ?
From: Darren Hart @ 2015-07-20 21:03 UTC (permalink / raw)
To: Shuah Khan
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
David Binderman
In-Reply-To: <55AD08C8.4030705-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
On Mon, Jul 20, 2015 at 08:42:16AM -0600, Shuah Khan wrote:
> On 07/20/2015 03:26 AM, David Binderman wrote:
> > Hello there,
> >
> > [linux-4.2-rc3/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c:194]: (style) Expression is always false because 'else if' condition matches previous condition at line 191.
> >
> > Source code is
> >
> > if (res> 0) {
> > atomic_set(&requeued, 1);
> > break;
> > } else if (res> 0) {
> >
>
> Hi Daren,
>
> Is this something that could be fixed?
Ew, yuck. I'll look into this and provide a fix.
Thanks for the report David.
--
Darren Hart
Intel Open Source Technology Center
^ permalink raw reply
* [RFC ebeam PATCH 2/2] input: misc: New USB eBeam input driver
From: Yann Cantin @ 2015-07-20 21:03 UTC (permalink / raw)
To: linux-input, linux-usb
Cc: linux-kernel, linux-api, dmitry.torokhov, jkosina, gregkh,
Yann Cantin
In-Reply-To: <1437426199-29866-1-git-send-email-yann.cantin@laposte.net>
Signed-off-by: Yann Cantin <yann.cantin@laposte.net>
---
Documentation/ABI/testing/sysfs-driver-ebeam | 53 ++
drivers/input/misc/Kconfig | 22 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/ebeam.c | 777 +++++++++++++++++++++++++++
4 files changed, 853 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-driver-ebeam
create mode 100644 drivers/input/misc/ebeam.c
diff --git a/Documentation/ABI/testing/sysfs-driver-ebeam b/Documentation/ABI/testing/sysfs-driver-ebeam
new file mode 100644
index 0000000..6873db5
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ebeam
@@ -0,0 +1,53 @@
+What: /sys/class/input/inputXX/device/min_x
+ /sys/class/input/inputXX/device/min_y
+ /sys/class/input/inputXX/device/max_x
+ /sys/class/input/inputXX/device/max_y
+Date: Jul 2015
+Kernel Version: 4.1
+Contact: yann.cantin@laposte.net
+ linux-usb@vger.kernel.org
+Description:
+ Reading from these files return the actually used range values of
+ the reported coordinates.
+ Writing to these files preset these range values.
+ See below for the calibration procedure.
+
+What: /sys/class/input/inputXX/device/h[1..9]
+Date: Jul 2015
+Kernel Version: 4.1
+Contact: yann.cantin@laposte.net
+ linux-usb@vger.kernel.org
+Description:
+ Reading from these files return the 3x3 transformation matrix elements
+ actually used, in row-major.
+ Writing to these files preset these elements values.
+ See below for the calibration procedure.
+
+What: /sys/class/input/inputXX/device/calibrated
+Date: Jul 2015
+Kernel Version: 4.1
+Contact: yann.cantin@laposte.net
+ linux-usb@vger.kernel.org
+Description:
+ Reading from this file :
+ - Return 0 if the driver is in "un-calibrated" mode : it actually send
+ raw coordinates in the device's internal coordinates system.
+ - Return 1 if the driver is in "calibrated" mode : it send computed coordinates
+ that (hopefully) matches the screen's coordinates system.
+ Writing 1 to this file enable the "calibrated" mode, 0 reset the driver in
+ "un-calibrated" mode.
+
+Calibration procedure :
+
+When loaded, the driver is in "un-calibrated" mode : it send device's raw coordinates
+in the [0..65535]x[0..65535] range, the transformation matrix is the identity.
+
+A calibration program have to compute a homography transformation matrix that convert
+the device's raw coordinates to the matching screen's ones.
+It then write to the appropriate sysfs files the computed values, pre-setting the
+driver's parameters : xy range, and the matrix's elements.
+When all values are passed, it write 1 to the calibrated sysfs file to enable the "calibrated" mode.
+
+Warning : The parameters aren't used until 1 is writen to the calibrated sysfs file.
+
+Writing 0 to the calibrated sysfs file reset the driver in "un-calibrated" mode.
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d4f0a81..22c46a4 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -103,6 +103,28 @@ config INPUT_E3X0_BUTTON
To compile this driver as a module, choose M here: the
module will be called e3x0_button.
+config INPUT_EBEAM_USB
+ tristate "USB eBeam driver"
+ depends on USB_ARCH_HAS_HCD
+ select USB
+ help
+ Say Y here if you have a USB eBeam pointing device and want to
+ use it without any proprietary user space tools.
+
+ Have a look at <http://ebeam.tuxfamily.org/> for
+ a usage description and the required user-space tools.
+
+ Supported devices :
+ - Luidia eBeam Classic Projection and eBeam Edge Projection
+ - Nec NP01Wi1 & NP01Wi2 interactive solution
+
+ Supposed working devices, need test, may lack functionality :
+ - Luidia eBeam Edge Whiteboard and eBeam Engage
+ - Hitachi Starboard FX-63, FX-77, FX-82, FX-77GII
+
+ To compile this driver as a module, choose M here: the
+ module will be called ebeam.
+
config INPUT_PCSPKR
tristate "PC Speaker support"
depends on PCSPKR_PLATFORM
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 53df07d..125f8a9 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o
obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o
obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_INPUT_E3X0_BUTTON) += e3x0-button.o
+obj-$(CONFIG_INPUT_EBEAM_USB) += ebeam.o
obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o
obj-$(CONFIG_INPUT_DRV2665_HAPTICS) += drv2665.o
obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o
diff --git a/drivers/input/misc/ebeam.c b/drivers/input/misc/ebeam.c
new file mode 100644
index 0000000..79cac51
--- /dev/null
+++ b/drivers/input/misc/ebeam.c
@@ -0,0 +1,777 @@
+/******************************************************************************
+ *
+ * eBeam driver
+ *
+ * Copyright (C) 2012-2015 Yann Cantin (yann.cantin@laposte.net)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * based on
+ *
+ * usbtouchscreen.c by Daniel Ritz <daniel.ritz@gmx.ch>
+ * aiptek.c (sysfs/settings) by Chris Atenasio <chris@crud.net>
+ * Bryan W. Headley <bwheadley@earthlink.net>
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/math64.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <asm/unaligned.h>
+
+#define DRIVER_AUTHOR "Yann Cantin <yann.cantin@laposte.net>"
+#define DRIVER_DESC "USB eBeam Driver"
+
+/* Common values for eBeam devices */
+#define REPT_SIZE 8 /* packet size */
+#define MIN_RAW_X 0 /* raw coordinates ranges */
+#define MAX_RAW_X 0xFFFF
+#define MIN_RAW_Y 0
+#define MAX_RAW_Y 0xFFFF
+
+/* Electronics For Imaging, Inc */
+#define USB_VENDOR_ID_EFI 0x2650
+
+/* eBeam hardware : */
+/* Luidia Classic and Edge */
+/* Nec NP01Wi1 & NP01Wi2 */
+#define USB_DEVICE_ID_EFI_EBEAM_USB1 0x1311
+/* From https://github.com/dpiquet */
+/* Need confirmation */
+#define USB_DEVICE_ID_EFI_EBEAM_USB2 0x1315
+#define USB_DEVICE_ID_EFI_EBEAM_BT_USB1 0x1313
+#define USB_DEVICE_ID_EFI_EBEAM_BT_USB2 0x1320
+
+#define EBEAM_BTN_TIP 0x1 /* tip */
+#define EBEAM_BTN_LIT 0x2 /* little */
+#define EBEAM_BTN_BIG 0x4 /* big */
+
+/* ebeam settings */
+struct ebeam_settings {
+ int min_x; /* computed coordinates ranges for the input layer */
+ int max_x;
+ int min_y;
+ int max_y;
+
+ /* H matrix */
+ s64 h1;
+ s64 h2;
+ s64 h3;
+ s64 h4;
+ s64 h5;
+ s64 h6;
+ s64 h7;
+ s64 h8;
+ s64 h9;
+};
+
+/* ebeam device */
+struct ebeam_device {
+ unsigned char *data;
+ dma_addr_t data_dma;
+ unsigned char *buffer;
+ int buf_len;
+ struct urb *irq;
+ struct usb_interface *interface;
+ struct input_dev *input;
+ char name[128];
+ char phys[64];
+ void *priv;
+
+ struct ebeam_settings cursetting; /* device's current settings */
+ struct ebeam_settings newsetting; /* ... and new ones */
+
+ bool calibrated; /* false : send raw */
+ /* true : send computed */
+
+ u16 raw_x; /* raw coordinates */
+ u16 raw_y;
+ int x; /* computed coordinates */
+ int y;
+ int btn_map; /* internal buttons map */
+};
+
+/* device types */
+enum {
+ DEVTYPE_EBEAM,
+};
+
+static const struct usb_device_id ebeam_devices[] = {
+ {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB1),
+ .driver_info = DEVTYPE_EBEAM},
+ {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB2),
+ .driver_info = DEVTYPE_EBEAM},
+ {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB1),
+ .driver_info = DEVTYPE_EBEAM},
+ {USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB2),
+ .driver_info = DEVTYPE_EBEAM},
+ {}
+};
+
+static void ebeam_init_settings(struct ebeam_device *ebeam)
+{
+ ebeam->calibrated = false;
+
+ /* Init (x,y) min/max to raw ones */
+ ebeam->cursetting.min_x = ebeam->newsetting.min_x = MIN_RAW_X;
+ ebeam->cursetting.max_x = ebeam->newsetting.max_x = MAX_RAW_X;
+ ebeam->cursetting.min_y = ebeam->newsetting.min_y = MIN_RAW_Y;
+ ebeam->cursetting.max_y = ebeam->newsetting.max_y = MAX_RAW_Y;
+
+ /* Safe values for the H matrix (Identity) */
+ ebeam->cursetting.h1 = ebeam->newsetting.h1 = 1;
+ ebeam->cursetting.h2 = ebeam->newsetting.h2 = 0;
+ ebeam->cursetting.h3 = ebeam->newsetting.h3 = 0;
+
+ ebeam->cursetting.h4 = ebeam->newsetting.h4 = 0;
+ ebeam->cursetting.h5 = ebeam->newsetting.h5 = 1;
+ ebeam->cursetting.h6 = ebeam->newsetting.h6 = 0;
+
+ ebeam->cursetting.h7 = ebeam->newsetting.h7 = 0;
+ ebeam->cursetting.h8 = ebeam->newsetting.h8 = 0;
+ ebeam->cursetting.h9 = ebeam->newsetting.h9 = 1;
+}
+
+static void ebeam_setup_input(struct ebeam_device *ebeam,
+ struct input_dev *input_dev)
+{
+ unsigned long flags;
+
+ /* Take event lock while modifying parameters */
+ spin_lock_irqsave(&input_dev->event_lock, flags);
+
+ /* Properties */
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ /* Events generated */
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(EV_ABS, input_dev->evbit);
+
+ /* Keys */
+ set_bit(BTN_LEFT, input_dev->keybit);
+ set_bit(BTN_MIDDLE, input_dev->keybit);
+ set_bit(BTN_RIGHT, input_dev->keybit);
+
+ /* Axis */
+ if (!ebeam->calibrated) {
+ ebeam->cursetting.min_x = MIN_RAW_X;
+ ebeam->cursetting.max_x = MAX_RAW_X;
+ ebeam->cursetting.min_y = MIN_RAW_Y;
+ ebeam->cursetting.max_y = MAX_RAW_Y;
+ }
+
+ input_set_abs_params(input_dev, ABS_X,
+ ebeam->cursetting.min_x, ebeam->cursetting.max_x,
+ 0, 0);
+ input_set_abs_params(input_dev, ABS_Y,
+ ebeam->cursetting.min_y, ebeam->cursetting.max_y,
+ 0, 0);
+
+ spin_unlock_irqrestore(&input_dev->event_lock, flags);
+}
+
+/*******************************************************************************
+ * sysfs part
+ */
+
+/*
+ * screen min/max and H matrix coefs
+ * _get return *current* value
+ * _set set new value
+ */
+#define DEVICE_MINMAX_ATTR(MM) \
+static ssize_t ebeam_##MM##_get(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct ebeam_device *ebeam = dev_get_drvdata(dev); \
+ \
+ return snprintf(buf, PAGE_SIZE, "%d\n", ebeam->cursetting.MM); \
+} \
+static ssize_t ebeam_##MM##_set(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, \
+ size_t count) \
+{ \
+ struct ebeam_device *ebeam = dev_get_drvdata(dev); \
+ int err, MM; \
+ \
+ err = kstrtoint(buf, 10, &MM); \
+ if (err) \
+ return err; \
+ \
+ ebeam->newsetting.MM = MM; \
+ return count; \
+} \
+static DEVICE_ATTR(MM, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, \
+ ebeam_##MM##_get, \
+ ebeam_##MM##_set)
+
+DEVICE_MINMAX_ATTR(min_x);
+DEVICE_MINMAX_ATTR(max_x);
+DEVICE_MINMAX_ATTR(min_y);
+DEVICE_MINMAX_ATTR(max_y);
+
+#define DEVICE_H_ATTR(SET_ID) \
+static ssize_t ebeam_h##SET_ID##_get(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct ebeam_device *ebeam = dev_get_drvdata(dev); \
+ \
+ return snprintf(buf, PAGE_SIZE, "%lld\n", ebeam->cursetting.h##SET_ID);\
+} \
+static ssize_t ebeam_h##SET_ID##_set(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, \
+ size_t count) \
+{ \
+ struct ebeam_device *ebeam = dev_get_drvdata(dev); \
+ int err; \
+ u64 h; \
+ \
+ err = kstrtoll(buf, 10, &h); \
+ if (err) \
+ return err; \
+ \
+ ebeam->newsetting.h##SET_ID = h; \
+ return count; \
+} \
+static DEVICE_ATTR(h##SET_ID, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, \
+ ebeam_h##SET_ID##_get, \
+ ebeam_h##SET_ID##_set)
+
+DEVICE_H_ATTR(1);
+DEVICE_H_ATTR(2);
+DEVICE_H_ATTR(3);
+DEVICE_H_ATTR(4);
+DEVICE_H_ATTR(5);
+DEVICE_H_ATTR(6);
+DEVICE_H_ATTR(7);
+DEVICE_H_ATTR(8);
+DEVICE_H_ATTR(9);
+
+/*
+ * sysfs calibrated
+ * Once H matrix coefs are set, writing 1 to this file triggers
+ * coordinates mapping.
+ * Anything else reset the device to un-calibrated mode,
+ * storing cursetting in newsetting.
+*/
+static ssize_t ebeam_calibrated_get(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ebeam_device *ebeam = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ebeam->calibrated);
+}
+
+static ssize_t ebeam_calibrated_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ebeam_device *ebeam = dev_get_drvdata(dev);
+ int err, c;
+
+ err = kstrtoint(buf, 10, &c);
+ if (err)
+ return err;
+
+ if (c == 1) {
+ memcpy(&ebeam->cursetting, &ebeam->newsetting,
+ sizeof(struct ebeam_settings));
+ ebeam->calibrated = true;
+ ebeam_setup_input(ebeam, ebeam->input);
+ } else {
+ memcpy(&ebeam->newsetting, &ebeam->cursetting,
+ sizeof(struct ebeam_settings));
+ ebeam->calibrated = false;
+ ebeam_setup_input(ebeam, ebeam->input);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(calibrated, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP,
+ ebeam_calibrated_get, ebeam_calibrated_set);
+
+static struct attribute *ebeam_attrs[] = {
+ &dev_attr_min_x.attr,
+ &dev_attr_min_y.attr,
+ &dev_attr_max_x.attr,
+ &dev_attr_max_y.attr,
+ &dev_attr_h1.attr,
+ &dev_attr_h2.attr,
+ &dev_attr_h3.attr,
+ &dev_attr_h4.attr,
+ &dev_attr_h5.attr,
+ &dev_attr_h6.attr,
+ &dev_attr_h7.attr,
+ &dev_attr_h8.attr,
+ &dev_attr_h9.attr,
+ &dev_attr_calibrated.attr,
+ NULL
+};
+
+static const struct attribute_group ebeam_attr_group = {
+ .attrs = ebeam_attrs,
+};
+
+/* IRQ */
+static int ebeam_read_data(struct ebeam_device *ebeam, unsigned char *pkt)
+{
+
+/*
+ * Packet description : 8 bytes
+ *
+ * nop packet : FF FF FF FF FF FF FF FF
+ *
+ * pkt[0] : Sensors
+ * bit 1 : ultrasound signal (guessed)
+ * bit 2 : IR signal (tested with a remote...) ;
+ * readings OK : 0x03 (anything else is a show-stopper)
+ *
+ * pkt[1] : raw_x low
+ * pkt[2] : raw_x high
+ *
+ * pkt[3] : raw_y low
+ * pkt[4] : raw_y high
+ *
+ * pkt[5] : fiability ?
+ * often 0xC0
+ * > 0x80 : OK
+ *
+ * pkt[6] :
+ * buttons state (low 4 bits)
+ * 0x1 = no buttons
+ * bit 0 : tip (WARNING inversed : 0=pressed)
+ * bit 1 : ? (always 0 during tests)
+ * bit 2 : little (1=pressed)
+ * bit 3 : big (1=pressed)
+ *
+ * pointer ID : (high 4 bits)
+ * Tested : 0x6=wand ;
+ * Guessed : 0x1=red ; 0x2=blue ; 0x3=green ; 0x4=black ;
+ * 0x5=eraser
+ * bit 4 : pointer ID
+ * bit 5 : pointer ID
+ * bit 6 : pointer ID
+ * bit 7 : pointer ID
+ *
+ *
+ * pkt[7] : fiability ?
+ * often 0xFF
+ *
+ */
+
+ /* Filtering bad/nop packet */
+ if (pkt[0] != 0x03)
+ return 0;
+
+ ebeam->raw_x = get_unaligned_le16(&pkt[1]);
+ ebeam->raw_y = get_unaligned_le16(&pkt[3]);
+
+ ebeam->btn_map = (!(pkt[6] & 0x1)) |
+ ((pkt[6] & 0x4) >> 1) |
+ ((pkt[6] & 0x8) >> 1);
+
+ return 1;
+}
+
+/*
+ * IRQ
+ * compute screen coordinates from raw
+ * Overflow and negative values are ignored
+ */
+static bool ebeam_calculate_xy(struct ebeam_device *ebeam)
+{
+ /* 64-bits divisions handled by div64_s64 */
+
+ s64 scale;
+
+ if (!ebeam->calibrated) {
+ ebeam->x = ebeam->raw_x;
+ ebeam->y = ebeam->raw_y;
+ } else {
+ scale = ebeam->cursetting.h7 * ebeam->raw_x +
+ ebeam->cursetting.h8 * ebeam->raw_y +
+ ebeam->cursetting.h9;
+
+ /* Who want a division by zero in kernel ? */
+ if (scale == 0) {
+ dev_err(&(ebeam->interface)->dev,
+ "%s - Division by zero, wrong calibration.\n",
+ __func__);
+ dev_err(&(ebeam->interface)->dev,
+ "%s - Resetting to un-calibrated mode.\n",
+ __func__);
+ ebeam->calibrated = false;
+ return 0;
+ }
+
+ /*
+ * We *must* round the result, but can't do (int) (v1/v2 + 0.5)
+ *
+ * (int) (v1/v2 + 0.5) <=> (int) ( (2*v1 + v2)/(2*v2) )
+ */
+ ebeam->x =
+ (int)div64_s64((((ebeam->cursetting.h1 * ebeam->raw_x +
+ ebeam->cursetting.h2 * ebeam->raw_y +
+ ebeam->cursetting.h3) << 1) + scale),
+ (scale << 1));
+ ebeam->y =
+ (int)div64_s64((((ebeam->cursetting.h4 * ebeam->raw_x +
+ ebeam->cursetting.h5 * ebeam->raw_y +
+ ebeam->cursetting.h6) << 1) + scale),
+ (scale << 1));
+
+ /* check range */
+ if ((ebeam->x < ebeam->cursetting.min_x) ||
+ (ebeam->x > ebeam->cursetting.max_x) ||
+ (ebeam->y < ebeam->cursetting.min_y) ||
+ (ebeam->y > ebeam->cursetting.max_y))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* IRQ */
+static void ebeam_report_input(struct ebeam_device *ebeam)
+{
+ input_report_key(ebeam->input, BTN_LEFT,
+ (ebeam->btn_map & EBEAM_BTN_TIP));
+ input_report_key(ebeam->input, BTN_MIDDLE,
+ (ebeam->btn_map & EBEAM_BTN_LIT));
+ input_report_key(ebeam->input, BTN_RIGHT,
+ (ebeam->btn_map & EBEAM_BTN_BIG));
+
+ input_report_abs(ebeam->input, ABS_X, ebeam->x);
+ input_report_abs(ebeam->input, ABS_Y, ebeam->y);
+
+ input_sync(ebeam->input);
+}
+
+/* IRQ */
+static void ebeam_process_pkt(struct ebeam_device *ebeam,
+ unsigned char *pkt, int len)
+{
+ if (!ebeam_read_data(ebeam, pkt))
+ return;
+
+ if (!ebeam_calculate_xy(ebeam))
+ return;
+
+ ebeam_report_input(ebeam);
+}
+
+/* IRQ
+ * handler */
+static void ebeam_irq(struct urb *urb)
+{
+ struct ebeam_device *ebeam = urb->context;
+ struct device *dev = &ebeam->interface->dev;
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ETIME:
+ /* this urb is timing out */
+ dev_dbg(dev,
+ "%s - urb timed out - was the device unplugged?\n",
+ __func__);
+ return;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -EPIPE:
+ /* this urb is terminated, clean up */
+ dev_dbg(dev, "%s - urb shutting down with status: %d\n",
+ __func__, urb->status);
+ return;
+ default:
+ dev_dbg(dev, "%s - nonzero urb status received: %d\n",
+ __func__, urb->status);
+ goto exit;
+ }
+
+ ebeam_process_pkt(ebeam, ebeam->data, urb->actual_length);
+
+exit:
+ usb_mark_last_busy(interface_to_usbdev(ebeam->interface));
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
+ __func__, retval);
+}
+
+static int ebeam_open(struct input_dev *input)
+{
+ struct ebeam_device *ebeam = input_get_drvdata(input);
+ int r;
+
+ ebeam->irq->dev = interface_to_usbdev(ebeam->interface);
+
+ r = usb_autopm_get_interface(ebeam->interface) ? -EIO : 0;
+ if (r < 0)
+ goto out;
+
+ if (usb_submit_urb(ebeam->irq, GFP_KERNEL)) {
+ r = -EIO;
+ goto out_put;
+ }
+
+ ebeam->interface->needs_remote_wakeup = 1;
+out_put:
+ usb_autopm_put_interface(ebeam->interface);
+out:
+ return r;
+}
+
+static void ebeam_close(struct input_dev *input)
+{
+ struct ebeam_device *ebeam = input_get_drvdata(input);
+ int r;
+
+ r = usb_autopm_get_interface(ebeam->interface);
+
+ usb_kill_urb(ebeam->irq);
+ ebeam->interface->needs_remote_wakeup = 0;
+
+ if (!r)
+ usb_autopm_put_interface(ebeam->interface);
+}
+
+static int ebeam_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct ebeam_device *ebeam = usb_get_intfdata(intf);
+
+ usb_kill_urb(ebeam->irq);
+
+ return 0;
+}
+
+static int ebeam_resume(struct usb_interface *intf)
+{
+ struct ebeam_device *ebeam = usb_get_intfdata(intf);
+ struct input_dev *input = ebeam->input;
+ int result = 0;
+
+ mutex_lock(&input->mutex);
+ if (input->users)
+ result = usb_submit_urb(ebeam->irq, GFP_NOIO);
+ mutex_unlock(&input->mutex);
+
+ return result;
+}
+
+static void ebeam_free_buffers(struct usb_device *udev,
+ struct ebeam_device *ebeam)
+{
+ usb_free_coherent(udev, REPT_SIZE, ebeam->data, ebeam->data_dma);
+ kfree(ebeam->buffer);
+}
+
+static struct usb_endpoint_descriptor
+*ebeam_get_input_endpoint(struct usb_host_interface *interface)
+{
+ int i;
+
+ for (i = 0; i < interface->desc.bNumEndpoints; i++)
+ if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
+ return &interface->endpoint[i].desc;
+
+ return NULL;
+}
+
+static int ebeam_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct ebeam_device *ebeam;
+ struct input_dev *input_dev;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ int err = -ENOMEM;
+
+ endpoint = ebeam_get_input_endpoint(intf->cur_altsetting);
+ if (!endpoint)
+ return -ENXIO;
+
+ ebeam = kzalloc(sizeof(struct ebeam_device), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ebeam || !input_dev)
+ goto out_free;
+
+ ebeam_init_settings(ebeam);
+
+ ebeam->data = usb_alloc_coherent(udev, REPT_SIZE,
+ GFP_KERNEL, &ebeam->data_dma);
+ if (!ebeam->data)
+ goto out_free;
+
+ ebeam->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ebeam->irq) {
+ dev_dbg(&intf->dev,
+ "%s - usb_alloc_urb failed: ebeam->irq\n", __func__);
+ goto out_free_buffers;
+ }
+
+ ebeam->interface = intf;
+ ebeam->input = input_dev;
+
+ /* setup name */
+ snprintf(ebeam->name, sizeof(ebeam->name),
+ "USB eBeam %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ if (udev->manufacturer || udev->product) {
+ strlcat(ebeam->name, " (", sizeof(ebeam->name));
+
+ if (udev->manufacturer)
+ strlcat(ebeam->name,
+ udev->manufacturer,
+ sizeof(ebeam->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(ebeam->name, " ", sizeof(ebeam->name));
+ strlcat(ebeam->name,
+ udev->product,
+ sizeof(ebeam->name));
+ }
+
+ if (strlcat(ebeam->name, ")", sizeof(ebeam->name))
+ >= sizeof(ebeam->name)) {
+ /* overflowed, closing ) anyway */
+ ebeam->name[sizeof(ebeam->name) - 2] = ')';
+ }
+ }
+
+ /* usb tree */
+ usb_make_path(udev, ebeam->phys, sizeof(ebeam->phys));
+ strlcat(ebeam->phys, "/input0", sizeof(ebeam->phys));
+
+ /* input setup */
+ input_dev->name = ebeam->name;
+ input_dev->phys = ebeam->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+
+ input_set_drvdata(input_dev, ebeam);
+
+ input_dev->open = ebeam_open;
+ input_dev->close = ebeam_close;
+
+ /* usb urb setup */
+ if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
+ usb_fill_int_urb(ebeam->irq,
+ udev,
+ usb_rcvintpipe(udev,
+ endpoint->bEndpointAddress),
+ ebeam->data,
+ REPT_SIZE,
+ ebeam_irq,
+ ebeam,
+ endpoint->bInterval);
+ else
+ usb_fill_bulk_urb(ebeam->irq,
+ udev,
+ usb_rcvbulkpipe(udev,
+ endpoint->bEndpointAddress),
+ ebeam->data,
+ REPT_SIZE,
+ ebeam_irq,
+ ebeam);
+
+ ebeam->irq->dev = udev;
+ ebeam->irq->transfer_dma = ebeam->data_dma;
+ ebeam->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* usb final setup */
+ usb_set_intfdata(intf, ebeam);
+
+ /* sysfs setup */
+ err = sysfs_create_group(&intf->dev.kobj, &ebeam_attr_group);
+ if (err) {
+ dev_dbg(&intf->dev,
+ "%s - cannot create sysfs group, err: %d\n",
+ __func__, err);
+ goto out_free_usb;
+ }
+
+ /* input final setup */
+ ebeam_setup_input(ebeam, input_dev);
+
+ err = input_register_device(ebeam->input);
+ if (err) {
+ dev_dbg(&intf->dev,
+ "%s - input_register_device failed, err: %d\n",
+ __func__, err);
+ goto out_remove_sysfs;
+ }
+
+ return 0;
+
+out_remove_sysfs:
+ sysfs_remove_group(&intf->dev.kobj, &ebeam_attr_group);
+out_free_usb:
+ usb_set_intfdata(intf, NULL);
+ usb_free_urb(ebeam->irq);
+out_free_buffers:
+ ebeam_free_buffers(udev, ebeam);
+out_free:
+ input_free_device(input_dev);
+ kfree(ebeam);
+ return err;
+}
+
+static void ebeam_disconnect(struct usb_interface *intf)
+{
+ struct ebeam_device *ebeam = usb_get_intfdata(intf);
+
+ if (!ebeam)
+ return;
+
+ dev_dbg(&intf->dev,
+ "%s - ebeam is initialized, cleaning up\n", __func__);
+
+ usb_set_intfdata(intf, NULL);
+ /* this will stop IO via close */
+ input_unregister_device(ebeam->input);
+ sysfs_remove_group(&intf->dev.kobj, &ebeam_attr_group);
+ usb_free_urb(ebeam->irq);
+ ebeam_free_buffers(interface_to_usbdev(intf), ebeam);
+ kfree(ebeam);
+}
+
+MODULE_DEVICE_TABLE(usb, ebeam_devices);
+
+static struct usb_driver ebeam_driver = {
+ .name = "ebeam",
+ .probe = ebeam_probe,
+ .disconnect = ebeam_disconnect,
+ .suspend = ebeam_suspend,
+ .resume = ebeam_resume,
+ .reset_resume = ebeam_resume,
+ .id_table = ebeam_devices,
+ .supports_autosuspend = 1,
+};
+
+module_usb_driver(ebeam_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--
2.3.8
^ permalink raw reply related
* [RFC ebeam PATCH 1/2] hid: Blacklist eBeam devices
From: Yann Cantin @ 2015-07-20 21:03 UTC (permalink / raw)
To: linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w, jkosina-AlSwsSmVLrQ,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Yann Cantin
In-Reply-To: <1437426199-29866-1-git-send-email-yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>
Signed-off-by: Yann Cantin <yann.cantin-QFKgK+z4sOrR7s880joybQ@public.gmane.org>
---
drivers/hid/hid-core.c | 6 ++++++
drivers/hid/hid-ids.h | 6 ++++++
2 files changed, 12 insertions(+)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 157c627..db4c7ee 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2267,6 +2267,12 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) },
+#if defined(CONFIG_INPUT_EBEAM_USB)
+ { HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_USB2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_EFI, USB_DEVICE_ID_EFI_EBEAM_BT_USB2) },
+#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b04b082..ca013c2 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -303,6 +303,12 @@
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001
+#define USB_VENDOR_ID_EFI 0x2650
+#define USB_DEVICE_ID_EFI_EBEAM_USB1 0x1311
+#define USB_DEVICE_ID_EFI_EBEAM_USB2 0x1315
+#define USB_DEVICE_ID_EFI_EBEAM_BT_USB1 0x1313
+#define USB_DEVICE_ID_EFI_EBEAM_BT_USB2 0x1320
+
#define USB_VENDOR_ID_ELAN 0x04f3
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b
--
2.3.8
^ permalink raw reply related
* [RFC ebeam PATCH 0/3] new USB eBeam input driver
From: Yann Cantin @ 2015-07-20 21:03 UTC (permalink / raw)
To: linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w, jkosina-AlSwsSmVLrQ,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r
Hi,
New USB input driver for eBeam devices.
Currently supported (tested) :
- Luidia eBeam classic projection and edge projection models
- Nec "interactive solution" NP01Wi1 & NP01Wi2 accessories.
Patch 1 to blacklist the devices for hid generic-usb.
Patch 2 is the actual driver.
Notable stuff :
- use div64_s64 for portable 64/64-bits divisions.
- 13 sysfs custom files : 9 values for the transformation matrix,
4 for xy ranges and a calibration trigger.
- need userspace gui tool for calibration (ebeam.tuxfamily.org)
Side notes :
- The module run fine since 3.3.6, both x86_32 and 64.
- Already reviewed in 2012 and 2013, but i have'nt pushed for inclusion.
- The only recent change is switching to non world-writable sysfs files.
- There is a proprietary application suite based on libusb, hope it won't
break with this driver.
Thanks for your help.
^ permalink raw reply
* Re: [PATCH V3 4/5] mm: mmap: Add mmap flag to request VM_LOCKONFAULT
From: Chris Metcalf @ 2015-07-20 20:40 UTC (permalink / raw)
To: Paul Gortmaker, Eric B Munson
Cc: Andrew Morton, Michal Hocko, Vlastimil Babka, LKML, linux-mm,
linux-arch, linux-api, linux-next@vger.kernel.org
In-Reply-To: <CAP=VYLq5=9DCfncJpQizcSbQt1O7VL2yEdzZNOFK+M3pqLpb3Q@mail.gmail.com>
On 07/18/2015 03:11 PM, Paul Gortmaker wrote:
> On Tue, Jul 7, 2015 at 1:03 PM, Eric B Munson<emunson@akamai.com> wrote:
>> >The cost of faulting in all memory to be locked can be very high when
>> >working with large mappings. If only portions of the mapping will be
>> >used this can incur a high penalty for locking.
>> >
>> >Now that we have the new VMA flag for the locked but not present state,
>> >expose it as an mmap option like MAP_LOCKED -> VM_LOCKED.
> An automatic bisection on arch/tile leads to this commit:
>
> 5a5656f2c9b61c74c15f9ef3fa2e6513b6c237bb is the first bad commit
> commit 5a5656f2c9b61c74c15f9ef3fa2e6513b6c237bb
> Author: Eric B Munson<emunson@akamai.com>
> Date: Thu Jul 16 10:09:22 2015 +1000
>
> mm: mmap: add mmap flag to request VM_LOCKONFAULT
Eric, I'm happy to help with figuring out the tile issues.
--
Chris Metcalf, EZChip Semiconductor
http://www.ezchip.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox