Re: [PATCH v1] kernel/trace:check the val against the available mem

2018-04-03 Thread Michal Hocko
On Tue 03-04-18 10:17:53, Steven Rostedt wrote:
> On Tue, 3 Apr 2018 15:56:07 +0200
> Michal Hocko  wrote:
[...]
> > I simply do not see the difference between the two. Both have the same
> > deadly effect in the end. The direct OOM has an arguable advantage that
> > the effect is immediate rather than subtle with potential performance
> > side effects until the machine OOMs after crawling for quite some time.
> 
> The difference is if the allocation succeeds or not. If it doesn't
> succeed, we free all memory that we tried to allocate. If it succeeds
> and causes issues, then yes, that's the admins fault.

What am I trying to say is that this is so extremely time and workload
sensitive that you can hardly have a stable behavior. It will become a
pure luck whether the failure happens.

> I'm worried about
> the accidental putting in too big of a number, either by an admin by
> mistake, or some stupid script that just thinks the current machines
> has terabytes of memory.

I would argue that stupid scripts should have no business calling root
only interfaces which can allocate a lot of memory and cause OOMs.

> I'm under the assumption that if I allocate an allocation of 32 pages
> with RETRY_MAYFAIL, and there's 2 pages available, but not 32, and
> while my allocation is reclaiming memory, and another task comes in and
> asks for a single page, it can still succeed. This would be why I would
> be using RETRY_MAYFAIL with higher orders of pages, that it doesn't
> take all memory in the system if it fails. Is this assumption incorrect?

Yes. There is no guarantee that the allocation will get the memory it
reclaimed in the direct reclaim. Pages are simply freed back into the
pool and it is a matter of timing who gets them.

> The current approach of allocating 1 page at a time with RETRY_MAYFAIL
> is that it will succeed to get any pages that are available, until
> there are none, and if some unlucky task asks for memory during that
> time, it is guaranteed to fail its allocation triggering an OOM.
> 
> I was thinking of doing something like:
> 
>   large_pages = nr_pages / 32;
>   if (large_pages) {
>   pages = alloc_pages_node(cpu_to_node(cpu),
>   GFP_KERNEL | __GFP_RETRY_MAYFAIL, 5);
>   if (pages)
>   /* break up pages */
>   else
>   /* try to allocate with NORETRY */
>   }

You can do so, of course. In fact it would have some advantages over
single pages because you would fragment the memory less but this is not
a reliable prevention from OOM killing and the complete memory
depletion if you allow arbitrary trace buffer sizes.

> Now it will allocate memory in 32 page chunks using reclaim. If it
> fails to allocate them, it would not have taken up any smaller chunks
> that were available, leaving them for other users. It would then go
> back to singe pages, allocating with RETRY. Or I could just say screw
> it, and make the allocation of the ring buffer always be 32 page chunks
> (or at least make it user defined).

yes a fallback is questionable. Whether to make the batch size
configuration is a matter of how much internal details you want to
expose to userspace.
-- 
Michal Hocko
SUSE Labs


Re: [PATCH v1] kernel/trace:check the val against the available mem

2018-04-03 Thread Michal Hocko
On Tue 03-04-18 10:17:53, Steven Rostedt wrote:
> On Tue, 3 Apr 2018 15:56:07 +0200
> Michal Hocko  wrote:
[...]
> > I simply do not see the difference between the two. Both have the same
> > deadly effect in the end. The direct OOM has an arguable advantage that
> > the effect is immediate rather than subtle with potential performance
> > side effects until the machine OOMs after crawling for quite some time.
> 
> The difference is if the allocation succeeds or not. If it doesn't
> succeed, we free all memory that we tried to allocate. If it succeeds
> and causes issues, then yes, that's the admins fault.

What am I trying to say is that this is so extremely time and workload
sensitive that you can hardly have a stable behavior. It will become a
pure luck whether the failure happens.

> I'm worried about
> the accidental putting in too big of a number, either by an admin by
> mistake, or some stupid script that just thinks the current machines
> has terabytes of memory.

I would argue that stupid scripts should have no business calling root
only interfaces which can allocate a lot of memory and cause OOMs.

> I'm under the assumption that if I allocate an allocation of 32 pages
> with RETRY_MAYFAIL, and there's 2 pages available, but not 32, and
> while my allocation is reclaiming memory, and another task comes in and
> asks for a single page, it can still succeed. This would be why I would
> be using RETRY_MAYFAIL with higher orders of pages, that it doesn't
> take all memory in the system if it fails. Is this assumption incorrect?

Yes. There is no guarantee that the allocation will get the memory it
reclaimed in the direct reclaim. Pages are simply freed back into the
pool and it is a matter of timing who gets them.

> The current approach of allocating 1 page at a time with RETRY_MAYFAIL
> is that it will succeed to get any pages that are available, until
> there are none, and if some unlucky task asks for memory during that
> time, it is guaranteed to fail its allocation triggering an OOM.
> 
> I was thinking of doing something like:
> 
>   large_pages = nr_pages / 32;
>   if (large_pages) {
>   pages = alloc_pages_node(cpu_to_node(cpu),
>   GFP_KERNEL | __GFP_RETRY_MAYFAIL, 5);
>   if (pages)
>   /* break up pages */
>   else
>   /* try to allocate with NORETRY */
>   }

You can do so, of course. In fact it would have some advantages over
single pages because you would fragment the memory less but this is not
a reliable prevention from OOM killing and the complete memory
depletion if you allow arbitrary trace buffer sizes.

> Now it will allocate memory in 32 page chunks using reclaim. If it
> fails to allocate them, it would not have taken up any smaller chunks
> that were available, leaving them for other users. It would then go
> back to singe pages, allocating with RETRY. Or I could just say screw
> it, and make the allocation of the ring buffer always be 32 page chunks
> (or at least make it user defined).

yes a fallback is questionable. Whether to make the batch size
configuration is a matter of how much internal details you want to
expose to userspace.
-- 
Michal Hocko
SUSE Labs


Re: [PATCH v2 1/3] locking: Document the semantics of spin_is_locked()

2018-04-03 Thread Paul E. McKenney
On Tue, Apr 03, 2018 at 08:03:56AM -0700, Paul E. McKenney wrote:
> On Tue, Apr 03, 2018 at 04:43:00PM +0200, Peter Zijlstra wrote:
> > On Tue, Apr 03, 2018 at 07:17:18AM -0700, Paul E. McKenney wrote:
> > > Suggestions for a fix?  Clearly great care is required when using it
> > > in things like WARN_ON()...
> > 
> > Yeah, don't use it there, use lockdep_assert_held().
> 
> Good point, -ETOOEARLY.  ;-)
> 
> > As I stated before in this thread, ideally we'd make *_is_locked() go
> > away entirely.
> 
> After being reminded of the issues on UP systems, I now have much more
> sympathy for that view...

And so the main remaining use case is debug prints on !PROVE_LOCKING
builds.  Which need some thought about the UP case.

Or am I missing something here?

Thanx, Paul



Re: [PATCH v2 1/3] locking: Document the semantics of spin_is_locked()

2018-04-03 Thread Paul E. McKenney
On Tue, Apr 03, 2018 at 08:03:56AM -0700, Paul E. McKenney wrote:
> On Tue, Apr 03, 2018 at 04:43:00PM +0200, Peter Zijlstra wrote:
> > On Tue, Apr 03, 2018 at 07:17:18AM -0700, Paul E. McKenney wrote:
> > > Suggestions for a fix?  Clearly great care is required when using it
> > > in things like WARN_ON()...
> > 
> > Yeah, don't use it there, use lockdep_assert_held().
> 
> Good point, -ETOOEARLY.  ;-)
> 
> > As I stated before in this thread, ideally we'd make *_is_locked() go
> > away entirely.
> 
> After being reminded of the issues on UP systems, I now have much more
> sympathy for that view...

And so the main remaining use case is debug prints on !PROVE_LOCKING
builds.  Which need some thought about the UP case.

Or am I missing something here?

Thanx, Paul



Re: [PATCH v2] f2fs: remain written times to update inode during fsync

2018-04-03 Thread Jaegeuk Kim
On 04/03, Chao Yu wrote:
> On 2018/4/3 13:23, Jaegeuk Kim wrote:
> > On 04/03, Chao Yu wrote:
> >> On 2018/3/31 0:30, Jaegeuk Kim wrote:
> >>> Change log from v1:
> >>>  - add more description
> >>>
> >>> This fixes xfstests/generic/392.
> >>>
> >>> The failure was caused by different times between 1) one marked in the 
> >>> last
> >>> fsync(2) call and 2) the other given by roll-forward recovery after 
> >>> power-cut.
> >>> The reason was that we skipped updating inode block at 1), since its 
> >>> i_size
> >>> was recoverable along with 4KB-aligned data writes, which was fixed by:
> >>>   "f2fs: fix a wrong condition in f2fs_skip_inode_update"
> >>>
> >>> Signed-off-by: Jaegeuk Kim 
> >>> ---
> >>>  fs/f2fs/f2fs.h  | 15 +++
> >>>  fs/f2fs/inode.c |  4 
> >>>  2 files changed, 19 insertions(+)
> >>>
> >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> >>> index 000f93f6767e..675c39d85111 100644
> >>> --- a/fs/f2fs/f2fs.h
> >>> +++ b/fs/f2fs/f2fs.h
> >>> @@ -664,6 +664,7 @@ struct f2fs_inode_info {
> >>>   kprojid_t i_projid; /* id for project quota */
> >>>   int i_inline_xattr_size;/* inline xattr size */
> >>>   struct timespec i_crtime;   /* inode creation time */
> >>> + struct timespec i_disk_time[4]; /* inode disk times */
> >>>  };
> >>>  
> >>>  static inline void get_extent_info(struct extent_info *ext,
> >>> @@ -2457,6 +2458,11 @@ static inline void clear_file(struct inode *inode, 
> >>> int type)
> >>>   f2fs_mark_inode_dirty_sync(inode, true);
> >>>  }
> >>>  
> >>> +static inline bool time_equal(struct timespec a, struct timespec b)
> >>> +{
> >>> + return (a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec);
> >>> +}
> >>
> >> We can use existing timespec_equal in  instead of defining a
> >> duplicated one?
> > 
> > It is defined with const parameters.
> 
> I didn't get it, const keyword can used to protect parameter not to be changed
> in that function, that will be more safe, so it will be better to use that 
> one?

Oh, I just made a mistake when testing timespec_equal().
I really need more recess time. :P

Change log from v3:
 - use timespec_equal()

This fixes xfstests/generic/392.

The failure was caused by different times between 1) one marked in the last
fsync(2) call and 2) the other given by roll-forward recovery after power-cut.
The reason was that we skipped updating inode block at 1), since its i_size
was recoverable along with 4KB-aligned data writes, which was fixed by:
  "f2fs: fix a wrong condition in f2fs_skip_inode_update"

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/f2fs.h  | 11 +++
 fs/f2fs/inode.c |  8 
 2 files changed, 19 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 7102d3965fea..1df7f10476d6 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -664,6 +664,7 @@ struct f2fs_inode_info {
kprojid_t i_projid; /* id for project quota */
int i_inline_xattr_size;/* inline xattr size */
struct timespec i_crtime;   /* inode creation time */
+   struct timespec i_disk_time[4]; /* inode disk times */
 };
 
 static inline void get_extent_info(struct extent_info *ext,
@@ -2474,6 +2475,16 @@ static inline bool f2fs_skip_inode_update(struct inode 
*inode, int dsync)
i_size_read(inode) & ~PAGE_MASK)
return false;
 
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time, >i_atime))
+   return false;
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, >i_ctime))
+   return false;
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, >i_mtime))
+   return false;
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time + 3,
+   _I(inode)->i_crtime))
+   return false;
+
down_read(_I(inode)->i_sem);
ret = F2FS_I(inode)->last_disk_size == i_size_read(inode);
up_read(_I(inode)->i_sem);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 401f09ccce7e..e0d9e8f27ed2 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -284,6 +284,10 @@ static int do_read_inode(struct inode *inode)
fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
}
 
+   F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
+   F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
+   F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+   F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
f2fs_put_page(node_page, 1);
 
stat_inc_inline_xattr(inode);
@@ -444,6 +448,10 @@ void update_inode(struct inode *inode, struct page 
*node_page)
if (inode->i_nlink == 0)
clear_inline_node(node_page);
 
+   F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
+   F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
+   F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+   F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
 }
 
 

Re: [PATCH v2] f2fs: remain written times to update inode during fsync

2018-04-03 Thread Jaegeuk Kim
On 04/03, Chao Yu wrote:
> On 2018/4/3 13:23, Jaegeuk Kim wrote:
> > On 04/03, Chao Yu wrote:
> >> On 2018/3/31 0:30, Jaegeuk Kim wrote:
> >>> Change log from v1:
> >>>  - add more description
> >>>
> >>> This fixes xfstests/generic/392.
> >>>
> >>> The failure was caused by different times between 1) one marked in the 
> >>> last
> >>> fsync(2) call and 2) the other given by roll-forward recovery after 
> >>> power-cut.
> >>> The reason was that we skipped updating inode block at 1), since its 
> >>> i_size
> >>> was recoverable along with 4KB-aligned data writes, which was fixed by:
> >>>   "f2fs: fix a wrong condition in f2fs_skip_inode_update"
> >>>
> >>> Signed-off-by: Jaegeuk Kim 
> >>> ---
> >>>  fs/f2fs/f2fs.h  | 15 +++
> >>>  fs/f2fs/inode.c |  4 
> >>>  2 files changed, 19 insertions(+)
> >>>
> >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> >>> index 000f93f6767e..675c39d85111 100644
> >>> --- a/fs/f2fs/f2fs.h
> >>> +++ b/fs/f2fs/f2fs.h
> >>> @@ -664,6 +664,7 @@ struct f2fs_inode_info {
> >>>   kprojid_t i_projid; /* id for project quota */
> >>>   int i_inline_xattr_size;/* inline xattr size */
> >>>   struct timespec i_crtime;   /* inode creation time */
> >>> + struct timespec i_disk_time[4]; /* inode disk times */
> >>>  };
> >>>  
> >>>  static inline void get_extent_info(struct extent_info *ext,
> >>> @@ -2457,6 +2458,11 @@ static inline void clear_file(struct inode *inode, 
> >>> int type)
> >>>   f2fs_mark_inode_dirty_sync(inode, true);
> >>>  }
> >>>  
> >>> +static inline bool time_equal(struct timespec a, struct timespec b)
> >>> +{
> >>> + return (a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec);
> >>> +}
> >>
> >> We can use existing timespec_equal in  instead of defining a
> >> duplicated one?
> > 
> > It is defined with const parameters.
> 
> I didn't get it, const keyword can used to protect parameter not to be changed
> in that function, that will be more safe, so it will be better to use that 
> one?

Oh, I just made a mistake when testing timespec_equal().
I really need more recess time. :P

Change log from v3:
 - use timespec_equal()

This fixes xfstests/generic/392.

The failure was caused by different times between 1) one marked in the last
fsync(2) call and 2) the other given by roll-forward recovery after power-cut.
The reason was that we skipped updating inode block at 1), since its i_size
was recoverable along with 4KB-aligned data writes, which was fixed by:
  "f2fs: fix a wrong condition in f2fs_skip_inode_update"

Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/f2fs.h  | 11 +++
 fs/f2fs/inode.c |  8 
 2 files changed, 19 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 7102d3965fea..1df7f10476d6 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -664,6 +664,7 @@ struct f2fs_inode_info {
kprojid_t i_projid; /* id for project quota */
int i_inline_xattr_size;/* inline xattr size */
struct timespec i_crtime;   /* inode creation time */
+   struct timespec i_disk_time[4]; /* inode disk times */
 };
 
 static inline void get_extent_info(struct extent_info *ext,
@@ -2474,6 +2475,16 @@ static inline bool f2fs_skip_inode_update(struct inode 
*inode, int dsync)
i_size_read(inode) & ~PAGE_MASK)
return false;
 
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time, >i_atime))
+   return false;
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, >i_ctime))
+   return false;
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, >i_mtime))
+   return false;
+   if (!timespec_equal(F2FS_I(inode)->i_disk_time + 3,
+   _I(inode)->i_crtime))
+   return false;
+
down_read(_I(inode)->i_sem);
ret = F2FS_I(inode)->last_disk_size == i_size_read(inode);
up_read(_I(inode)->i_sem);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 401f09ccce7e..e0d9e8f27ed2 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -284,6 +284,10 @@ static int do_read_inode(struct inode *inode)
fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
}
 
+   F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
+   F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
+   F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+   F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
f2fs_put_page(node_page, 1);
 
stat_inc_inline_xattr(inode);
@@ -444,6 +448,10 @@ void update_inode(struct inode *inode, struct page 
*node_page)
if (inode->i_nlink == 0)
clear_inline_node(node_page);
 
+   F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
+   F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
+   F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+   F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
 }
 
 void update_inode_page(struct inode 

Re: [PATCH v2] x86/xen/efi: Initialize UEFI secure boot state during dom0 boot

2018-04-03 Thread Daniel Kiper
On Tue, Apr 03, 2018 at 08:44:41AM -0700, James Bottomley wrote:
> On Tue, 2018-04-03 at 16:39 +0200, Daniel Kiper wrote:
> > Initialize UEFI secure boot state during dom0 boot. Otherwise the
> > kernel
> > may not even know that it runs on secure boot enabled platform.
> >
> > Signed-off-by: Daniel Kiper 
> > ---
> >  arch/x86/xen/efi.c|   57
> > +
> >  drivers/firmware/efi/libstub/secureboot.c |3 ++
> >  2 files changed, 60 insertions(+)
> >
> > diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
> > index a18703b..1804b27 100644
> > --- a/arch/x86/xen/efi.c
> > +++ b/arch/x86/xen/efi.c
> > @@ -115,6 +115,61 @@ static efi_system_table_t __init
> > *xen_efi_probe(void)
> >     return _systab_xen;
> >  }
> >  
> > +/*
> > + * Determine whether we're in secure boot mode.
> > + *
> > + * Please keep the logic in sync with
> > + * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
> > + */
> > +static enum efi_secureboot_mode xen_efi_get_secureboot(void)
> > +{
> > +   static efi_guid_t efi_variable_guid =
> > EFI_GLOBAL_VARIABLE_GUID;
> > +   static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
> > +   efi_status_t status;
> > +   u8 moksbstate, secboot, setupmode;
> > +   unsigned long size;
> > +
> > +   size = sizeof(secboot);
> > +   status = efi.get_variable(L"SecureBoot", _variable_guid,
> > +     NULL, , );
> > +
> > +   if (status == EFI_NOT_FOUND)
> > +   return efi_secureboot_mode_disabled;
> > +
> > +   if (status != EFI_SUCCESS)
> > +   goto out_efi_err;
> > +
> > +   size = sizeof(setupmode);
> > +   status = efi.get_variable(L"SetupMode", _variable_guid,
> > +     NULL, , );
> > +
> > +   if (status != EFI_SUCCESS)
> > +   goto out_efi_err;
> > +
> > +   if (secboot == 0 || setupmode == 1)
> > +   return efi_secureboot_mode_disabled;
> > +
> > +   /* See if a user has put the shim into insecure mode. */
> > +   size = sizeof(moksbstate);
> > +   status = efi.get_variable(L"MokSBStateRT", _guid,
> > +     NULL, , );
> > +
> > +   /* If it fails, we don't care why. Default to secure. */
> > +   if (status != EFI_SUCCESS)
> > +   goto secure_boot_enabled;
> > +
> > +   if (moksbstate == 1)
> > +   return efi_secureboot_mode_disabled;
> > +
> > + secure_boot_enabled:
> > +   pr_info("UEFI Secure Boot is enabled.\n");
> > +   return efi_secureboot_mode_enabled;
> > +
> > + out_efi_err:
> > +   pr_err("Could not determine UEFI Secure Boot status.\n");
> > +   return efi_secureboot_mode_unknown;
> > +}
> > +
>
> This looks like a bad idea: you're duplicating the secure boot check in
>
> drivers/firmware/efi/libstub/secureboot.c
>
> Which is an implementation of policy.  If we have to have policy in the
> kernel, it should really only be in one place to prevent drift; why
> can't you simply use the libstub efi_get_secureboot() so we're not
> duplicating the implementation of policy?

Well, here is the first version of this patch: 
https://lkml.org/lkml/2018/1/9/496
Ard did not like it. I was not happy too. In general both approaches are not 
perfect.
More you can find in the discussion around this patchset. If you have better 
idea
how to do that I am happy to implement it.

Daniel


Re: [PATCH v2] x86/xen/efi: Initialize UEFI secure boot state during dom0 boot

2018-04-03 Thread Daniel Kiper
On Tue, Apr 03, 2018 at 08:44:41AM -0700, James Bottomley wrote:
> On Tue, 2018-04-03 at 16:39 +0200, Daniel Kiper wrote:
> > Initialize UEFI secure boot state during dom0 boot. Otherwise the
> > kernel
> > may not even know that it runs on secure boot enabled platform.
> >
> > Signed-off-by: Daniel Kiper 
> > ---
> >  arch/x86/xen/efi.c|   57
> > +
> >  drivers/firmware/efi/libstub/secureboot.c |3 ++
> >  2 files changed, 60 insertions(+)
> >
> > diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
> > index a18703b..1804b27 100644
> > --- a/arch/x86/xen/efi.c
> > +++ b/arch/x86/xen/efi.c
> > @@ -115,6 +115,61 @@ static efi_system_table_t __init
> > *xen_efi_probe(void)
> >     return _systab_xen;
> >  }
> >  
> > +/*
> > + * Determine whether we're in secure boot mode.
> > + *
> > + * Please keep the logic in sync with
> > + * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
> > + */
> > +static enum efi_secureboot_mode xen_efi_get_secureboot(void)
> > +{
> > +   static efi_guid_t efi_variable_guid =
> > EFI_GLOBAL_VARIABLE_GUID;
> > +   static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
> > +   efi_status_t status;
> > +   u8 moksbstate, secboot, setupmode;
> > +   unsigned long size;
> > +
> > +   size = sizeof(secboot);
> > +   status = efi.get_variable(L"SecureBoot", _variable_guid,
> > +     NULL, , );
> > +
> > +   if (status == EFI_NOT_FOUND)
> > +   return efi_secureboot_mode_disabled;
> > +
> > +   if (status != EFI_SUCCESS)
> > +   goto out_efi_err;
> > +
> > +   size = sizeof(setupmode);
> > +   status = efi.get_variable(L"SetupMode", _variable_guid,
> > +     NULL, , );
> > +
> > +   if (status != EFI_SUCCESS)
> > +   goto out_efi_err;
> > +
> > +   if (secboot == 0 || setupmode == 1)
> > +   return efi_secureboot_mode_disabled;
> > +
> > +   /* See if a user has put the shim into insecure mode. */
> > +   size = sizeof(moksbstate);
> > +   status = efi.get_variable(L"MokSBStateRT", _guid,
> > +     NULL, , );
> > +
> > +   /* If it fails, we don't care why. Default to secure. */
> > +   if (status != EFI_SUCCESS)
> > +   goto secure_boot_enabled;
> > +
> > +   if (moksbstate == 1)
> > +   return efi_secureboot_mode_disabled;
> > +
> > + secure_boot_enabled:
> > +   pr_info("UEFI Secure Boot is enabled.\n");
> > +   return efi_secureboot_mode_enabled;
> > +
> > + out_efi_err:
> > +   pr_err("Could not determine UEFI Secure Boot status.\n");
> > +   return efi_secureboot_mode_unknown;
> > +}
> > +
>
> This looks like a bad idea: you're duplicating the secure boot check in
>
> drivers/firmware/efi/libstub/secureboot.c
>
> Which is an implementation of policy.  If we have to have policy in the
> kernel, it should really only be in one place to prevent drift; why
> can't you simply use the libstub efi_get_secureboot() so we're not
> duplicating the implementation of policy?

Well, here is the first version of this patch: 
https://lkml.org/lkml/2018/1/9/496
Ard did not like it. I was not happy too. In general both approaches are not 
perfect.
More you can find in the discussion around this patchset. If you have better 
idea
how to do that I am happy to implement it.

Daniel


Re: [PATCH v5 3/3] MIPS: use generic GCC library routines from lib/

2018-04-03 Thread James Hogan
On Tue, Apr 03, 2018 at 10:24:26AM +0100, Matt Redfearn wrote:
> From: Antony Pavlov 
> 
> The commit b35cd9884fa5 ("lib: Add shared copies of some GCC library
> routines") makes it possible to share generic GCC library routines by
> several architectures.
> 
> This commit removes several generic GCC library routines from
> arch/mips/lib/ in favour of similar routines from lib/.
> 
> Signed-off-by: Antony Pavlov 
> [Matt Redfearn] Use GENERIC_LIB_* named Kconfig entries
> Signed-off-by: Matt Redfearn 
> Cc: Palmer Dabbelt 
> Cc: Matt Redfearn 
> Cc: James Hogan 
> Cc: Ralf Baechle 
> Cc: linux-m...@linux-mips.org
> Cc: linux-kernel@vger.kernel.org

ci20_defconfig:
make[1]: *** No rule to make target 'arch/mips/lib/ashldi3.c', needed by 
'arch/mips/boot/compressed/ashldi3.c'.  Stop.
make[1]: *** Waiting for unfinished jobs
make: *** [arch/mips/Makefile +395 : vmlinuz] Error 2

same for db1xxx_defconfig (and possibly others).

Thanks
James


signature.asc
Description: Digital signature


Re: [PATCH v5 3/3] MIPS: use generic GCC library routines from lib/

2018-04-03 Thread James Hogan
On Tue, Apr 03, 2018 at 10:24:26AM +0100, Matt Redfearn wrote:
> From: Antony Pavlov 
> 
> The commit b35cd9884fa5 ("lib: Add shared copies of some GCC library
> routines") makes it possible to share generic GCC library routines by
> several architectures.
> 
> This commit removes several generic GCC library routines from
> arch/mips/lib/ in favour of similar routines from lib/.
> 
> Signed-off-by: Antony Pavlov 
> [Matt Redfearn] Use GENERIC_LIB_* named Kconfig entries
> Signed-off-by: Matt Redfearn 
> Cc: Palmer Dabbelt 
> Cc: Matt Redfearn 
> Cc: James Hogan 
> Cc: Ralf Baechle 
> Cc: linux-m...@linux-mips.org
> Cc: linux-kernel@vger.kernel.org

ci20_defconfig:
make[1]: *** No rule to make target 'arch/mips/lib/ashldi3.c', needed by 
'arch/mips/boot/compressed/ashldi3.c'.  Stop.
make[1]: *** Waiting for unfinished jobs
make: *** [arch/mips/Makefile +395 : vmlinuz] Error 2

same for db1xxx_defconfig (and possibly others).

Thanks
James


signature.asc
Description: Digital signature


Re: [PATCH v17 01/10] LIB: Introduce a generic PIO mapping method

2018-04-03 Thread John Garry

+int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
+{
+   struct logic_pio_hwaddr *range;
+   resource_size_t start = new_range->hw_start;
+   resource_size_t end = new_range->hw_start + new_range->size;
+   resource_size_t mmio_sz = 0;
+   resource_size_t iio_sz = MMIO_UPPER_LIMIT;
+   int ret = 0;
+
+   if (!new_range || !new_range->fwnode || !new_range->size)
+   return -EINVAL;
+
+   mutex_lock(_range_mutex);
+   list_for_each_entry_rcu(range, _range_list, list) {
+   if (range->fwnode == new_range->fwnode) {
+   /* range already there */
+   ret = -EFAULT;
+   goto end_register;
+   }




Hi Thierry,


This is the -EFAULT that propagates to pci-tegra.c's ->probe() and fails
to bind the driver.

I'm not exactly sure what's causing the duplicate here because it's
rather difficult to get at something useful from just the ->fwnode, but
I'm fairly sure that the reason this breaks is because the Tegra driver
will defer probe due to some regulators that aren't available on the
first try. Given the above code and the rest of this file, I can't see a
way to "fix" the driver and remove the I/O range on failure.

This is doubly bad because this doesn't only leak the ranges on probe
deferral, but also on driver unload, and we just added support for
building the Tegra driver as a loadable module, so these are actually
cases that can happen in regular uses of the driver.

I have no idea on how to fix this. Anyone know of a quick fix to restore
PCI for Tegra other than reverting all of these changes?

I suppose an API could be added to unregister the range, but the calling
sequence is rather obfuscated, so removing the range will look totally
asymmetric, I'm afraid.

Here's the call stack:

tegra_pcie_probe()
tegra_pcie_parse_dt()
of_pci_range_to_resource()
pci_register_io_range()
logic_pio_register_range()

So the range here is registered as part of a resource parsing function,
which is supposed to not have any side-effects. There's no equivalent of
that parsing routine (i.e. no "unparse" function that would undo the
effects of parsing).

Perhaps a cleaner way would be to decouple the parsing from the actual
request step that has the side-effect.


This could be added if we agreed that it would be useful.



Going back in history a little, it looks like even before this commit
the I/O range registration was triggered by the parsing code and even
the range leak was there, except that it caused pci_register_io_range()
to return 0 rather than -EFAULT. Perhaps the quickest fix for this would
be to do the same in the new code and restore drivers that accidentally
depend on this behaviour.


I can confirm that the following fixes the issue for me, though I don't
think it's a very clean fix given that the range will remain requested
forever, even if the driver is gone. But since that's already been the
case for quite a while, probably something that can be fixed separately.



Right, there was no way to deregister the range previously.  From 
looking at the history here I see no reason to not support it.


As for this patch, as you said, the only difference is that we fault on 
trying to register the same range again. So this solution seems reasonable.


On another point, for the tegra driver, is it possible to defer earlier 
in the probe, before these currently irreversible steps are taken?


Thanks very much,
John


Cc'ing linux-tegra for visibility.

Thierry

--- >8 ---
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
index 29cedeadb397..4664b87e1c5f 100644
--- a/lib/logic_pio.c
+++ b/lib/logic_pio.c
@@ -46,7 +46,6 @@ int logic_pio_register_range(struct logic_pio_hwaddr 
*new_range)
list_for_each_entry_rcu(range, _range_list, list) {
if (range->fwnode == new_range->fwnode) {
/* range already there */
-   ret = -EFAULT;
goto end_register;
}
if (range->flags == LOGIC_PIO_CPU_MMIO &&






Re: [PATCH v17 01/10] LIB: Introduce a generic PIO mapping method

2018-04-03 Thread John Garry

+int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
+{
+   struct logic_pio_hwaddr *range;
+   resource_size_t start = new_range->hw_start;
+   resource_size_t end = new_range->hw_start + new_range->size;
+   resource_size_t mmio_sz = 0;
+   resource_size_t iio_sz = MMIO_UPPER_LIMIT;
+   int ret = 0;
+
+   if (!new_range || !new_range->fwnode || !new_range->size)
+   return -EINVAL;
+
+   mutex_lock(_range_mutex);
+   list_for_each_entry_rcu(range, _range_list, list) {
+   if (range->fwnode == new_range->fwnode) {
+   /* range already there */
+   ret = -EFAULT;
+   goto end_register;
+   }




Hi Thierry,


This is the -EFAULT that propagates to pci-tegra.c's ->probe() and fails
to bind the driver.

I'm not exactly sure what's causing the duplicate here because it's
rather difficult to get at something useful from just the ->fwnode, but
I'm fairly sure that the reason this breaks is because the Tegra driver
will defer probe due to some regulators that aren't available on the
first try. Given the above code and the rest of this file, I can't see a
way to "fix" the driver and remove the I/O range on failure.

This is doubly bad because this doesn't only leak the ranges on probe
deferral, but also on driver unload, and we just added support for
building the Tegra driver as a loadable module, so these are actually
cases that can happen in regular uses of the driver.

I have no idea on how to fix this. Anyone know of a quick fix to restore
PCI for Tegra other than reverting all of these changes?

I suppose an API could be added to unregister the range, but the calling
sequence is rather obfuscated, so removing the range will look totally
asymmetric, I'm afraid.

Here's the call stack:

tegra_pcie_probe()
tegra_pcie_parse_dt()
of_pci_range_to_resource()
pci_register_io_range()
logic_pio_register_range()

So the range here is registered as part of a resource parsing function,
which is supposed to not have any side-effects. There's no equivalent of
that parsing routine (i.e. no "unparse" function that would undo the
effects of parsing).

Perhaps a cleaner way would be to decouple the parsing from the actual
request step that has the side-effect.


This could be added if we agreed that it would be useful.



Going back in history a little, it looks like even before this commit
the I/O range registration was triggered by the parsing code and even
the range leak was there, except that it caused pci_register_io_range()
to return 0 rather than -EFAULT. Perhaps the quickest fix for this would
be to do the same in the new code and restore drivers that accidentally
depend on this behaviour.


I can confirm that the following fixes the issue for me, though I don't
think it's a very clean fix given that the range will remain requested
forever, even if the driver is gone. But since that's already been the
case for quite a while, probably something that can be fixed separately.



Right, there was no way to deregister the range previously.  From 
looking at the history here I see no reason to not support it.


As for this patch, as you said, the only difference is that we fault on 
trying to register the same range again. So this solution seems reasonable.


On another point, for the tegra driver, is it possible to defer earlier 
in the probe, before these currently irreversible steps are taken?


Thanks very much,
John


Cc'ing linux-tegra for visibility.

Thierry

--- >8 ---
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
index 29cedeadb397..4664b87e1c5f 100644
--- a/lib/logic_pio.c
+++ b/lib/logic_pio.c
@@ -46,7 +46,6 @@ int logic_pio_register_range(struct logic_pio_hwaddr 
*new_range)
list_for_each_entry_rcu(range, _range_list, list) {
if (range->fwnode == new_range->fwnode) {
/* range already there */
-   ret = -EFAULT;
goto end_register;
}
if (range->flags == LOGIC_PIO_CPU_MMIO &&






Re: [PATCH v2 1/6] spi: core: handle timeout error from transfer_one()

2018-04-03 Thread Sergey Suloev

On 04/03/2018 06:52 PM, Mark Brown wrote:

On Tue, Apr 03, 2018 at 06:29:00PM +0300, Sergey Suloev wrote:

As long as sun4i/sun6i SPI drivers have overriden the default
"wait for completion" procedure then we need to properly
handle -ETIMEDOUT error from transfer_one().

Why is this connected to those drivers specifically?


These 2 drivers have their own "waiting" code and not using the code 
from SPI core.




Re: [PATCH v2 1/6] spi: core: handle timeout error from transfer_one()

2018-04-03 Thread Sergey Suloev

On 04/03/2018 06:52 PM, Mark Brown wrote:

On Tue, Apr 03, 2018 at 06:29:00PM +0300, Sergey Suloev wrote:

As long as sun4i/sun6i SPI drivers have overriden the default
"wait for completion" procedure then we need to properly
handle -ETIMEDOUT error from transfer_one().

Why is this connected to those drivers specifically?


These 2 drivers have their own "waiting" code and not using the code 
from SPI core.




Re: [PATCH V3 4/4] genirq/affinity: irq vector spread among online CPUs as far as possible

2018-04-03 Thread Ming Lei
On Tue, Apr 03, 2018 at 03:32:21PM +0200, Thomas Gleixner wrote:
> On Thu, 8 Mar 2018, Ming Lei wrote:
> > 1) before 84676c1f21 ("genirq/affinity: assign vectors to all possible 
> > CPUs")
> > irq 39, cpu list 0
> > irq 40, cpu list 1
> > irq 41, cpu list 2
> > irq 42, cpu list 3
> > 
> > 2) after 84676c1f21 ("genirq/affinity: assign vectors to all possible CPUs")
> > irq 39, cpu list 0-2
> > irq 40, cpu list 3-4,6
> > irq 41, cpu list 5
> > irq 42, cpu list 7
> > 
> > 3) after applying this patch against V4.15+:
> > irq 39, cpu list 0,4
> > irq 40, cpu list 1,6
> > irq 41, cpu list 2,5
> > irq 42, cpu list 3,7
> 
> That's more or less window dressing. If the device is already in use when
> the offline CPUs get hot plugged, then the interrupts still stay on cpu 0-3
> because the effective affinity of interrupts on X86 (and other
> architectures) is always a single CPU.
> 
> So this only might move interrupts to the hotplugged CPUs when the device
> is initialized after CPU hotplug and the actual vector allocation moves an
> interrupt out to the higher numbered CPUs if they have less vectors
> allocated than the lower numbered ones.

It works for blk-mq devices, such as NVMe.

Now NVMe driver creates num_possible_cpus() hw queues, and each
hw queue is assigned one msix irq vector.

Storage is Client/Server model, that means the interrupt is only
delivered to CPU after one IO request is submitted to hw queue and
it is completed by this hw queue.

When CPUs is hotplugged, and there will be IO submitted from these
CPUs, then finally IOs complete and irq events are generated from
hw queues, and notify these submission CPU by IRQ finally.

Thanks,
Ming


Re: [PATCH V3 4/4] genirq/affinity: irq vector spread among online CPUs as far as possible

2018-04-03 Thread Ming Lei
On Tue, Apr 03, 2018 at 03:32:21PM +0200, Thomas Gleixner wrote:
> On Thu, 8 Mar 2018, Ming Lei wrote:
> > 1) before 84676c1f21 ("genirq/affinity: assign vectors to all possible 
> > CPUs")
> > irq 39, cpu list 0
> > irq 40, cpu list 1
> > irq 41, cpu list 2
> > irq 42, cpu list 3
> > 
> > 2) after 84676c1f21 ("genirq/affinity: assign vectors to all possible CPUs")
> > irq 39, cpu list 0-2
> > irq 40, cpu list 3-4,6
> > irq 41, cpu list 5
> > irq 42, cpu list 7
> > 
> > 3) after applying this patch against V4.15+:
> > irq 39, cpu list 0,4
> > irq 40, cpu list 1,6
> > irq 41, cpu list 2,5
> > irq 42, cpu list 3,7
> 
> That's more or less window dressing. If the device is already in use when
> the offline CPUs get hot plugged, then the interrupts still stay on cpu 0-3
> because the effective affinity of interrupts on X86 (and other
> architectures) is always a single CPU.
> 
> So this only might move interrupts to the hotplugged CPUs when the device
> is initialized after CPU hotplug and the actual vector allocation moves an
> interrupt out to the higher numbered CPUs if they have less vectors
> allocated than the lower numbered ones.

It works for blk-mq devices, such as NVMe.

Now NVMe driver creates num_possible_cpus() hw queues, and each
hw queue is assigned one msix irq vector.

Storage is Client/Server model, that means the interrupt is only
delivered to CPU after one IO request is submitted to hw queue and
it is completed by this hw queue.

When CPUs is hotplugged, and there will be IO submitted from these
CPUs, then finally IOs complete and irq events are generated from
hw queues, and notify these submission CPU by IRQ finally.

Thanks,
Ming


Re: [PATCH] usbip: vhc_hcd: prevent module being removed while device are attached

2018-04-03 Thread Shuah Khan
On 04/03/2018 12:56 AM, Greg KH wrote:
> On Mon, Apr 02, 2018 at 02:52:31PM -0600, Shuah Khan wrote:
>> vhci_hcd module can be removed even when devices are attached. Fix to
>> prevent module removal when devices are still attached.
>>
>> Signed-off-by: Shuah Khan 
>> ---
>>  drivers/usb/usbip/vhci_sysfs.c | 25 +
>>  1 file changed, 21 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
>> index 48808388ec33..6a54b9aa92be 100644
>> --- a/drivers/usb/usbip/vhci_sysfs.c
>> +++ b/drivers/usb/usbip/vhci_sysfs.c
>> @@ -9,6 +9,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  
>>  #include "usbip_common.h"
>>  #include "vhci.h"
>> @@ -252,6 +253,8 @@ static ssize_t detach_store(struct device *dev, struct 
>> device_attribute *attr,
>>  if (ret < 0)
>>  return -EINVAL;
>>  
>> +module_put(THIS_MODULE);
>> +
>>  usbip_dbg_vhci_sysfs("Leave\n");
>>  
>>  return count;
>> @@ -302,7 +305,7 @@ static ssize_t attach_store(struct device *dev, struct 
>> device_attribute *attr,
>>  struct vhci_hcd *vhci_hcd;
>>  struct vhci_device *vdev;
>>  struct vhci *vhci;
>> -int err;
>> +int err, ret;
>>  unsigned long flags;
>>  
>>  /*
>> @@ -339,10 +342,18 @@ static ssize_t attach_store(struct device *dev, struct 
>> device_attribute *attr,
>>  else
>>  vdev = >vhci_hcd_hs->vdev[rhport];
>>  
>> +/* get module ref to avoid being removed with active attached devs */
>> +if (!try_module_get(THIS_MODULE)) {
>> +ret = -EAGAIN;
>> +goto module_get_err;
>> +}
> 
> That's really not a good idea, trying to grab your own module reference
> is considered racy and we stopped adding that code pattern to the kernel
> a long time ago.

Thanks. Good to know.

> 
> What's wrong if you remove the vhci module if devices are attached?  You
> can do that today for any other USB host driver, this shouldn't be
> "special".

This is a virtual device associated to a real physical device on a different
system. My concern is that if the module gets removed accidentally then it
could disrupt access to the remote device. The remote nature of the device
with several players involved makes this scenario a bit more complex than
a regular usb case when device is physically on the system. It is probably one
of the minor problems that could happen with a remote device.

I found a few modules that hold reference to themselves in the kernel. Block,
crypto, net, md, vfio, nfs.

md for example holds reference to itself when it creates a blank device.
vfio get regerence to itself it when opens pci and mediated devices.
Some network drivers do the same for handling virtual functions.
nfs does this for rpc handling.

I am not making a case for adding one more, however I am curious if this
vhci_hcd falls into a similar special case of handling virtual connections
and devices.

> 
> Also, kernel modules are never automatically removed by the system, so
> someone has to do this by hand, so they knew what they were doing :)
> 

Yes. This will not be a usual scenario. The question is whether not kernel
should detect driver is in use and prevent it.

thanks,
-- Shuah



Re: [PATCH] usbip: vhc_hcd: prevent module being removed while device are attached

2018-04-03 Thread Shuah Khan
On 04/03/2018 12:56 AM, Greg KH wrote:
> On Mon, Apr 02, 2018 at 02:52:31PM -0600, Shuah Khan wrote:
>> vhci_hcd module can be removed even when devices are attached. Fix to
>> prevent module removal when devices are still attached.
>>
>> Signed-off-by: Shuah Khan 
>> ---
>>  drivers/usb/usbip/vhci_sysfs.c | 25 +
>>  1 file changed, 21 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
>> index 48808388ec33..6a54b9aa92be 100644
>> --- a/drivers/usb/usbip/vhci_sysfs.c
>> +++ b/drivers/usb/usbip/vhci_sysfs.c
>> @@ -9,6 +9,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  
>>  #include "usbip_common.h"
>>  #include "vhci.h"
>> @@ -252,6 +253,8 @@ static ssize_t detach_store(struct device *dev, struct 
>> device_attribute *attr,
>>  if (ret < 0)
>>  return -EINVAL;
>>  
>> +module_put(THIS_MODULE);
>> +
>>  usbip_dbg_vhci_sysfs("Leave\n");
>>  
>>  return count;
>> @@ -302,7 +305,7 @@ static ssize_t attach_store(struct device *dev, struct 
>> device_attribute *attr,
>>  struct vhci_hcd *vhci_hcd;
>>  struct vhci_device *vdev;
>>  struct vhci *vhci;
>> -int err;
>> +int err, ret;
>>  unsigned long flags;
>>  
>>  /*
>> @@ -339,10 +342,18 @@ static ssize_t attach_store(struct device *dev, struct 
>> device_attribute *attr,
>>  else
>>  vdev = >vhci_hcd_hs->vdev[rhport];
>>  
>> +/* get module ref to avoid being removed with active attached devs */
>> +if (!try_module_get(THIS_MODULE)) {
>> +ret = -EAGAIN;
>> +goto module_get_err;
>> +}
> 
> That's really not a good idea, trying to grab your own module reference
> is considered racy and we stopped adding that code pattern to the kernel
> a long time ago.

Thanks. Good to know.

> 
> What's wrong if you remove the vhci module if devices are attached?  You
> can do that today for any other USB host driver, this shouldn't be
> "special".

This is a virtual device associated to a real physical device on a different
system. My concern is that if the module gets removed accidentally then it
could disrupt access to the remote device. The remote nature of the device
with several players involved makes this scenario a bit more complex than
a regular usb case when device is physically on the system. It is probably one
of the minor problems that could happen with a remote device.

I found a few modules that hold reference to themselves in the kernel. Block,
crypto, net, md, vfio, nfs.

md for example holds reference to itself when it creates a blank device.
vfio get regerence to itself it when opens pci and mediated devices.
Some network drivers do the same for handling virtual functions.
nfs does this for rpc handling.

I am not making a case for adding one more, however I am curious if this
vhci_hcd falls into a similar special case of handling virtual connections
and devices.

> 
> Also, kernel modules are never automatically removed by the system, so
> someone has to do this by hand, so they knew what they were doing :)
> 

Yes. This will not be a usual scenario. The question is whether not kernel
should detect driver is in use and prevent it.

thanks,
-- Shuah



Re: [PATCH] memcg, thp: do not invoke oom killer on thp charges

2018-04-03 Thread Michal Hocko
On Tue 03-04-18 10:58:53, Johannes Weiner wrote:
> On Wed, Mar 21, 2018 at 09:59:28PM +0100, Michal Hocko wrote:
> > From: Michal Hocko 
> > 
> > David has noticed that THP memcg charge can trigger the oom killer
> > since 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and
> > madvised allocations"). We have used an explicit __GFP_NORETRY
> > previously which ruled the OOM killer automagically.
> > 
> > Memcg charge path should be semantically compliant with the allocation
> > path and that means that if we do not trigger the OOM killer for costly
> > orders which should do the same in the memcg charge path as well.
> > Otherwise we are forcing callers to distinguish the two and use
> > different gfp masks which is both non-intuitive and bug prone. Not to
> > mention the maintenance burden.
> > 
> > Teach mem_cgroup_oom to bail out on costly order requests to fix the THP
> > issue as well as any other costly OOM eligible allocations to be added
> > in future.
> > 
> > Fixes: 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and 
> > madvised allocations")
> > Reported-by: David Rientjes 
> > Signed-off-by: Michal Hocko 
> 
> I also prefer this fix over having separate OOM behaviors (which is
> user-visible, and not just about technical ability to satisfy the
> allocation) between the allocator and memcg.
> 
> Acked-by: Johannes Weiner 

I will repost the patch with the currently merged THP specific handling
reverted (see below). While 9d3c3354bb85 might have been an appropriate
quick fix, we shouldn't keep it longterm for 4.17+ IMHO.

Does you ack apply to that patch as well?
---
>From 3e1b127dd6107a0e51654e90d9faef7f196f5a10 Mon Sep 17 00:00:00 2001
From: Michal Hocko 
Date: Wed, 21 Mar 2018 10:10:37 +0100
Subject: [PATCH] memcg, thp: do not invoke oom killer on thp charges

David has noticed that THP memcg charge can trigger the oom killer
since 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and
madvised allocations"). We have used an explicit __GFP_NORETRY
previously which ruled the OOM killer automagically.

Memcg charge path should be semantically compliant with the allocation
path and that means that if we do not trigger the OOM killer for
costly orders which should do the same in the memcg charge path as
well.  Otherwise we are forcing callers to distinguish the two and use
different gfp masks which is both non-intuitive and bug prone. As soon
as we get a costly high order kmalloc user we even do not have any means
to tell the memcg specific gfp mask to prevent from OOM because the
charging is deep within guts of the slab allocator.

The unexpected memcg OOM on THP has already been fixed upstream by
9d3c3354bb85 ("mm, thp: do not cause memcg oom for thp") but this is
one-off fix rather than a generic solution. Teach mem_cgroup_oom to bail
out on costly order requests to fix the THP issue as well as any other
costly OOM eligible allocations to be added in future.

Also revert 9d3c3354bb85 because special gfp for THP is no longer
needed.

Fixes: 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and 
madvised allocations")
Reported-by: David Rientjes 
Signed-off-by: Michal Hocko 
---
 mm/huge_memory.c | 5 ++---
 mm/khugepaged.c  | 8 ++--
 mm/memcontrol.c  | 2 +-
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 2297dd9cc7c3..0cc62405de9c 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -555,8 +555,7 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault 
*vmf, struct page *page,
 
VM_BUG_ON_PAGE(!PageCompound(page), page);
 
-   if (mem_cgroup_try_charge(page, vma->vm_mm, gfp | __GFP_NORETRY, ,
- true)) {
+   if (mem_cgroup_try_charge(page, vma->vm_mm, gfp, , true)) {
put_page(page);
count_vm_event(THP_FAULT_FALLBACK);
return VM_FAULT_FALLBACK;
@@ -1317,7 +1316,7 @@ int do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t 
orig_pmd)
}
 
if (unlikely(mem_cgroup_try_charge(new_page, vma->vm_mm,
-   huge_gfp | __GFP_NORETRY, , true))) {
+   huge_gfp, , true))) {
put_page(new_page);
split_huge_pmd(vma, vmf->pmd, vmf->address);
if (page)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 214e614b62b0..b7e2268dfc9a 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -960,9 +960,7 @@ static void collapse_huge_page(struct mm_struct *mm,
goto out_nolock;
}
 
-   /* Do not oom kill for khugepaged charges */
-   if (unlikely(mem_cgroup_try_charge(new_page, mm, gfp | __GFP_NORETRY,
-  , true))) {
+   if (unlikely(mem_cgroup_try_charge(new_page, mm, gfp, , true))) {

Re: [PATCH] memcg, thp: do not invoke oom killer on thp charges

2018-04-03 Thread Michal Hocko
On Tue 03-04-18 10:58:53, Johannes Weiner wrote:
> On Wed, Mar 21, 2018 at 09:59:28PM +0100, Michal Hocko wrote:
> > From: Michal Hocko 
> > 
> > David has noticed that THP memcg charge can trigger the oom killer
> > since 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and
> > madvised allocations"). We have used an explicit __GFP_NORETRY
> > previously which ruled the OOM killer automagically.
> > 
> > Memcg charge path should be semantically compliant with the allocation
> > path and that means that if we do not trigger the OOM killer for costly
> > orders which should do the same in the memcg charge path as well.
> > Otherwise we are forcing callers to distinguish the two and use
> > different gfp masks which is both non-intuitive and bug prone. Not to
> > mention the maintenance burden.
> > 
> > Teach mem_cgroup_oom to bail out on costly order requests to fix the THP
> > issue as well as any other costly OOM eligible allocations to be added
> > in future.
> > 
> > Fixes: 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and 
> > madvised allocations")
> > Reported-by: David Rientjes 
> > Signed-off-by: Michal Hocko 
> 
> I also prefer this fix over having separate OOM behaviors (which is
> user-visible, and not just about technical ability to satisfy the
> allocation) between the allocator and memcg.
> 
> Acked-by: Johannes Weiner 

I will repost the patch with the currently merged THP specific handling
reverted (see below). While 9d3c3354bb85 might have been an appropriate
quick fix, we shouldn't keep it longterm for 4.17+ IMHO.

Does you ack apply to that patch as well?
---
>From 3e1b127dd6107a0e51654e90d9faef7f196f5a10 Mon Sep 17 00:00:00 2001
From: Michal Hocko 
Date: Wed, 21 Mar 2018 10:10:37 +0100
Subject: [PATCH] memcg, thp: do not invoke oom killer on thp charges

David has noticed that THP memcg charge can trigger the oom killer
since 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and
madvised allocations"). We have used an explicit __GFP_NORETRY
previously which ruled the OOM killer automagically.

Memcg charge path should be semantically compliant with the allocation
path and that means that if we do not trigger the OOM killer for
costly orders which should do the same in the memcg charge path as
well.  Otherwise we are forcing callers to distinguish the two and use
different gfp masks which is both non-intuitive and bug prone. As soon
as we get a costly high order kmalloc user we even do not have any means
to tell the memcg specific gfp mask to prevent from OOM because the
charging is deep within guts of the slab allocator.

The unexpected memcg OOM on THP has already been fixed upstream by
9d3c3354bb85 ("mm, thp: do not cause memcg oom for thp") but this is
one-off fix rather than a generic solution. Teach mem_cgroup_oom to bail
out on costly order requests to fix the THP issue as well as any other
costly OOM eligible allocations to be added in future.

Also revert 9d3c3354bb85 because special gfp for THP is no longer
needed.

Fixes: 2516035499b9 ("mm, thp: remove __GFP_NORETRY from khugepaged and 
madvised allocations")
Reported-by: David Rientjes 
Signed-off-by: Michal Hocko 
---
 mm/huge_memory.c | 5 ++---
 mm/khugepaged.c  | 8 ++--
 mm/memcontrol.c  | 2 +-
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 2297dd9cc7c3..0cc62405de9c 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -555,8 +555,7 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault 
*vmf, struct page *page,
 
VM_BUG_ON_PAGE(!PageCompound(page), page);
 
-   if (mem_cgroup_try_charge(page, vma->vm_mm, gfp | __GFP_NORETRY, ,
- true)) {
+   if (mem_cgroup_try_charge(page, vma->vm_mm, gfp, , true)) {
put_page(page);
count_vm_event(THP_FAULT_FALLBACK);
return VM_FAULT_FALLBACK;
@@ -1317,7 +1316,7 @@ int do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t 
orig_pmd)
}
 
if (unlikely(mem_cgroup_try_charge(new_page, vma->vm_mm,
-   huge_gfp | __GFP_NORETRY, , true))) {
+   huge_gfp, , true))) {
put_page(new_page);
split_huge_pmd(vma, vmf->pmd, vmf->address);
if (page)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 214e614b62b0..b7e2268dfc9a 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -960,9 +960,7 @@ static void collapse_huge_page(struct mm_struct *mm,
goto out_nolock;
}
 
-   /* Do not oom kill for khugepaged charges */
-   if (unlikely(mem_cgroup_try_charge(new_page, mm, gfp | __GFP_NORETRY,
-  , true))) {
+   if (unlikely(mem_cgroup_try_charge(new_page, mm, gfp, , true))) {
result = SCAN_CGROUP_CHARGE_FAIL;
goto out_nolock;
}
@@ -1321,9 +1319,7 @@ static void 

Re: [PATCH v2 1/6] spi: core: handle timeout error from transfer_one()

2018-04-03 Thread Mark Brown
On Tue, Apr 03, 2018 at 06:29:00PM +0300, Sergey Suloev wrote:
> As long as sun4i/sun6i SPI drivers have overriden the default
> "wait for completion" procedure then we need to properly
> handle -ETIMEDOUT error from transfer_one().

Why is this connected to those drivers specifically?


signature.asc
Description: PGP signature


Re: [PATCH v2 1/6] spi: core: handle timeout error from transfer_one()

2018-04-03 Thread Mark Brown
On Tue, Apr 03, 2018 at 06:29:00PM +0300, Sergey Suloev wrote:
> As long as sun4i/sun6i SPI drivers have overriden the default
> "wait for completion" procedure then we need to properly
> handle -ETIMEDOUT error from transfer_one().

Why is this connected to those drivers specifically?


signature.asc
Description: PGP signature


Re: [PATCH 14/15] ARM: pxa: change SSP devices allocation

2018-04-03 Thread Arnd Bergmann
On Tue, Apr 3, 2018 at 5:32 PM, Robert Jarzmik  wrote:
> Arnd Bergmann  writes:
>
> chop chop ... removed several mail recipients to leave only the ASoC / PXA
> subset ...
>
>> On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik  
>> wrote:
>>
>>>
>>> +static struct pxa_ssp_info pxa_ssp_infos[] = {
>>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>>> +};
>>
>> This part looks odd to me, you're adding an extra level of indirection to
>> do two stages of lookups in some form of platform data.
> That's unfortunately right.
>
>> Why can't you just always use "rx" and "tx" as the names here?
> Well I couldn't. I'll explain you why, and maybe you'll find a better 
> solution.
>
> That all is related to how ASoC and SSP interact.
> If I remember correctly, here is how it works :
>  - the DMA channel is requested in sound/arm/pxa2xx-pcm-lib.c:128
> return snd_dmaengine_pcm_open(
> substream, dma_request_slave_channel(rtd->platform->dev,
>The trick is that the device here is _not_ the SSP one, it's if memory 
> serves
>me well the pxa-pcm-audio one.
>
>As a consequence, the device cannot be used to differenciate which SSP
>exactly is providing the sound samples stream. This information is
>nevertheless required to choose the correct requestor line, which is a 
> 1-to-1
>match to the SSP port.
>
>The indirection in the channel name is used to choose the correct requestor
>line for a given SSP port providing the samples.
>
>It also must be underlined that this dma request serves both AC97 and SSP 
> as
>sample providers.

I'm still unable to follow through that code, but I understand now that
the device you pass to dma_request_slave_channel() is not the one
we'd like it to be here.

Where exactly does that call to dma_request_chan() happen? Is this
the one in dmaengine_pcm_new()? Could we perhaps put a
pointer to the SSP device into snd_dmaengine_dai_dma_data?

   Arnd


Re: [PATCH 14/15] ARM: pxa: change SSP devices allocation

2018-04-03 Thread Arnd Bergmann
On Tue, Apr 3, 2018 at 5:32 PM, Robert Jarzmik  wrote:
> Arnd Bergmann  writes:
>
> chop chop ... removed several mail recipients to leave only the ASoC / PXA
> subset ...
>
>> On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik  
>> wrote:
>>
>>>
>>> +static struct pxa_ssp_info pxa_ssp_infos[] = {
>>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>>> +};
>>
>> This part looks odd to me, you're adding an extra level of indirection to
>> do two stages of lookups in some form of platform data.
> That's unfortunately right.
>
>> Why can't you just always use "rx" and "tx" as the names here?
> Well I couldn't. I'll explain you why, and maybe you'll find a better 
> solution.
>
> That all is related to how ASoC and SSP interact.
> If I remember correctly, here is how it works :
>  - the DMA channel is requested in sound/arm/pxa2xx-pcm-lib.c:128
> return snd_dmaengine_pcm_open(
> substream, dma_request_slave_channel(rtd->platform->dev,
>The trick is that the device here is _not_ the SSP one, it's if memory 
> serves
>me well the pxa-pcm-audio one.
>
>As a consequence, the device cannot be used to differenciate which SSP
>exactly is providing the sound samples stream. This information is
>nevertheless required to choose the correct requestor line, which is a 
> 1-to-1
>match to the SSP port.
>
>The indirection in the channel name is used to choose the correct requestor
>line for a given SSP port providing the samples.
>
>It also must be underlined that this dma request serves both AC97 and SSP 
> as
>sample providers.

I'm still unable to follow through that code, but I understand now that
the device you pass to dma_request_slave_channel() is not the one
we'd like it to be here.

Where exactly does that call to dma_request_chan() happen? Is this
the one in dmaengine_pcm_new()? Could we perhaps put a
pointer to the SSP device into snd_dmaengine_dai_dma_data?

   Arnd


Re: call/normal switch was Re: omap4-droid4: voice call support was

2018-04-03 Thread Pavel Machek
Hi!

> > OK thanks for checking. So probably only n_gsm channel 1 is for normal
> > Qualcomm at commands, and then channel 2 and others are commands
> > implemented by Motorola on the mdm6600.
> > 
> > I guess we'd have to add support for reading and writing to
> > /dev/gsmtty2 at least as it looks like these cannot be accessed
> > via /dev/ttyUSB4. Or at least I have not figured out any other
> > way to access them.
> 
> Hmm or maybe there is some way to select where qmi to tunnels the
> AT commands to? Some kind of channel type paramenter like n_gsm
> has?
> 
> Anyways, for trying to figure out things for alsamixer, I tested
> that ngsm 2 "AT+EACC=3,0" is not related to cpcap audio register
> settings and the mic is enabled during the call with Pavel's patch
> with alsamixer "Mode" set to either "Call" or "Normal". Also speaker
> keeps working during the call toggling between "Call" and "Normal".
> "Voice" in alsamixer does also control the speaker volume during
> the call. And setting the second "Speaker" from "Voice" to "HiFi"
> mutes the speaker.

Take a look at the patch. Selecting "call" does something at hardware
level, selecting "normal" is a nop.

Sorry for confusion.

Yes, that patch needs more work.

Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Re: call/normal switch was Re: omap4-droid4: voice call support was

2018-04-03 Thread Pavel Machek
Hi!

> > OK thanks for checking. So probably only n_gsm channel 1 is for normal
> > Qualcomm at commands, and then channel 2 and others are commands
> > implemented by Motorola on the mdm6600.
> > 
> > I guess we'd have to add support for reading and writing to
> > /dev/gsmtty2 at least as it looks like these cannot be accessed
> > via /dev/ttyUSB4. Or at least I have not figured out any other
> > way to access them.
> 
> Hmm or maybe there is some way to select where qmi to tunnels the
> AT commands to? Some kind of channel type paramenter like n_gsm
> has?
> 
> Anyways, for trying to figure out things for alsamixer, I tested
> that ngsm 2 "AT+EACC=3,0" is not related to cpcap audio register
> settings and the mic is enabled during the call with Pavel's patch
> with alsamixer "Mode" set to either "Call" or "Normal". Also speaker
> keeps working during the call toggling between "Call" and "Normal".
> "Voice" in alsamixer does also control the speaker volume during
> the call. And setting the second "Speaker" from "Voice" to "HiFi"
> mutes the speaker.

Take a look at the patch. Selecting "call" does something at hardware
level, selecting "normal" is a nop.

Sorry for confusion.

Yes, that patch needs more work.

Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Re: [alsa-devel] [PATCH] ASoC: atmel_ssc_dai: fix spelling mistake: "Stoping" -> "Stopping"

2018-04-03 Thread Joe Perches
On Tue, 2018-04-03 at 15:45 +0200, Ladislav Michl wrote:
> On Fri, Mar 30, 2018 at 04:44:20PM +0100, Colin King wrote:
> > From: Colin Ian King 
> 
> Hello Colin,
> 
> > Trivial fix to spelling mistake in pr_debug message text
> 
> would you mind making this patch a bit less non-trivial and
> change pr_debug to dev_dbg dropping Atmel_ssc_dai prefix?

Presumably, then all the pr_ calls should be changed.
Something like:
---
 sound/soc/atmel/atmel_ssc_dai.c | 38 --
 1 file changed, 16 insertions(+), 22 deletions(-)

diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index a1e2c5682dcd..594228156b2d 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -291,11 +291,10 @@ static int atmel_ssc_startup(struct snd_pcm_substream 
*substream,
int dir, dir_mask;
int ret;
 
-   pr_debug("atmel_ssc_startup: SSC_SR=0x%x\n",
-   ssc_readl(ssc_p->ssc->regs, SR));
+   dev_dbg(dai->dev, "SSC_SR=0x%x\n", ssc_readl(ssc_p->ssc->regs, SR));
 
/* Enable PMC peripheral clock for this SSC */
-   pr_debug("atmel_ssc_dai: Starting clock\n");
+   dev_dbg(dai->dev, "Starting clock\n");
clk_enable(ssc_p->ssc->clk);
ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
 
@@ -385,7 +384,7 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream 
*substream,
spin_unlock_irq(_p->lock);
 
/* Shutdown the SSC clock. */
-   pr_debug("atmel_ssc_dai: Stopping clock\n");
+   dev_dbg(dai->dev, "Stopping clock\n");
clk_disable(ssc_p->ssc->clk);
 }
 
@@ -794,13 +793,12 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream 
*substream,
break;
 
default:
-   printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 
0x%x\n",
-   ssc_p->daifmt);
+   dev_warn(dai->dev, "unsupported DAI format 0x%x\n",
+ssc_p->daifmt);
return -EINVAL;
}
-   pr_debug("atmel_ssc_hw_params: "
-   "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
-   rcmr, rfmr, tcmr, tfmr);
+   dev_dbg(dai->dev, "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
+   rcmr, rfmr, tcmr, tfmr);
 
if (!ssc_p->initialized) {
if (!ssc_p->ssc->pdata->use_dma) {
@@ -818,9 +816,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream 
*substream,
ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
ssc_p->name, ssc_p);
if (ret < 0) {
-   printk(KERN_WARNING
-   "atmel_ssc_dai: request_irq failure\n");
-   pr_debug("Atmel_ssc_dai: Stoping clock\n");
+   dev_warn(dai->dev, "request_irq failure\n");
+   dev_dbg(dai->dev, "Stopping clock\n");
clk_disable(ssc_p->ssc->clk);
return ret;
}
@@ -839,7 +836,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream 
*substream,
ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
 
-   pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
+   dev_dbg(dai->dev, "SSC initialized\n");
return 0;
 }
 
@@ -862,9 +859,9 @@ static int atmel_ssc_prepare(struct snd_pcm_substream 
*substream,
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
-   pr_debug("%s enabled SSC_SR=0x%08x\n",
-   dir ? "receive" : "transmit",
-   ssc_readl(ssc_p->ssc->regs, SR));
+   dev_dbg(dai->dev, "%s enabled SSC_SR=0x%08x\n",
+   dir ? "receive" : "transmit",
+   ssc_readl(ssc_p->ssc->regs, SR));
return 0;
 }
 
@@ -1050,21 +1047,18 @@ static void asoc_ssc_exit(struct device *dev)
 int atmel_ssc_set_audio(int ssc_id)
 {
struct ssc_device *ssc;
-   int ret;
 
/* If we can grab the SSC briefly to parent the DAI device off it */
ssc = ssc_request(ssc_id);
if (IS_ERR(ssc)) {
pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
-   PTR_ERR(ssc));
+  PTR_ERR(ssc));
return PTR_ERR(ssc);
-   } else {
-   ssc_info[ssc_id].ssc = ssc;
}
 
-   ret = asoc_ssc_init(>pdev->dev);
+   ssc_info[ssc_id].ssc = ssc;
 
-   return ret;
+   return asoc_ssc_init(>pdev->dev);
 }
 EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
 


Re: [alsa-devel] [PATCH] ASoC: atmel_ssc_dai: fix spelling mistake: "Stoping" -> "Stopping"

2018-04-03 Thread Joe Perches
On Tue, 2018-04-03 at 15:45 +0200, Ladislav Michl wrote:
> On Fri, Mar 30, 2018 at 04:44:20PM +0100, Colin King wrote:
> > From: Colin Ian King 
> 
> Hello Colin,
> 
> > Trivial fix to spelling mistake in pr_debug message text
> 
> would you mind making this patch a bit less non-trivial and
> change pr_debug to dev_dbg dropping Atmel_ssc_dai prefix?

Presumably, then all the pr_ calls should be changed.
Something like:
---
 sound/soc/atmel/atmel_ssc_dai.c | 38 --
 1 file changed, 16 insertions(+), 22 deletions(-)

diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index a1e2c5682dcd..594228156b2d 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -291,11 +291,10 @@ static int atmel_ssc_startup(struct snd_pcm_substream 
*substream,
int dir, dir_mask;
int ret;
 
-   pr_debug("atmel_ssc_startup: SSC_SR=0x%x\n",
-   ssc_readl(ssc_p->ssc->regs, SR));
+   dev_dbg(dai->dev, "SSC_SR=0x%x\n", ssc_readl(ssc_p->ssc->regs, SR));
 
/* Enable PMC peripheral clock for this SSC */
-   pr_debug("atmel_ssc_dai: Starting clock\n");
+   dev_dbg(dai->dev, "Starting clock\n");
clk_enable(ssc_p->ssc->clk);
ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);
 
@@ -385,7 +384,7 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream 
*substream,
spin_unlock_irq(_p->lock);
 
/* Shutdown the SSC clock. */
-   pr_debug("atmel_ssc_dai: Stopping clock\n");
+   dev_dbg(dai->dev, "Stopping clock\n");
clk_disable(ssc_p->ssc->clk);
 }
 
@@ -794,13 +793,12 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream 
*substream,
break;
 
default:
-   printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 
0x%x\n",
-   ssc_p->daifmt);
+   dev_warn(dai->dev, "unsupported DAI format 0x%x\n",
+ssc_p->daifmt);
return -EINVAL;
}
-   pr_debug("atmel_ssc_hw_params: "
-   "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
-   rcmr, rfmr, tcmr, tfmr);
+   dev_dbg(dai->dev, "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
+   rcmr, rfmr, tcmr, tfmr);
 
if (!ssc_p->initialized) {
if (!ssc_p->ssc->pdata->use_dma) {
@@ -818,9 +816,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream 
*substream,
ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
ssc_p->name, ssc_p);
if (ret < 0) {
-   printk(KERN_WARNING
-   "atmel_ssc_dai: request_irq failure\n");
-   pr_debug("Atmel_ssc_dai: Stoping clock\n");
+   dev_warn(dai->dev, "request_irq failure\n");
+   dev_dbg(dai->dev, "Stopping clock\n");
clk_disable(ssc_p->ssc->clk);
return ret;
}
@@ -839,7 +836,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream 
*substream,
ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
 
-   pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
+   dev_dbg(dai->dev, "SSC initialized\n");
return 0;
 }
 
@@ -862,9 +859,9 @@ static int atmel_ssc_prepare(struct snd_pcm_substream 
*substream,
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
-   pr_debug("%s enabled SSC_SR=0x%08x\n",
-   dir ? "receive" : "transmit",
-   ssc_readl(ssc_p->ssc->regs, SR));
+   dev_dbg(dai->dev, "%s enabled SSC_SR=0x%08x\n",
+   dir ? "receive" : "transmit",
+   ssc_readl(ssc_p->ssc->regs, SR));
return 0;
 }
 
@@ -1050,21 +1047,18 @@ static void asoc_ssc_exit(struct device *dev)
 int atmel_ssc_set_audio(int ssc_id)
 {
struct ssc_device *ssc;
-   int ret;
 
/* If we can grab the SSC briefly to parent the DAI device off it */
ssc = ssc_request(ssc_id);
if (IS_ERR(ssc)) {
pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
-   PTR_ERR(ssc));
+  PTR_ERR(ssc));
return PTR_ERR(ssc);
-   } else {
-   ssc_info[ssc_id].ssc = ssc;
}
 
-   ret = asoc_ssc_init(>pdev->dev);
+   ssc_info[ssc_id].ssc = ssc;
 
-   return ret;
+   return asoc_ssc_init(>pdev->dev);
 }
 EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
 


Re: [PATCH v3 2/4] mfd: add Gateworks System Controller core driver

2018-04-03 Thread Tim Harvey
On Wed, Mar 28, 2018 at 8:14 AM, Tim Harvey  wrote:
> The Gateworks System Controller (GSC) is an I2C slave controller
> implemented with an MSP430 micro-controller whose firmware embeds the
> following features:
>  - I/O expander (16 GPIO's) using PCA955x protocol
>  - Real Time Clock using DS1672 protocol
>  - User EEPROM using AT24 protocol
>  - HWMON using custom protocol
>  - Interrupt controller with tamper detect, user pushbotton
>  - Watchdog controller capable of full board power-cycle
>  - Power Control capable of full board power-cycle
>
> see http://trac.gateworks.com/wiki/gsc for more details
>

> +
> +/*
> + * gsc_powerdown - API to use GSC to power down board for a specific time
> + *
> + * secs - number of seconds to remain powered off
> + */
> +static int gsc_powerdown(struct gsc_dev *gsc, unsigned long secs)
> +{
> +   int ret;
> +   unsigned char regs[4];
> +
> +   dev_info(>i2c->dev, "GSC powerdown for %ld seconds\n",
> +secs);
> +   regs[0] = secs & 0xff;
> +   regs[1] = (secs >> 8) & 0xff;
> +   regs[2] = (secs >> 16) & 0xff;
> +   regs[3] = (secs >> 24) & 0xff;
> +   ret = regmap_bulk_write(gsc->regmap, GSC_TIME_ADD, regs, 4);
> +
> +   return ret;
> +}

Any feedback on the 'powerdown' sysfs attribute that hooks to this
function? This allows the GSC to disable the board primary power
supply for 2^32 seconds and is often used to 'reset' the board
although it could also be used to put the board in a power down state
longer. I'm wondering if there is a more appropriate API for this in
the kernel that I don't know about.

I would also like to register a restart handler using this but I
believe that ARM restart handlers currently can not use I2C - is that
correct?

Regards,

Tim


Re: [PATCH v3 2/4] mfd: add Gateworks System Controller core driver

2018-04-03 Thread Tim Harvey
On Wed, Mar 28, 2018 at 8:14 AM, Tim Harvey  wrote:
> The Gateworks System Controller (GSC) is an I2C slave controller
> implemented with an MSP430 micro-controller whose firmware embeds the
> following features:
>  - I/O expander (16 GPIO's) using PCA955x protocol
>  - Real Time Clock using DS1672 protocol
>  - User EEPROM using AT24 protocol
>  - HWMON using custom protocol
>  - Interrupt controller with tamper detect, user pushbotton
>  - Watchdog controller capable of full board power-cycle
>  - Power Control capable of full board power-cycle
>
> see http://trac.gateworks.com/wiki/gsc for more details
>

> +
> +/*
> + * gsc_powerdown - API to use GSC to power down board for a specific time
> + *
> + * secs - number of seconds to remain powered off
> + */
> +static int gsc_powerdown(struct gsc_dev *gsc, unsigned long secs)
> +{
> +   int ret;
> +   unsigned char regs[4];
> +
> +   dev_info(>i2c->dev, "GSC powerdown for %ld seconds\n",
> +secs);
> +   regs[0] = secs & 0xff;
> +   regs[1] = (secs >> 8) & 0xff;
> +   regs[2] = (secs >> 16) & 0xff;
> +   regs[3] = (secs >> 24) & 0xff;
> +   ret = regmap_bulk_write(gsc->regmap, GSC_TIME_ADD, regs, 4);
> +
> +   return ret;
> +}

Any feedback on the 'powerdown' sysfs attribute that hooks to this
function? This allows the GSC to disable the board primary power
supply for 2^32 seconds and is often used to 'reset' the board
although it could also be used to put the board in a power down state
longer. I'm wondering if there is a more appropriate API for this in
the kernel that I don't know about.

I would also like to register a restart handler using this but I
believe that ARM restart handlers currently can not use I2C - is that
correct?

Regards,

Tim


[PATCH v3 2/6] spi: sun6i: handle chip select polarity flag

2018-04-03 Thread Sergey Suloev
The chip select polarity flag is declared as supported
but is not handled in the code.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 88ad45e..78acc1f 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -193,6 +193,12 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
else
reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
 
+   /* Handle chip select "reverse" polarity */
+   if (spi->mode & SPI_CS_HIGH)
+   reg &= ~SUN6I_TFR_CTL_SPOL;
+   else
+   reg |= SUN6I_TFR_CTL_SPOL;
+
/* We want to control the chip select manually */
reg |= SUN6I_TFR_CTL_CS_MANUAL;
 
-- 
2.16.2



[PATCH v3 2/6] spi: sun6i: handle chip select polarity flag

2018-04-03 Thread Sergey Suloev
The chip select polarity flag is declared as supported
but is not handled in the code.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 88ad45e..78acc1f 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -193,6 +193,12 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
else
reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
 
+   /* Handle chip select "reverse" polarity */
+   if (spi->mode & SPI_CS_HIGH)
+   reg &= ~SUN6I_TFR_CTL_SPOL;
+   else
+   reg |= SUN6I_TFR_CTL_SPOL;
+
/* We want to control the chip select manually */
reg |= SUN6I_TFR_CTL_CS_MANUAL;
 
-- 
2.16.2



[PATCH v3 1/6] spi: sun6i: coding style/readability improvements

2018-04-03 Thread Sergey Suloev
Minor changes to fulfill the coding style and improve
the readability of the code.

Changes in v2:
1) Fixed issue with misplacing a piece of code that requires access
to the transfer structure into sun6i_spi_prepare_message() function
where the transfer structure is not available.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 97 +
 1 file changed, 58 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 8533f4e..88ad45e 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -88,8 +88,12 @@
 #define SUN6I_TXDATA_REG   0x200
 #define SUN6I_RXDATA_REG   0x300
 
+#define SUN6I_SPI_MODE_BITS(SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | 
SPI_LSB_FIRST)
+
+#define SUN6I_SPI_MAX_SPEED_HZ 1
+#define SUN6I_SPI_MIN_SPEED_HZ 3000
+
 struct sun6i_spi {
-   struct spi_master   *master;
void __iomem*base_addr;
struct clk  *hclk;
struct clk  *mclk;
@@ -189,6 +193,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
else
reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
 
+   /* We want to control the chip select manually */
+   reg |= SUN6I_TFR_CTL_CS_MANUAL;
+
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
 }
 
@@ -197,6 +204,39 @@ static size_t sun6i_spi_max_transfer_size(struct 
spi_device *spi)
return SUN6I_MAX_XFER_SIZE - 1;
 }
 
+static int sun6i_spi_prepare_message(struct spi_master *master,
+struct spi_message *msg)
+{
+   struct spi_device *spi = msg->spi;
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
+   u32 reg;
+
+   /*
+* Setup the transfer control register: Chip Select,
+* polarities, etc.
+*/
+   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+
+   if (spi->mode & SPI_CPOL)
+   reg |= SUN6I_TFR_CTL_CPOL;
+   else
+   reg &= ~SUN6I_TFR_CTL_CPOL;
+
+   if (spi->mode & SPI_CPHA)
+   reg |= SUN6I_TFR_CTL_CPHA;
+   else
+   reg &= ~SUN6I_TFR_CTL_CPHA;
+
+   if (spi->mode & SPI_LSB_FIRST)
+   reg |= SUN6I_TFR_CTL_FBS;
+   else
+   reg &= ~SUN6I_TFR_CTL_FBS;
+
+   sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+
+   return 0;
+}
+
 static int sun6i_spi_transfer_one(struct spi_master *master,
  struct spi_device *spi,
  struct spi_transfer *tfr)
@@ -235,27 +275,8 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
(trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
(trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS));
 
-   /*
-* Setup the transfer control register: Chip Select,
-* polarities, etc.
-*/
-   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
-
-   if (spi->mode & SPI_CPOL)
-   reg |= SUN6I_TFR_CTL_CPOL;
-   else
-   reg &= ~SUN6I_TFR_CTL_CPOL;
-
-   if (spi->mode & SPI_CPHA)
-   reg |= SUN6I_TFR_CTL_CPHA;
-   else
-   reg &= ~SUN6I_TFR_CTL_CPHA;
-
-   if (spi->mode & SPI_LSB_FIRST)
-   reg |= SUN6I_TFR_CTL_FBS;
-   else
-   reg &= ~SUN6I_TFR_CTL_FBS;
 
+   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
/*
 * If it's a TX only transfer, we don't want to fill the RX
 * FIFO with bogus data
@@ -265,11 +286,9 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
else
reg |= SUN6I_TFR_CTL_DHB;
 
-   /* We want to control the chip select manually */
-   reg |= SUN6I_TFR_CTL_CS_MANUAL;
-
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
 
+
/* Ensure that we have a parent clock fast enough */
mclk_rate = clk_get_rate(sspi->mclk);
if (mclk_rate < (2 * tfr->speed_hz)) {
@@ -442,12 +461,24 @@ static int sun6i_spi_probe(struct platform_device *pdev)
struct resource *res;
int ret = 0, irq;
 
-   master = spi_alloc_master(>dev, sizeof(struct sun6i_spi));
+   master = spi_alloc_master(>dev, sizeof(*sspi));
if (!master) {
dev_err(>dev, "Unable to allocate SPI Master\n");
return -ENOMEM;
}
 
+   master->max_speed_hz = SUN6I_SPI_MAX_SPEED_HZ;
+   master->min_speed_hz = SUN6I_SPI_MIN_SPEED_HZ;
+   master->num_chipselect = 4;
+   master->mode_bits = SUN6I_SPI_MODE_BITS;
+   master->bits_per_word_mask = SPI_BPW_MASK(8);
+   master->set_cs = sun6i_spi_set_cs;
+   master->prepare_message = sun6i_spi_prepare_message;
+   master->transfer_one = sun6i_spi_transfer_one;
+   master->max_transfer_size = sun6i_spi_max_transfer_size;
+   master->dev.of_node = 

[PATCH v3 1/6] spi: sun6i: coding style/readability improvements

2018-04-03 Thread Sergey Suloev
Minor changes to fulfill the coding style and improve
the readability of the code.

Changes in v2:
1) Fixed issue with misplacing a piece of code that requires access
to the transfer structure into sun6i_spi_prepare_message() function
where the transfer structure is not available.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 97 +
 1 file changed, 58 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 8533f4e..88ad45e 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -88,8 +88,12 @@
 #define SUN6I_TXDATA_REG   0x200
 #define SUN6I_RXDATA_REG   0x300
 
+#define SUN6I_SPI_MODE_BITS(SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | 
SPI_LSB_FIRST)
+
+#define SUN6I_SPI_MAX_SPEED_HZ 1
+#define SUN6I_SPI_MIN_SPEED_HZ 3000
+
 struct sun6i_spi {
-   struct spi_master   *master;
void __iomem*base_addr;
struct clk  *hclk;
struct clk  *mclk;
@@ -189,6 +193,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
else
reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
 
+   /* We want to control the chip select manually */
+   reg |= SUN6I_TFR_CTL_CS_MANUAL;
+
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
 }
 
@@ -197,6 +204,39 @@ static size_t sun6i_spi_max_transfer_size(struct 
spi_device *spi)
return SUN6I_MAX_XFER_SIZE - 1;
 }
 
+static int sun6i_spi_prepare_message(struct spi_master *master,
+struct spi_message *msg)
+{
+   struct spi_device *spi = msg->spi;
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
+   u32 reg;
+
+   /*
+* Setup the transfer control register: Chip Select,
+* polarities, etc.
+*/
+   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+
+   if (spi->mode & SPI_CPOL)
+   reg |= SUN6I_TFR_CTL_CPOL;
+   else
+   reg &= ~SUN6I_TFR_CTL_CPOL;
+
+   if (spi->mode & SPI_CPHA)
+   reg |= SUN6I_TFR_CTL_CPHA;
+   else
+   reg &= ~SUN6I_TFR_CTL_CPHA;
+
+   if (spi->mode & SPI_LSB_FIRST)
+   reg |= SUN6I_TFR_CTL_FBS;
+   else
+   reg &= ~SUN6I_TFR_CTL_FBS;
+
+   sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+
+   return 0;
+}
+
 static int sun6i_spi_transfer_one(struct spi_master *master,
  struct spi_device *spi,
  struct spi_transfer *tfr)
@@ -235,27 +275,8 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
(trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
(trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS));
 
-   /*
-* Setup the transfer control register: Chip Select,
-* polarities, etc.
-*/
-   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
-
-   if (spi->mode & SPI_CPOL)
-   reg |= SUN6I_TFR_CTL_CPOL;
-   else
-   reg &= ~SUN6I_TFR_CTL_CPOL;
-
-   if (spi->mode & SPI_CPHA)
-   reg |= SUN6I_TFR_CTL_CPHA;
-   else
-   reg &= ~SUN6I_TFR_CTL_CPHA;
-
-   if (spi->mode & SPI_LSB_FIRST)
-   reg |= SUN6I_TFR_CTL_FBS;
-   else
-   reg &= ~SUN6I_TFR_CTL_FBS;
 
+   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
/*
 * If it's a TX only transfer, we don't want to fill the RX
 * FIFO with bogus data
@@ -265,11 +286,9 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
else
reg |= SUN6I_TFR_CTL_DHB;
 
-   /* We want to control the chip select manually */
-   reg |= SUN6I_TFR_CTL_CS_MANUAL;
-
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
 
+
/* Ensure that we have a parent clock fast enough */
mclk_rate = clk_get_rate(sspi->mclk);
if (mclk_rate < (2 * tfr->speed_hz)) {
@@ -442,12 +461,24 @@ static int sun6i_spi_probe(struct platform_device *pdev)
struct resource *res;
int ret = 0, irq;
 
-   master = spi_alloc_master(>dev, sizeof(struct sun6i_spi));
+   master = spi_alloc_master(>dev, sizeof(*sspi));
if (!master) {
dev_err(>dev, "Unable to allocate SPI Master\n");
return -ENOMEM;
}
 
+   master->max_speed_hz = SUN6I_SPI_MAX_SPEED_HZ;
+   master->min_speed_hz = SUN6I_SPI_MIN_SPEED_HZ;
+   master->num_chipselect = 4;
+   master->mode_bits = SUN6I_SPI_MODE_BITS;
+   master->bits_per_word_mask = SPI_BPW_MASK(8);
+   master->set_cs = sun6i_spi_set_cs;
+   master->prepare_message = sun6i_spi_prepare_message;
+   master->transfer_one = sun6i_spi_transfer_one;
+   master->max_transfer_size = sun6i_spi_max_transfer_size;
+   master->dev.of_node = pdev->dev.of_node;
+   

[PATCH v3 4/6] spi: sun6i: use completion provided by SPI core

2018-04-03 Thread Sergey Suloev
As long as the completion is already provided by the SPI core
then there is no need to waste extra-memory on this.
Also a waiting function was added to avoid code duplication.

Changes in v2:
1) Fixed issue with passing an invalid argument into devm_request_irq()
function.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 52 -
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index c09ad10..0912404 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -99,8 +99,6 @@ struct sun6i_spi {
struct clk  *mclk;
struct reset_control*rstc;
 
-   struct completion   done;
-
const u8*tx_buf;
u8  *rx_buf;
int len;
@@ -246,6 +244,30 @@ static int sun6i_spi_prepare_message(struct spi_master 
*master,
return 0;
 }
 
+static int sun6i_spi_wait_for_transfer(struct spi_device *spi,
+  struct spi_transfer *tfr)
+{
+   struct spi_master *master = spi->master;
+   unsigned int start, end, tx_time;
+   unsigned int timeout;
+
+   /* smart wait for completion */
+   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+   start = jiffies;
+   timeout = wait_for_completion_timeout(>xfer_completion,
+ msecs_to_jiffies(tx_time));
+   end = jiffies;
+   if (!timeout) {
+   dev_warn(>dev,
+"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+dev_name(>dev), tfr->len, tfr->speed_hz,
+jiffies_to_msecs(end - start), tx_time);
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
+
 static int sun6i_spi_transfer_one(struct spi_master *master,
  struct spi_device *spi,
  struct spi_transfer *tfr)
@@ -267,7 +289,6 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
if (tfr->len > sspi->fifo_depth)
return -EMSGSIZE;
 
-   reinit_completion(>done);
sspi->tx_buf = tfr->tx_buf;
sspi->rx_buf = tfr->rx_buf;
sspi->len = tfr->len;
@@ -358,21 +379,9 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
 
-   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
-   start = jiffies;
-   timeout = wait_for_completion_timeout(>done,
- msecs_to_jiffies(tx_time));
-   end = jiffies;
-   if (!timeout) {
-   dev_warn(>dev,
-"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
-dev_name(>dev), tfr->len, tfr->speed_hz,
-jiffies_to_msecs(end - start), tx_time);
-   ret = -ETIMEDOUT;
-   goto out;
-   }
+   /* Wait for completion */
+   ret = sun6i_spi_wait_for_transfer(spi, tfr);
 
-out:
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
 
return ret;
@@ -380,7 +389,8 @@ out:
 
 static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
 {
-   struct sun6i_spi *sspi = dev_id;
+   struct spi_master *master = dev_id;
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
u32 status;
 
status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
@@ -389,7 +399,7 @@ static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
if (status & SUN6I_INT_CTL_TC) {
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
-   complete(>done);
+   spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
@@ -496,7 +506,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
}
 
ret = devm_request_irq(>dev, irq, sun6i_spi_handler,
-  0, dev_name(>dev), sspi);
+  0, dev_name(>dev), master);
if (ret) {
dev_err(>dev, "Cannot request IRQ\n");
goto err_free_master;
@@ -518,8 +528,6 @@ static int sun6i_spi_probe(struct platform_device *pdev)
goto err_free_master;
}
 
-   init_completion(>done);
-
sspi->rstc = devm_reset_control_get_exclusive(>dev, NULL);
if (IS_ERR(sspi->rstc)) {
dev_err(>dev, "Couldn't get reset controller\n");
-- 
2.16.2



[PATCH v3 4/6] spi: sun6i: use completion provided by SPI core

2018-04-03 Thread Sergey Suloev
As long as the completion is already provided by the SPI core
then there is no need to waste extra-memory on this.
Also a waiting function was added to avoid code duplication.

Changes in v2:
1) Fixed issue with passing an invalid argument into devm_request_irq()
function.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 52 -
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index c09ad10..0912404 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -99,8 +99,6 @@ struct sun6i_spi {
struct clk  *mclk;
struct reset_control*rstc;
 
-   struct completion   done;
-
const u8*tx_buf;
u8  *rx_buf;
int len;
@@ -246,6 +244,30 @@ static int sun6i_spi_prepare_message(struct spi_master 
*master,
return 0;
 }
 
+static int sun6i_spi_wait_for_transfer(struct spi_device *spi,
+  struct spi_transfer *tfr)
+{
+   struct spi_master *master = spi->master;
+   unsigned int start, end, tx_time;
+   unsigned int timeout;
+
+   /* smart wait for completion */
+   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+   start = jiffies;
+   timeout = wait_for_completion_timeout(>xfer_completion,
+ msecs_to_jiffies(tx_time));
+   end = jiffies;
+   if (!timeout) {
+   dev_warn(>dev,
+"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+dev_name(>dev), tfr->len, tfr->speed_hz,
+jiffies_to_msecs(end - start), tx_time);
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
+
 static int sun6i_spi_transfer_one(struct spi_master *master,
  struct spi_device *spi,
  struct spi_transfer *tfr)
@@ -267,7 +289,6 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
if (tfr->len > sspi->fifo_depth)
return -EMSGSIZE;
 
-   reinit_completion(>done);
sspi->tx_buf = tfr->tx_buf;
sspi->rx_buf = tfr->rx_buf;
sspi->len = tfr->len;
@@ -358,21 +379,9 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
 
-   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
-   start = jiffies;
-   timeout = wait_for_completion_timeout(>done,
- msecs_to_jiffies(tx_time));
-   end = jiffies;
-   if (!timeout) {
-   dev_warn(>dev,
-"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
-dev_name(>dev), tfr->len, tfr->speed_hz,
-jiffies_to_msecs(end - start), tx_time);
-   ret = -ETIMEDOUT;
-   goto out;
-   }
+   /* Wait for completion */
+   ret = sun6i_spi_wait_for_transfer(spi, tfr);
 
-out:
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
 
return ret;
@@ -380,7 +389,8 @@ out:
 
 static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
 {
-   struct sun6i_spi *sspi = dev_id;
+   struct spi_master *master = dev_id;
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
u32 status;
 
status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
@@ -389,7 +399,7 @@ static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
if (status & SUN6I_INT_CTL_TC) {
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
-   complete(>done);
+   spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
@@ -496,7 +506,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
}
 
ret = devm_request_irq(>dev, irq, sun6i_spi_handler,
-  0, dev_name(>dev), sspi);
+  0, dev_name(>dev), master);
if (ret) {
dev_err(>dev, "Cannot request IRQ\n");
goto err_free_master;
@@ -518,8 +528,6 @@ static int sun6i_spi_probe(struct platform_device *pdev)
goto err_free_master;
}
 
-   init_completion(>done);
-
sspi->rstc = devm_reset_control_get_exclusive(>dev, NULL);
if (IS_ERR(sspi->rstc)) {
dev_err(>dev, "Couldn't get reset controller\n");
-- 
2.16.2



[PATCH v3 0/6] spi: Add support for DMA transfers in sun6i SPI driver

2018-04-03 Thread Sergey Suloev
The following patchset provides corrections for PIO-mode
and support for DMA transfers in sun6i SPI driver.

Changes in v2:
1) Fixed issue with misplacing a piece of code that requires access
to the transfer structure into sun6i_spi_prepare_message() function
where the transfer structure is not available.

2) Fixed issue with passing an invalid argument into devm_request_irq()
function.

Changes in v3:
1) Restored processing of 3/4 FIFO full interrupt.

2) Debug log enhancements.

Sergey Suloev (6):
  spi: sun6i: coding style/readability improvements
  spi: sun6i: handle chip select polarity flag
  spi: sun6i: restrict transfer length in PIO-mode
  spi: sun6i: use completion provided by SPI core
  spi: sun6i: introduce register set/unset helpers
  spi: sun6i: add DMA transfers support

 drivers/spi/spi-sun6i.c | 526 
 1 file changed, 402 insertions(+), 124 deletions(-)

-- 
2.16.2



[PATCH v3 0/6] spi: Add support for DMA transfers in sun6i SPI driver

2018-04-03 Thread Sergey Suloev
The following patchset provides corrections for PIO-mode
and support for DMA transfers in sun6i SPI driver.

Changes in v2:
1) Fixed issue with misplacing a piece of code that requires access
to the transfer structure into sun6i_spi_prepare_message() function
where the transfer structure is not available.

2) Fixed issue with passing an invalid argument into devm_request_irq()
function.

Changes in v3:
1) Restored processing of 3/4 FIFO full interrupt.

2) Debug log enhancements.

Sergey Suloev (6):
  spi: sun6i: coding style/readability improvements
  spi: sun6i: handle chip select polarity flag
  spi: sun6i: restrict transfer length in PIO-mode
  spi: sun6i: use completion provided by SPI core
  spi: sun6i: introduce register set/unset helpers
  spi: sun6i: add DMA transfers support

 drivers/spi/spi-sun6i.c | 526 
 1 file changed, 402 insertions(+), 124 deletions(-)

-- 
2.16.2



[PATCH v3 3/6] spi: sun6i: restrict transfer length in PIO-mode

2018-04-03 Thread Sergey Suloev
There is no need to handle 3/4 empty interrupt as the maximum
supported transfer length in PIO mode is equal to FIFO depth,
i.e. 128 bytes for sun6i and 64 bytes for sun8i SoCs.

Changes in v3:
1) Restored processing of 3/4 FIFO full interrupt.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 41 +
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 78acc1f..c09ad10 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -207,7 +207,10 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
 {
-   return SUN6I_MAX_XFER_SIZE - 1;
+   struct spi_master *master = spi->master;
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+   return sspi->fifo_depth;
 }
 
 static int sun6i_spi_prepare_message(struct spi_master *master,
@@ -255,8 +258,14 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
int ret = 0;
u32 reg;
 
-   if (tfr->len > SUN6I_MAX_XFER_SIZE)
-   return -EINVAL;
+   /* A zero length transfer never finishes if programmed
+  in the hardware */
+   if (!tfr->len)
+   return 0;
+
+   /* Don't support transfer larger than the FIFO */
+   if (tfr->len > sspi->fifo_depth)
+   return -EMSGSIZE;
 
reinit_completion(>done);
sspi->tx_buf = tfr->tx_buf;
@@ -278,8 +287,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 */
trig_level = sspi->fifo_depth / 4 * 3;
sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
-   (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
-   (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS));
+   (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS));
 
 
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
@@ -343,11 +351,8 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
sun6i_spi_fill_fifo(sspi, sspi->fifo_depth);
 
/* Enable the interrupts */
-   sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TC |
 SUN6I_INT_CTL_RF_RDY);
-   if (tx_len > sspi->fifo_depth)
-   sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
 
/* Start the transfer */
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
@@ -376,7 +381,9 @@ out:
 static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
 {
struct sun6i_spi *sspi = dev_id;
-   u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
+   u32 status;
+
+   status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
 
/* Transfer complete */
if (status & SUN6I_INT_CTL_TC) {
@@ -388,26 +395,12 @@ static irqreturn_t sun6i_spi_handler(int irq, void 
*dev_id)
 
/* Receive FIFO 3/4 full */
if (status & SUN6I_INT_CTL_RF_RDY) {
-   sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+   sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
/* Only clear the interrupt _after_ draining the FIFO */
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_RF_RDY);
return IRQ_HANDLED;
}
 
-   /* Transmit FIFO 3/4 empty */
-   if (status & SUN6I_INT_CTL_TF_ERQ) {
-   sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
-
-   if (!sspi->len)
-   /* nothing left to transmit */
-   sun6i_spi_disable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
-
-   /* Only clear the interrupt _after_ re-seeding the FIFO */
-   sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TF_ERQ);
-
-   return IRQ_HANDLED;
-   }
-
return IRQ_NONE;
 }
 
-- 
2.16.2



[PATCH v3 3/6] spi: sun6i: restrict transfer length in PIO-mode

2018-04-03 Thread Sergey Suloev
There is no need to handle 3/4 empty interrupt as the maximum
supported transfer length in PIO mode is equal to FIFO depth,
i.e. 128 bytes for sun6i and 64 bytes for sun8i SoCs.

Changes in v3:
1) Restored processing of 3/4 FIFO full interrupt.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 41 +
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 78acc1f..c09ad10 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -207,7 +207,10 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
 {
-   return SUN6I_MAX_XFER_SIZE - 1;
+   struct spi_master *master = spi->master;
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+   return sspi->fifo_depth;
 }
 
 static int sun6i_spi_prepare_message(struct spi_master *master,
@@ -255,8 +258,14 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
int ret = 0;
u32 reg;
 
-   if (tfr->len > SUN6I_MAX_XFER_SIZE)
-   return -EINVAL;
+   /* A zero length transfer never finishes if programmed
+  in the hardware */
+   if (!tfr->len)
+   return 0;
+
+   /* Don't support transfer larger than the FIFO */
+   if (tfr->len > sspi->fifo_depth)
+   return -EMSGSIZE;
 
reinit_completion(>done);
sspi->tx_buf = tfr->tx_buf;
@@ -278,8 +287,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 */
trig_level = sspi->fifo_depth / 4 * 3;
sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
-   (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
-   (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS));
+   (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS));
 
 
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
@@ -343,11 +351,8 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
sun6i_spi_fill_fifo(sspi, sspi->fifo_depth);
 
/* Enable the interrupts */
-   sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TC |
 SUN6I_INT_CTL_RF_RDY);
-   if (tx_len > sspi->fifo_depth)
-   sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
 
/* Start the transfer */
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
@@ -376,7 +381,9 @@ out:
 static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
 {
struct sun6i_spi *sspi = dev_id;
-   u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
+   u32 status;
+
+   status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
 
/* Transfer complete */
if (status & SUN6I_INT_CTL_TC) {
@@ -388,26 +395,12 @@ static irqreturn_t sun6i_spi_handler(int irq, void 
*dev_id)
 
/* Receive FIFO 3/4 full */
if (status & SUN6I_INT_CTL_RF_RDY) {
-   sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+   sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
/* Only clear the interrupt _after_ draining the FIFO */
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_RF_RDY);
return IRQ_HANDLED;
}
 
-   /* Transmit FIFO 3/4 empty */
-   if (status & SUN6I_INT_CTL_TF_ERQ) {
-   sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
-
-   if (!sspi->len)
-   /* nothing left to transmit */
-   sun6i_spi_disable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
-
-   /* Only clear the interrupt _after_ re-seeding the FIFO */
-   sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TF_ERQ);
-
-   return IRQ_HANDLED;
-   }
-
return IRQ_NONE;
 }
 
-- 
2.16.2



[PATCH] rapidio: use a reference count for struct mport_dma_req

2018-04-03 Thread Ioan Nicu
Once the dma request is passed to the DMA engine, the DMA
subsystem would hold a pointer to this structure and could
call the completion callback after do_dma_request() has
timed out.

The current code deals with this by putting timed out SYNC
requests to a pending list and freeing them later, when the
mport cdev device is released. But this still does not
guarantee that the DMA subsystem is really done with those
transfers, so in theory dma_xfer_callback/dma_req_free
could be called after mport_cdev_release_dma and could
potentially access already freed memory.

This patch simplifies the current handling by using a kref
in the mport dma request structure, so that it gets freed
only when nobody uses it anymore.

This also simplifies the code a bit, as FAF transfers are
now handled in the same way as SYNC and ASYNC transfers.
There is no need anymore for the pending list and for the
dma workqueue which was used in case of FAF transfers, so
we remove them both.

Signed-off-by: Ioan Nicu 
---
 drivers/rapidio/devices/rio_mport_cdev.c | 122 +--
 1 file changed, 18 insertions(+), 104 deletions(-)

diff --git a/drivers/rapidio/devices/rio_mport_cdev.c 
b/drivers/rapidio/devices/rio_mport_cdev.c
index cfb54e01d758..9d27016c899e 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -212,7 +212,6 @@ struct mport_cdev_priv {
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
struct dma_chan *dmach;
struct list_headasync_list;
-   struct list_headpend_list;
spinlock_t  req_lock;
struct mutexdma_lock;
struct kref dma_ref;
@@ -258,8 +257,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mport_cdev_wait);
 static struct class *dev_class;
 static dev_t dev_number;
 
-static struct workqueue_struct *dma_wq;
-
 static void mport_release_mapping(struct kref *ref);
 
 static int rio_mport_maint_rd(struct mport_cdev_priv *priv, void __user *arg,
@@ -539,6 +536,7 @@ static int maint_comptag_set(struct mport_cdev_priv *priv, 
void __user *arg)
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 
 struct mport_dma_req {
+   struct kref refcount;
struct list_head node;
struct file *filp;
struct mport_cdev_priv *priv;
@@ -554,11 +552,6 @@ struct mport_dma_req {
struct completion req_comp;
 };
 
-struct mport_faf_work {
-   struct work_struct work;
-   struct mport_dma_req *req;
-};
-
 static void mport_release_def_dma(struct kref *dma_ref)
 {
struct mport_dev *md =
@@ -578,8 +571,10 @@ static void mport_release_dma(struct kref *dma_ref)
complete(>comp);
 }
 
-static void dma_req_free(struct mport_dma_req *req)
+static void dma_req_free(struct kref *ref)
 {
+   struct mport_dma_req *req = container_of(ref, struct mport_dma_req,
+   refcount);
struct mport_cdev_priv *priv = req->priv;
unsigned int i;
 
@@ -611,30 +606,7 @@ static void dma_xfer_callback(void *param)
req->status = dma_async_is_tx_complete(priv->dmach, req->cookie,
   NULL, NULL);
complete(>req_comp);
-}
-
-static void dma_faf_cleanup(struct work_struct *_work)
-{
-   struct mport_faf_work *work = container_of(_work,
-   struct mport_faf_work, work);
-   struct mport_dma_req *req = work->req;
-
-   dma_req_free(req);
-   kfree(work);
-}
-
-static void dma_faf_callback(void *param)
-{
-   struct mport_dma_req *req = (struct mport_dma_req *)param;
-   struct mport_faf_work *work;
-
-   work = kmalloc(sizeof(*work), GFP_ATOMIC);
-   if (!work)
-   return;
-
-   INIT_WORK(>work, dma_faf_cleanup);
-   work->req = req;
-   queue_work(dma_wq, >work);
+   kref_put(>refcount, dma_req_free);
 }
 
 /*
@@ -765,16 +737,14 @@ static int do_dma_request(struct mport_dma_req *req,
goto err_out;
}
 
-   if (sync == RIO_TRANSFER_FAF)
-   tx->callback = dma_faf_callback;
-   else
-   tx->callback = dma_xfer_callback;
+   tx->callback = dma_xfer_callback;
tx->callback_param = req;
 
req->dmach = chan;
req->sync = sync;
req->status = DMA_IN_PROGRESS;
init_completion(>req_comp);
+   kref_get(>refcount);
 
cookie = dmaengine_submit(tx);
req->cookie = cookie;
@@ -785,6 +755,7 @@ static int do_dma_request(struct mport_dma_req *req,
if (dma_submit_error(cookie)) {
rmcd_error("submit err=%d (addr:0x%llx len:0x%llx)",
   cookie, xfer->rio_addr, xfer->length);
+   kref_put(>refcount, dma_req_free);
ret = -EIO;
goto err_out;
}
@@ -860,6 +831,8 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
if (!req)
return -ENOMEM;
 
+   

[PATCH] rapidio: use a reference count for struct mport_dma_req

2018-04-03 Thread Ioan Nicu
Once the dma request is passed to the DMA engine, the DMA
subsystem would hold a pointer to this structure and could
call the completion callback after do_dma_request() has
timed out.

The current code deals with this by putting timed out SYNC
requests to a pending list and freeing them later, when the
mport cdev device is released. But this still does not
guarantee that the DMA subsystem is really done with those
transfers, so in theory dma_xfer_callback/dma_req_free
could be called after mport_cdev_release_dma and could
potentially access already freed memory.

This patch simplifies the current handling by using a kref
in the mport dma request structure, so that it gets freed
only when nobody uses it anymore.

This also simplifies the code a bit, as FAF transfers are
now handled in the same way as SYNC and ASYNC transfers.
There is no need anymore for the pending list and for the
dma workqueue which was used in case of FAF transfers, so
we remove them both.

Signed-off-by: Ioan Nicu 
---
 drivers/rapidio/devices/rio_mport_cdev.c | 122 +--
 1 file changed, 18 insertions(+), 104 deletions(-)

diff --git a/drivers/rapidio/devices/rio_mport_cdev.c 
b/drivers/rapidio/devices/rio_mport_cdev.c
index cfb54e01d758..9d27016c899e 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -212,7 +212,6 @@ struct mport_cdev_priv {
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
struct dma_chan *dmach;
struct list_headasync_list;
-   struct list_headpend_list;
spinlock_t  req_lock;
struct mutexdma_lock;
struct kref dma_ref;
@@ -258,8 +257,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mport_cdev_wait);
 static struct class *dev_class;
 static dev_t dev_number;
 
-static struct workqueue_struct *dma_wq;
-
 static void mport_release_mapping(struct kref *ref);
 
 static int rio_mport_maint_rd(struct mport_cdev_priv *priv, void __user *arg,
@@ -539,6 +536,7 @@ static int maint_comptag_set(struct mport_cdev_priv *priv, 
void __user *arg)
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 
 struct mport_dma_req {
+   struct kref refcount;
struct list_head node;
struct file *filp;
struct mport_cdev_priv *priv;
@@ -554,11 +552,6 @@ struct mport_dma_req {
struct completion req_comp;
 };
 
-struct mport_faf_work {
-   struct work_struct work;
-   struct mport_dma_req *req;
-};
-
 static void mport_release_def_dma(struct kref *dma_ref)
 {
struct mport_dev *md =
@@ -578,8 +571,10 @@ static void mport_release_dma(struct kref *dma_ref)
complete(>comp);
 }
 
-static void dma_req_free(struct mport_dma_req *req)
+static void dma_req_free(struct kref *ref)
 {
+   struct mport_dma_req *req = container_of(ref, struct mport_dma_req,
+   refcount);
struct mport_cdev_priv *priv = req->priv;
unsigned int i;
 
@@ -611,30 +606,7 @@ static void dma_xfer_callback(void *param)
req->status = dma_async_is_tx_complete(priv->dmach, req->cookie,
   NULL, NULL);
complete(>req_comp);
-}
-
-static void dma_faf_cleanup(struct work_struct *_work)
-{
-   struct mport_faf_work *work = container_of(_work,
-   struct mport_faf_work, work);
-   struct mport_dma_req *req = work->req;
-
-   dma_req_free(req);
-   kfree(work);
-}
-
-static void dma_faf_callback(void *param)
-{
-   struct mport_dma_req *req = (struct mport_dma_req *)param;
-   struct mport_faf_work *work;
-
-   work = kmalloc(sizeof(*work), GFP_ATOMIC);
-   if (!work)
-   return;
-
-   INIT_WORK(>work, dma_faf_cleanup);
-   work->req = req;
-   queue_work(dma_wq, >work);
+   kref_put(>refcount, dma_req_free);
 }
 
 /*
@@ -765,16 +737,14 @@ static int do_dma_request(struct mport_dma_req *req,
goto err_out;
}
 
-   if (sync == RIO_TRANSFER_FAF)
-   tx->callback = dma_faf_callback;
-   else
-   tx->callback = dma_xfer_callback;
+   tx->callback = dma_xfer_callback;
tx->callback_param = req;
 
req->dmach = chan;
req->sync = sync;
req->status = DMA_IN_PROGRESS;
init_completion(>req_comp);
+   kref_get(>refcount);
 
cookie = dmaengine_submit(tx);
req->cookie = cookie;
@@ -785,6 +755,7 @@ static int do_dma_request(struct mport_dma_req *req,
if (dma_submit_error(cookie)) {
rmcd_error("submit err=%d (addr:0x%llx len:0x%llx)",
   cookie, xfer->rio_addr, xfer->length);
+   kref_put(>refcount, dma_req_free);
ret = -EIO;
goto err_out;
}
@@ -860,6 +831,8 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
if (!req)
return -ENOMEM;
 
+   kref_init(>refcount);
+

[PATCH v3 5/6] spi: sun6i: introduce register set/unset helpers

2018-04-03 Thread Sergey Suloev
Two helper functions were added in order to set/unset
specified flags in registers.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 37 -
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 0912404..2fa9d6e 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -115,29 +115,29 @@ static inline void sun6i_spi_write(struct sun6i_spi 
*sspi, u32 reg, u32 value)
writel(value, sspi->base_addr + reg);
 }
 
-static inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi)
+static inline void sun6i_spi_set(struct sun6i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
-
-   reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+   u32 reg = sun6i_spi_read(sspi, addr);
 
-   return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
+   reg |= val;
+   sun6i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun6i_spi_enable_interrupt(struct sun6i_spi *sspi, u32 mask)
+static inline void sun6i_spi_unset(struct sun6i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
+   u32 reg = sun6i_spi_read(sspi, addr);
 
-   reg |= mask;
-   sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
+   reg &= ~val;
+   sun6i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun6i_spi_disable_interrupt(struct sun6i_spi *sspi, u32 
mask)
+static inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi)
 {
-   u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
+   u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
 
-   reg &= ~mask;
-   sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
+   reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+
+   return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
 }
 
 static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
@@ -310,18 +310,14 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
(trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS));
 
-
-   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
/*
 * If it's a TX only transfer, we don't want to fill the RX
 * FIFO with bogus data
 */
if (sspi->rx_buf)
-   reg &= ~SUN6I_TFR_CTL_DHB;
+   sun6i_spi_unset(sspi, SUN6I_TFR_CTL_REG, SUN6I_TFR_CTL_DHB);
else
-   reg |= SUN6I_TFR_CTL_DHB;
-
-   sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+   sun6i_spi_set(sspi, SUN6I_TFR_CTL_REG, SUN6I_TFR_CTL_DHB);
 
 
/* Ensure that we have a parent clock fast enough */
@@ -376,8 +372,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 SUN6I_INT_CTL_RF_RDY);
 
/* Start the transfer */
-   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
-   sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+   sun6i_spi_set(sspi, SUN6I_TFR_CTL_REG, SUN6I_TFR_CTL_XCH);
 
/* Wait for completion */
ret = sun6i_spi_wait_for_transfer(spi, tfr);
-- 
2.16.2



[PATCH v3 5/6] spi: sun6i: introduce register set/unset helpers

2018-04-03 Thread Sergey Suloev
Two helper functions were added in order to set/unset
specified flags in registers.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 37 -
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 0912404..2fa9d6e 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -115,29 +115,29 @@ static inline void sun6i_spi_write(struct sun6i_spi 
*sspi, u32 reg, u32 value)
writel(value, sspi->base_addr + reg);
 }
 
-static inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi)
+static inline void sun6i_spi_set(struct sun6i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
-
-   reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+   u32 reg = sun6i_spi_read(sspi, addr);
 
-   return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
+   reg |= val;
+   sun6i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun6i_spi_enable_interrupt(struct sun6i_spi *sspi, u32 mask)
+static inline void sun6i_spi_unset(struct sun6i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
+   u32 reg = sun6i_spi_read(sspi, addr);
 
-   reg |= mask;
-   sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
+   reg &= ~val;
+   sun6i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun6i_spi_disable_interrupt(struct sun6i_spi *sspi, u32 
mask)
+static inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi)
 {
-   u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
+   u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
 
-   reg &= ~mask;
-   sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
+   reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+
+   return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
 }
 
 static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
@@ -310,18 +310,14 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
(trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS));
 
-
-   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
/*
 * If it's a TX only transfer, we don't want to fill the RX
 * FIFO with bogus data
 */
if (sspi->rx_buf)
-   reg &= ~SUN6I_TFR_CTL_DHB;
+   sun6i_spi_unset(sspi, SUN6I_TFR_CTL_REG, SUN6I_TFR_CTL_DHB);
else
-   reg |= SUN6I_TFR_CTL_DHB;
-
-   sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+   sun6i_spi_set(sspi, SUN6I_TFR_CTL_REG, SUN6I_TFR_CTL_DHB);
 
 
/* Ensure that we have a parent clock fast enough */
@@ -376,8 +372,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 SUN6I_INT_CTL_RF_RDY);
 
/* Start the transfer */
-   reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
-   sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+   sun6i_spi_set(sspi, SUN6I_TFR_CTL_REG, SUN6I_TFR_CTL_XCH);
 
/* Wait for completion */
ret = sun6i_spi_wait_for_transfer(spi, tfr);
-- 
2.16.2



[PATCH v3 6/6] spi: sun6i: add DMA transfers support

2018-04-03 Thread Sergey Suloev
DMA transfers are now available for sun6i and sun8i SoCs.
The DMA mode is used automatically as soon as requested
transfer length is more than FIFO length.

Changes in v3:
1) Debug log enhancements.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 331 ++--
 1 file changed, 294 insertions(+), 37 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 2fa9d6e..7f41871 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -55,17 +57,20 @@
 
 #define SUN6I_FIFO_CTL_REG 0x18
 #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK  0xff
-#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS  0
+#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_POS   0
+#define SUN6I_FIFO_CTL_RF_DRQ_EN   BIT(8)
 #define SUN6I_FIFO_CTL_RF_RST  BIT(15)
 #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK  0xff
-#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS  16
+#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_POS   16
+#define SUN6I_FIFO_CTL_TF_DRQ_EN   BIT(24)
 #define SUN6I_FIFO_CTL_TF_RST  BIT(31)
+#define SUN6I_FIFO_CTL_DMA_DEDICATEBIT(9)|BIT(25)
 
 #define SUN6I_FIFO_STA_REG 0x1c
 #define SUN6I_FIFO_STA_RF_CNT_MASK 0x7f
-#define SUN6I_FIFO_STA_RF_CNT_BITS 0
+#define SUN6I_FIFO_STA_RF_CNT_POS  0
 #define SUN6I_FIFO_STA_TF_CNT_MASK 0x7f
-#define SUN6I_FIFO_STA_TF_CNT_BITS 16
+#define SUN6I_FIFO_STA_TF_CNT_POS  16
 
 #define SUN6I_CLK_CTL_REG  0x24
 #define SUN6I_CLK_CTL_CDR2_MASK0xff
@@ -135,7 +140,7 @@ static inline u32 sun6i_spi_get_tx_fifo_count(struct 
sun6i_spi *sspi)
 {
u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
 
-   reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+   reg >>= SUN6I_FIFO_STA_TF_CNT_POS;
 
return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
 }
@@ -148,7 +153,7 @@ static inline void sun6i_spi_drain_fifo(struct sun6i_spi 
*sspi, int len)
/* See how much data is available */
reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
-   cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
+   cnt = reg >> SUN6I_FIFO_STA_RF_CNT_POS;
 
if (len > cnt)
len = cnt;
@@ -177,6 +182,15 @@ static inline void sun6i_spi_fill_fifo(struct sun6i_spi 
*sspi, int len)
}
 }
 
+static bool sun6i_spi_can_dma(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+   return tfr->len > sspi->fifo_depth;
+}
+
 static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
 {
struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
@@ -208,6 +222,9 @@ static size_t sun6i_spi_max_transfer_size(struct spi_device 
*spi)
struct spi_master *master = spi->master;
struct sun6i_spi *sspi = spi_master_get_devdata(master);
 
+   if (master->can_dma)
+   return SUN6I_MAX_XFER_SIZE;
+
return sspi->fifo_depth;
 }
 
@@ -268,16 +285,187 @@ static int sun6i_spi_wait_for_transfer(struct spi_device 
*spi,
return 0;
 }
 
+static void sun6i_spi_dma_callback(void *param)
+{
+   struct spi_master *master = param;
+
+   dev_dbg(>dev, "DMA transfer complete\n");
+   spi_finalize_current_transfer(master);
+}
+
+static int sun6i_spi_dmap_prep_tx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_tx,
+   tfr->tx_sg.sgl, tfr->tx_sg.nents,
+   DMA_TO_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!chan_desc) {
+   dev_err(>dev,
+   "Couldn't prepare TX DMA slave\n");
+   return -EIO;
+   }
+
+   chan_desc->callback = sun6i_spi_dma_callback;
+   chan_desc->callback_param = master;
+
+   *cookie = dmaengine_submit(chan_desc);
+   dma_async_issue_pending(master->dma_tx);
+
+   return 0;
+}
+
+static int sun6i_spi_dmap_prep_rx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_rx,
+   tfr->rx_sg.sgl, tfr->rx_sg.nents,
+   DMA_FROM_DEVICE,
+   

[PATCH v3 6/6] spi: sun6i: add DMA transfers support

2018-04-03 Thread Sergey Suloev
DMA transfers are now available for sun6i and sun8i SoCs.
The DMA mode is used automatically as soon as requested
transfer length is more than FIFO length.

Changes in v3:
1) Debug log enhancements.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun6i.c | 331 ++--
 1 file changed, 294 insertions(+), 37 deletions(-)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 2fa9d6e..7f41871 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -55,17 +57,20 @@
 
 #define SUN6I_FIFO_CTL_REG 0x18
 #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK  0xff
-#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS  0
+#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_POS   0
+#define SUN6I_FIFO_CTL_RF_DRQ_EN   BIT(8)
 #define SUN6I_FIFO_CTL_RF_RST  BIT(15)
 #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK  0xff
-#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS  16
+#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_POS   16
+#define SUN6I_FIFO_CTL_TF_DRQ_EN   BIT(24)
 #define SUN6I_FIFO_CTL_TF_RST  BIT(31)
+#define SUN6I_FIFO_CTL_DMA_DEDICATEBIT(9)|BIT(25)
 
 #define SUN6I_FIFO_STA_REG 0x1c
 #define SUN6I_FIFO_STA_RF_CNT_MASK 0x7f
-#define SUN6I_FIFO_STA_RF_CNT_BITS 0
+#define SUN6I_FIFO_STA_RF_CNT_POS  0
 #define SUN6I_FIFO_STA_TF_CNT_MASK 0x7f
-#define SUN6I_FIFO_STA_TF_CNT_BITS 16
+#define SUN6I_FIFO_STA_TF_CNT_POS  16
 
 #define SUN6I_CLK_CTL_REG  0x24
 #define SUN6I_CLK_CTL_CDR2_MASK0xff
@@ -135,7 +140,7 @@ static inline u32 sun6i_spi_get_tx_fifo_count(struct 
sun6i_spi *sspi)
 {
u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
 
-   reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+   reg >>= SUN6I_FIFO_STA_TF_CNT_POS;
 
return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
 }
@@ -148,7 +153,7 @@ static inline void sun6i_spi_drain_fifo(struct sun6i_spi 
*sspi, int len)
/* See how much data is available */
reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
-   cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
+   cnt = reg >> SUN6I_FIFO_STA_RF_CNT_POS;
 
if (len > cnt)
len = cnt;
@@ -177,6 +182,15 @@ static inline void sun6i_spi_fill_fifo(struct sun6i_spi 
*sspi, int len)
}
 }
 
+static bool sun6i_spi_can_dma(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+   struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+   return tfr->len > sspi->fifo_depth;
+}
+
 static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
 {
struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
@@ -208,6 +222,9 @@ static size_t sun6i_spi_max_transfer_size(struct spi_device 
*spi)
struct spi_master *master = spi->master;
struct sun6i_spi *sspi = spi_master_get_devdata(master);
 
+   if (master->can_dma)
+   return SUN6I_MAX_XFER_SIZE;
+
return sspi->fifo_depth;
 }
 
@@ -268,16 +285,187 @@ static int sun6i_spi_wait_for_transfer(struct spi_device 
*spi,
return 0;
 }
 
+static void sun6i_spi_dma_callback(void *param)
+{
+   struct spi_master *master = param;
+
+   dev_dbg(>dev, "DMA transfer complete\n");
+   spi_finalize_current_transfer(master);
+}
+
+static int sun6i_spi_dmap_prep_tx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_tx,
+   tfr->tx_sg.sgl, tfr->tx_sg.nents,
+   DMA_TO_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!chan_desc) {
+   dev_err(>dev,
+   "Couldn't prepare TX DMA slave\n");
+   return -EIO;
+   }
+
+   chan_desc->callback = sun6i_spi_dma_callback;
+   chan_desc->callback_param = master;
+
+   *cookie = dmaengine_submit(chan_desc);
+   dma_async_issue_pending(master->dma_tx);
+
+   return 0;
+}
+
+static int sun6i_spi_dmap_prep_rx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_rx,
+   tfr->rx_sg.sgl, tfr->rx_sg.nents,
+   DMA_FROM_DEVICE,
+   DMA_PREP_INTERRUPT | 

Re: [PATCH v2] x86/xen/efi: Initialize UEFI secure boot state during dom0 boot

2018-04-03 Thread James Bottomley
On Tue, 2018-04-03 at 16:39 +0200, Daniel Kiper wrote:
> Initialize UEFI secure boot state during dom0 boot. Otherwise the
> kernel
> may not even know that it runs on secure boot enabled platform.
> 
> Signed-off-by: Daniel Kiper 
> ---
>  arch/x86/xen/efi.c|   57
> +
>  drivers/firmware/efi/libstub/secureboot.c |3 ++
>  2 files changed, 60 insertions(+)
> 
> diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
> index a18703b..1804b27 100644
> --- a/arch/x86/xen/efi.c
> +++ b/arch/x86/xen/efi.c
> @@ -115,6 +115,61 @@ static efi_system_table_t __init
> *xen_efi_probe(void)
>   return _systab_xen;
>  }
>  
> +/*
> + * Determine whether we're in secure boot mode.
> + *
> + * Please keep the logic in sync with
> + * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
> + */
> +static enum efi_secureboot_mode xen_efi_get_secureboot(void)
> +{
> + static efi_guid_t efi_variable_guid =
> EFI_GLOBAL_VARIABLE_GUID;
> + static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
> + efi_status_t status;
> + u8 moksbstate, secboot, setupmode;
> + unsigned long size;
> +
> + size = sizeof(secboot);
> + status = efi.get_variable(L"SecureBoot", _variable_guid,
> +   NULL, , );
> +
> + if (status == EFI_NOT_FOUND)
> + return efi_secureboot_mode_disabled;
> +
> + if (status != EFI_SUCCESS)
> + goto out_efi_err;
> +
> + size = sizeof(setupmode);
> + status = efi.get_variable(L"SetupMode", _variable_guid,
> +   NULL, , );
> +
> + if (status != EFI_SUCCESS)
> + goto out_efi_err;
> +
> + if (secboot == 0 || setupmode == 1)
> + return efi_secureboot_mode_disabled;
> +
> + /* See if a user has put the shim into insecure mode. */
> + size = sizeof(moksbstate);
> + status = efi.get_variable(L"MokSBStateRT", _guid,
> +   NULL, , );
> +
> + /* If it fails, we don't care why. Default to secure. */
> + if (status != EFI_SUCCESS)
> + goto secure_boot_enabled;
> +
> + if (moksbstate == 1)
> + return efi_secureboot_mode_disabled;
> +
> + secure_boot_enabled:
> + pr_info("UEFI Secure Boot is enabled.\n");
> + return efi_secureboot_mode_enabled;
> +
> + out_efi_err:
> + pr_err("Could not determine UEFI Secure Boot status.\n");
> + return efi_secureboot_mode_unknown;
> +}
> +

This looks like a bad idea: you're duplicating the secure boot check in

drivers/firmware/efi/libstub/secureboot.c

Which is an implementation of policy.  If we have to have policy in the
kernel, it should really only be in one place to prevent drift; why
can't you simply use the libstub efi_get_secureboot() so we're not
duplicating the implementation of policy?

James



Re: [PATCH v2] x86/xen/efi: Initialize UEFI secure boot state during dom0 boot

2018-04-03 Thread James Bottomley
On Tue, 2018-04-03 at 16:39 +0200, Daniel Kiper wrote:
> Initialize UEFI secure boot state during dom0 boot. Otherwise the
> kernel
> may not even know that it runs on secure boot enabled platform.
> 
> Signed-off-by: Daniel Kiper 
> ---
>  arch/x86/xen/efi.c|   57
> +
>  drivers/firmware/efi/libstub/secureboot.c |3 ++
>  2 files changed, 60 insertions(+)
> 
> diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
> index a18703b..1804b27 100644
> --- a/arch/x86/xen/efi.c
> +++ b/arch/x86/xen/efi.c
> @@ -115,6 +115,61 @@ static efi_system_table_t __init
> *xen_efi_probe(void)
>   return _systab_xen;
>  }
>  
> +/*
> + * Determine whether we're in secure boot mode.
> + *
> + * Please keep the logic in sync with
> + * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
> + */
> +static enum efi_secureboot_mode xen_efi_get_secureboot(void)
> +{
> + static efi_guid_t efi_variable_guid =
> EFI_GLOBAL_VARIABLE_GUID;
> + static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
> + efi_status_t status;
> + u8 moksbstate, secboot, setupmode;
> + unsigned long size;
> +
> + size = sizeof(secboot);
> + status = efi.get_variable(L"SecureBoot", _variable_guid,
> +   NULL, , );
> +
> + if (status == EFI_NOT_FOUND)
> + return efi_secureboot_mode_disabled;
> +
> + if (status != EFI_SUCCESS)
> + goto out_efi_err;
> +
> + size = sizeof(setupmode);
> + status = efi.get_variable(L"SetupMode", _variable_guid,
> +   NULL, , );
> +
> + if (status != EFI_SUCCESS)
> + goto out_efi_err;
> +
> + if (secboot == 0 || setupmode == 1)
> + return efi_secureboot_mode_disabled;
> +
> + /* See if a user has put the shim into insecure mode. */
> + size = sizeof(moksbstate);
> + status = efi.get_variable(L"MokSBStateRT", _guid,
> +   NULL, , );
> +
> + /* If it fails, we don't care why. Default to secure. */
> + if (status != EFI_SUCCESS)
> + goto secure_boot_enabled;
> +
> + if (moksbstate == 1)
> + return efi_secureboot_mode_disabled;
> +
> + secure_boot_enabled:
> + pr_info("UEFI Secure Boot is enabled.\n");
> + return efi_secureboot_mode_enabled;
> +
> + out_efi_err:
> + pr_err("Could not determine UEFI Secure Boot status.\n");
> + return efi_secureboot_mode_unknown;
> +}
> +

This looks like a bad idea: you're duplicating the secure boot check in

drivers/firmware/efi/libstub/secureboot.c

Which is an implementation of policy.  If we have to have policy in the
kernel, it should really only be in one place to prevent drift; why
can't you simply use the libstub efi_get_secureboot() so we're not
duplicating the implementation of policy?

James



Re: [PATCH v2 11/17] kvm: arm64: Configure VTCR per VM

2018-04-03 Thread Suzuki K Poulose

On 03/04/18 15:58, James Morse wrote:

Hi Suzuki,

On 27/03/18 14:15, Suzuki K Poulose wrote:

We set VTCR_EL2 very early during the stage2 init and don't
touch it ever. This is fine as we had a fixed IPA size. This
patch changes the behavior to set the VTCR for a given VM,
depending on its stage2 table. The common configuration for
VTCR is still performed during the early init as we have to
retain the hardware access flag update bits (VTCR_EL2_HA)
per CPU (as they are only set for the CPUs which are capabile).


(Nit: capable)



Thanks for spotting, will fix it.




The bits defining the number of levels in the page table (SL0)
and and the size of the Input address to the translation (T0SZ)
are programmed for each VM upon entry to the guest.



diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 870f4b1..5ccd3ae 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -164,6 +164,12 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu 
*vcpu)
  static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
  {
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+   u64 vtcr = read_sysreg(vtcr_el2);
+
+   vtcr &= ~VTCR_EL2_PRIVATE_MASK;
+   vtcr |= VTCR_EL2_SL0(kvm_stage2_levels(kvm)) |
+   VTCR_EL2_T0SZ(kvm_phys_shift(kvm));
+   write_sysreg(vtcr, vtcr_el2);
write_sysreg(kvm->arch.vttbr, vttbr_el2);
  }


Do we need to set this register for tlb maintenance too?
e.g. tlbi for a 3-level-stage2 vm when a 2-level-stage2 vm's vtcr is loaded...

(The ARM-ARM has 'Any of the bits of VTCR_EL2 are permitted to be cached in a 
TLB'.)


You're right. We need to set the VTCR for the tlb operations. I think
we can do this by hooking it to the __tlb_switch_to_guest() routine.
Will address it in the next version.

Cheers
Suzuki


Re: [PATCH v2 11/17] kvm: arm64: Configure VTCR per VM

2018-04-03 Thread Suzuki K Poulose

On 03/04/18 15:58, James Morse wrote:

Hi Suzuki,

On 27/03/18 14:15, Suzuki K Poulose wrote:

We set VTCR_EL2 very early during the stage2 init and don't
touch it ever. This is fine as we had a fixed IPA size. This
patch changes the behavior to set the VTCR for a given VM,
depending on its stage2 table. The common configuration for
VTCR is still performed during the early init as we have to
retain the hardware access flag update bits (VTCR_EL2_HA)
per CPU (as they are only set for the CPUs which are capabile).


(Nit: capable)



Thanks for spotting, will fix it.




The bits defining the number of levels in the page table (SL0)
and and the size of the Input address to the translation (T0SZ)
are programmed for each VM upon entry to the guest.



diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 870f4b1..5ccd3ae 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -164,6 +164,12 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu 
*vcpu)
  static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
  {
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+   u64 vtcr = read_sysreg(vtcr_el2);
+
+   vtcr &= ~VTCR_EL2_PRIVATE_MASK;
+   vtcr |= VTCR_EL2_SL0(kvm_stage2_levels(kvm)) |
+   VTCR_EL2_T0SZ(kvm_phys_shift(kvm));
+   write_sysreg(vtcr, vtcr_el2);
write_sysreg(kvm->arch.vttbr, vttbr_el2);
  }


Do we need to set this register for tlb maintenance too?
e.g. tlbi for a 3-level-stage2 vm when a 2-level-stage2 vm's vtcr is loaded...

(The ARM-ARM has 'Any of the bits of VTCR_EL2 are permitted to be cached in a 
TLB'.)


You're right. We need to set the VTCR for the tlb operations. I think
we can do this by hooking it to the __tlb_switch_to_guest() routine.
Will address it in the next version.

Cheers
Suzuki


Re: [PATCH v3 09/14] s390: vfio-ap: sysfs interfaces to configure domains

2018-04-03 Thread Tony Krowiak

On 04/03/2018 11:19 AM, Cornelia Huck wrote:

On Tue, 3 Apr 2018 11:12:45 -0400
Tony Krowiak  wrote:


On 04/03/2018 07:17 AM, Cornelia Huck wrote:

On Wed, 14 Mar 2018 14:25:49 -0400
Tony Krowiak  wrote:
  

Provides the sysfs interfaces for assigning AP domains to
and unassigning AP domains from a mediated matrix device.

An AP domain ID corresponds to an AP queue index (APQI). For
each domain assigned to the mediated matrix device, its
corresponging APQI is stored in an AP queue mask (AQM).
The bits in the AQM, from most significant to least
significant bit, correspond to AP domain numbers 0 to 255.
When a domain is assigned, the bit corresponding to its
APQI will be set in the AQM. Likewise, when a domain is
unassigned, the bit corresponding to its APQI will be
cleared from the AQM.

The relevant sysfs structures are:

/sys/devices/vfio_ap
... [matrix]
.. [mdev_supported_types]
. [vfio_ap-passthrough]
 [devices]
...[$uuid]
.. assign_domain
.. unassign_domain

To assign a domain to the $uuid mediated matrix device,
write the domain's ID to the assign_domain file. To
unassign a domain, write the domain's ID to the
unassign_domain file. The ID is specified using
conventional semantics: If it begins with 0x, the number
will be parsed as a hexadecimal (case insensitive) number;
otherwise, it will be parsed as a decimal number.

For example, to assign domain 173 (0xad) to the mediated matrix
device $uuid:

echo 173 > assign_domain

or

echo 0xad > assign_domain

To unassign domain 173 (0xad):

echo 173 > unassign_domain

or

echo 0xad > unassign_domain

The assignment will be rejected:

* If the domain ID exceeds the maximum value for an AP domain:

* If the AP Extended Addressing (APXA) facility is installed,
  the max value is 255

* Else the max value is 15

* If no AP adapters have yet been assigned and there are
no AP queues reserved by the VFIO AP driver that have an APQN
with an APQI matching that of the AP domain number being
assigned.

* If any of the APQNs that can be derived from the intersection
of the APQI being assigned and the AP adapter ID (APID) of
each of the AP adapters previously assigned can not be matched
with an APQN of an AP queue device reserved by the VFIO AP
driver.

Signed-off-by: Tony Krowiak 
---
   arch/s390/include/asm/kvm-ap.h|1 +
   drivers/s390/crypto/vfio_ap_ops.c |  215 
-
   2 files changed, 215 insertions(+), 1 deletions(-)

diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
b/drivers/s390/crypto/vfio_ap_ops.c
index 90512a6..c448835 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -377,10 +377,223 @@ static ssize_t unassign_adapter_store(struct device *dev,
   }
   DEVICE_ATTR_WO(unassign_adapter);
   
+/**

+ * vfio_ap_validate_queues_for_apqi
+ *
+ * @ap_matrix: the matrix device
+ * @matrix_mdev: the mediated matrix device
+ * @apqi: an AP queue index (APQI) - corresponds to a domain ID
+ *
+ * Verifies that each APQN that is derived from the intersection of @apqi and
+ * each AP adapter ID (APID) corresponding to an AP domain assigned to the
+ * @matrix_mdev matches the APQN of an AP queue reserved by the VFIO AP device
+ * driver.
+ *
+ * Returns 0 if validation succeeds; otherwise, returns an error.
+ */
+static int vfio_ap_validate_queues_for_apqi(struct ap_matrix *ap_matrix,
+   struct ap_matrix_mdev *matrix_mdev,
+   unsigned long apqi)
+{
+   int ret;
+   struct vfio_ap_qid_match qid_match;
+   unsigned long apid;
+   struct device_driver *drv = ap_matrix->device.driver;
+
+   /**
+* Examine each APQN with the specified APQI
+*/
+   for_each_set_bit_inv(apid, matrix_mdev->matrix->apm,
+matrix_mdev->matrix->apm_max) {
+   qid_match.qid = AP_MKQID(apid, apqi);
+   qid_match.dev = NULL;
+
+   ret = driver_for_each_device(drv, NULL, _match,
+vfio_ap_queue_match);
+   if (ret)
+   return ret;

Hm, I'm wondering whether jumping out of the outer loop is the correct
thing to do here - and if yes, whether we should log an error?

If you look at the vfio_ap_queue_match() function which is passed to the
driver_for_each_device() function, it never returns an error. The
driver_for_each_device() function only returns an error if the function
passed in returns an error, so in reality, the value of *ret *will never
be anything but 0. Having said that, there are no guarantees that the
vfio_ap_queue_match() function will never change, so it would probably
be a good idea to log an error if *ret *is not 

Re: [PATCH v3 09/14] s390: vfio-ap: sysfs interfaces to configure domains

2018-04-03 Thread Tony Krowiak

On 04/03/2018 11:19 AM, Cornelia Huck wrote:

On Tue, 3 Apr 2018 11:12:45 -0400
Tony Krowiak  wrote:


On 04/03/2018 07:17 AM, Cornelia Huck wrote:

On Wed, 14 Mar 2018 14:25:49 -0400
Tony Krowiak  wrote:
  

Provides the sysfs interfaces for assigning AP domains to
and unassigning AP domains from a mediated matrix device.

An AP domain ID corresponds to an AP queue index (APQI). For
each domain assigned to the mediated matrix device, its
corresponging APQI is stored in an AP queue mask (AQM).
The bits in the AQM, from most significant to least
significant bit, correspond to AP domain numbers 0 to 255.
When a domain is assigned, the bit corresponding to its
APQI will be set in the AQM. Likewise, when a domain is
unassigned, the bit corresponding to its APQI will be
cleared from the AQM.

The relevant sysfs structures are:

/sys/devices/vfio_ap
... [matrix]
.. [mdev_supported_types]
. [vfio_ap-passthrough]
 [devices]
...[$uuid]
.. assign_domain
.. unassign_domain

To assign a domain to the $uuid mediated matrix device,
write the domain's ID to the assign_domain file. To
unassign a domain, write the domain's ID to the
unassign_domain file. The ID is specified using
conventional semantics: If it begins with 0x, the number
will be parsed as a hexadecimal (case insensitive) number;
otherwise, it will be parsed as a decimal number.

For example, to assign domain 173 (0xad) to the mediated matrix
device $uuid:

echo 173 > assign_domain

or

echo 0xad > assign_domain

To unassign domain 173 (0xad):

echo 173 > unassign_domain

or

echo 0xad > unassign_domain

The assignment will be rejected:

* If the domain ID exceeds the maximum value for an AP domain:

* If the AP Extended Addressing (APXA) facility is installed,
  the max value is 255

* Else the max value is 15

* If no AP adapters have yet been assigned and there are
no AP queues reserved by the VFIO AP driver that have an APQN
with an APQI matching that of the AP domain number being
assigned.

* If any of the APQNs that can be derived from the intersection
of the APQI being assigned and the AP adapter ID (APID) of
each of the AP adapters previously assigned can not be matched
with an APQN of an AP queue device reserved by the VFIO AP
driver.

Signed-off-by: Tony Krowiak 
---
   arch/s390/include/asm/kvm-ap.h|1 +
   drivers/s390/crypto/vfio_ap_ops.c |  215 
-
   2 files changed, 215 insertions(+), 1 deletions(-)

diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
b/drivers/s390/crypto/vfio_ap_ops.c
index 90512a6..c448835 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -377,10 +377,223 @@ static ssize_t unassign_adapter_store(struct device *dev,
   }
   DEVICE_ATTR_WO(unassign_adapter);
   
+/**

+ * vfio_ap_validate_queues_for_apqi
+ *
+ * @ap_matrix: the matrix device
+ * @matrix_mdev: the mediated matrix device
+ * @apqi: an AP queue index (APQI) - corresponds to a domain ID
+ *
+ * Verifies that each APQN that is derived from the intersection of @apqi and
+ * each AP adapter ID (APID) corresponding to an AP domain assigned to the
+ * @matrix_mdev matches the APQN of an AP queue reserved by the VFIO AP device
+ * driver.
+ *
+ * Returns 0 if validation succeeds; otherwise, returns an error.
+ */
+static int vfio_ap_validate_queues_for_apqi(struct ap_matrix *ap_matrix,
+   struct ap_matrix_mdev *matrix_mdev,
+   unsigned long apqi)
+{
+   int ret;
+   struct vfio_ap_qid_match qid_match;
+   unsigned long apid;
+   struct device_driver *drv = ap_matrix->device.driver;
+
+   /**
+* Examine each APQN with the specified APQI
+*/
+   for_each_set_bit_inv(apid, matrix_mdev->matrix->apm,
+matrix_mdev->matrix->apm_max) {
+   qid_match.qid = AP_MKQID(apid, apqi);
+   qid_match.dev = NULL;
+
+   ret = driver_for_each_device(drv, NULL, _match,
+vfio_ap_queue_match);
+   if (ret)
+   return ret;

Hm, I'm wondering whether jumping out of the outer loop is the correct
thing to do here - and if yes, whether we should log an error?

If you look at the vfio_ap_queue_match() function which is passed to the
driver_for_each_device() function, it never returns an error. The
driver_for_each_device() function only returns an error if the function
passed in returns an error, so in reality, the value of *ret *will never
be anything but 0. Having said that, there are no guarantees that the
vfio_ap_queue_match() function will never change, so it would probably
be a good idea to log an error if *ret *is not 0.**I think returning at
this point is valid because a non-zero is returned from

Re: [GIT PULL] Kernel lockdown for secure boot

2018-04-03 Thread Alexei Starovoitov
On Tue, Apr 03, 2018 at 08:11:07AM -0700, Andy Lutomirski wrote:
> >
> >> "bpf: Restrict kernel image access functions when the kernel is locked 
> >> down":
> >> This patch just sucks in general.
> >
> > Yes - but that's what Alexei Starovoitov specified.  bpf kind of sucks since
> > it gives you unrestricted access to the kernel.
> 
> bpf, in certain contexts, gives you unrestricted access to *reading*
> kernel memory.  bpf should, under no circumstances, let you write to
> the kernel unless you're using fault injection or similar.
> 
> I'm surprised that Alexei acked this patch.  If something like XDP or
> bpfilter starts becoming widely used, this patch will require a lot of
> reworking to avoid breaking standard distros.

my understanding was that this lockdown set attemps to disallow _reads_
of kernel memory from anything, so first version of patch was adding
run-time checks for bpf_probe_read() which is no-go
and without this helper the bpf for tracing is losing a lot of its power,
so the easiest is to disable it all.
I think lockdown suppose to disable xdp, bpfilter, nflog, raw sockets + pcap too
otherwise even cap_net_admin can see traffic coming into host.
Similarly kprobe, perf_event, ftrace should be off as well?



Re: [GIT PULL] Kernel lockdown for secure boot

2018-04-03 Thread Alexei Starovoitov
On Tue, Apr 03, 2018 at 08:11:07AM -0700, Andy Lutomirski wrote:
> >
> >> "bpf: Restrict kernel image access functions when the kernel is locked 
> >> down":
> >> This patch just sucks in general.
> >
> > Yes - but that's what Alexei Starovoitov specified.  bpf kind of sucks since
> > it gives you unrestricted access to the kernel.
> 
> bpf, in certain contexts, gives you unrestricted access to *reading*
> kernel memory.  bpf should, under no circumstances, let you write to
> the kernel unless you're using fault injection or similar.
> 
> I'm surprised that Alexei acked this patch.  If something like XDP or
> bpfilter starts becoming widely used, this patch will require a lot of
> reworking to avoid breaking standard distros.

my understanding was that this lockdown set attemps to disallow _reads_
of kernel memory from anything, so first version of patch was adding
run-time checks for bpf_probe_read() which is no-go
and without this helper the bpf for tracing is losing a lot of its power,
so the easiest is to disable it all.
I think lockdown suppose to disable xdp, bpfilter, nflog, raw sockets + pcap too
otherwise even cap_net_admin can see traffic coming into host.
Similarly kprobe, perf_event, ftrace should be off as well?



Re: [PATCH 02/15] ARM: pxa: add dma slave map

2018-04-03 Thread Arnd Bergmann
On Tue, Apr 3, 2018 at 5:18 PM, Robert Jarzmik  wrote:
> Arnd Bergmann  writes:
>
>>> +   { "smc911x.0", "rx", PDMA_FILTER_PARAM(LOWEST, -1) },
>>> +   { "smc911x.0", "tx", PDMA_FILTER_PARAM(LOWEST, -1) },
>>> +   { "smc91x.0", "data", PDMA_FILTER_PARAM(LOWEST, -1) },
>>
>> This one is interesting, as you are dealing with an off-chip device,
>> and the channel number is '-'1. How does this even work? Does it
>> mean
>
> This relies on pxa_dma, in which the "-1" for a requestor line means "no
> requestor" or said in another way "always requesting". As a consequence, as 
> soon
> as the DMA descriptors are queued, the transfer begins, and it is supposed
> implicitely that the FIFO output availability is at least as quick as the 
> system
> bus and the DMA size is perfectly fit for the FIFO available bytes.
>
> This is what has been the underlying of DMA transfers of smc91x(x) on the PXA
> platforms, where the smc91x(s) are directly wired on the system bus (the same
> bus having DRAM, SRAM, IO-mapped devices).

Ok, I looked at the driver in more detail now and found the scary parts.
So it's using the async DMA interface to do synchronous DMA in
interrupt context in order to transfer the rx data faster than an readsl()
would, correct?

It still feels odd to me that there is an entry in the slave map for
a device that does not have a request line. However, it also seems
that the entire code in those two drivers that deals with DMA is specific
to PXA anyway, so maybe it can be done differently: instead of
calling dma_request_slave_channel_compat() or dma_request_chan()
with a fake request line, how about calling dma_request_channel()
with an NULL filter function and data, and have the driver handle
the empty data case the same way as the rq=-1 case today?

>>> +   /* PXA25x specific map */
>>> +   { "pxa25x-ssp.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
>>> +   { "pxa25x-ssp.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
>>> +   { "pxa25x-nssp.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>>> +   { "pxa25x-nssp.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>>> +   { "pxa25x-nssp.2", "rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>>> +   { "pxa25x-nssp.2", "tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>>> +   { "pxa-pcm-audio", "nssp2_rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>>> +   { "pxa-pcm-audio", "nssp2_tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>>> +   { "pxa-pcm-audio", "nssp3_rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>>> +   { "pxa-pcm-audio", "nssp3_tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>>> +
>>> +   /* PXA27x specific map */
>>> +   { "pxa-pcm-audio", "ssp3_rx", PDMA_FILTER_PARAM(LOWEST, 66) },
>>> +   { "pxa-pcm-audio", "ssp3_tx", PDMA_FILTER_PARAM(LOWEST, 67) },
>>> +   { "pxa27x-camera.0", "CI_Y", PDMA_FILTER_PARAM(HIGHEST, 68) },
>>> +   { "pxa27x-camera.0", "CI_U", PDMA_FILTER_PARAM(HIGHEST, 69) },
>>> +   { "pxa27x-camera.0", "CI_V", PDMA_FILTER_PARAM(HIGHEST, 70) },
>>> +
>>> +   /* PXA3xx specific map */
>>> +   { "pxa-pcm-audio", "ssp4_rx", PDMA_FILTER_PARAM(LOWEST, 2) },
>>> +   { "pxa-pcm-audio", "ssp4_tx", PDMA_FILTER_PARAM(LOWEST, 3) },
>>> +   { "pxa2xx-mci.1", "rx", PDMA_FILTER_PARAM(LOWEST, 93) },
>>> +   { "pxa2xx-mci.1", "tx", PDMA_FILTER_PARAM(LOWEST, 94) },
>>> +   { "pxa3xx-nand", "data", PDMA_FILTER_PARAM(LOWEST, 97) },
>>> +   { "pxa2xx-mci.2", "rx", PDMA_FILTER_PARAM(LOWEST, 100) },
>>> +   { "pxa2xx-mci.2", "tx", PDMA_FILTER_PARAM(LOWEST, 101) },
>>> +};
>>
>> Since more than half the entries in here are chip specific, maybe it would be
>> better to split that table into three and have a copy for each one in
>> arch/arm/mach-pxa/pxa{25x.27x.3xx}.c?
> Mmmh, today the split is :
>  - 16 common entries
>  - 10 pxa25x specific entries
>  - 5 pxa27x specific entries
>  - 7 pxa3xx specific entries
>  => total of 38 lines
>
> After the split we'll have :
>  - 26 pxa25x specific entries
>  - 21 pxa27x specific entries
>  - 23 pxa3xx specific entries
>  => total of 70 lines
>
> That doubles the number of lines, not counting the declarations, and amending 
> of
> pxa2xx_set_dmac_info().
>
> If you think it's worth it, what is the driving benefit behind ?

It seems a bit cleaner to only register the tables for the dma lines that
are actually present on a given chip.

>> Does that mean it's actually a memory-to-memory transfer with a device being
>> on the external SRAM interface?
> I'm taking this is the follow up to the "-1" question :0

Right.

Arnd


Re: [PATCH 02/15] ARM: pxa: add dma slave map

2018-04-03 Thread Arnd Bergmann
On Tue, Apr 3, 2018 at 5:18 PM, Robert Jarzmik  wrote:
> Arnd Bergmann  writes:
>
>>> +   { "smc911x.0", "rx", PDMA_FILTER_PARAM(LOWEST, -1) },
>>> +   { "smc911x.0", "tx", PDMA_FILTER_PARAM(LOWEST, -1) },
>>> +   { "smc91x.0", "data", PDMA_FILTER_PARAM(LOWEST, -1) },
>>
>> This one is interesting, as you are dealing with an off-chip device,
>> and the channel number is '-'1. How does this even work? Does it
>> mean
>
> This relies on pxa_dma, in which the "-1" for a requestor line means "no
> requestor" or said in another way "always requesting". As a consequence, as 
> soon
> as the DMA descriptors are queued, the transfer begins, and it is supposed
> implicitely that the FIFO output availability is at least as quick as the 
> system
> bus and the DMA size is perfectly fit for the FIFO available bytes.
>
> This is what has been the underlying of DMA transfers of smc91x(x) on the PXA
> platforms, where the smc91x(s) are directly wired on the system bus (the same
> bus having DRAM, SRAM, IO-mapped devices).

Ok, I looked at the driver in more detail now and found the scary parts.
So it's using the async DMA interface to do synchronous DMA in
interrupt context in order to transfer the rx data faster than an readsl()
would, correct?

It still feels odd to me that there is an entry in the slave map for
a device that does not have a request line. However, it also seems
that the entire code in those two drivers that deals with DMA is specific
to PXA anyway, so maybe it can be done differently: instead of
calling dma_request_slave_channel_compat() or dma_request_chan()
with a fake request line, how about calling dma_request_channel()
with an NULL filter function and data, and have the driver handle
the empty data case the same way as the rq=-1 case today?

>>> +   /* PXA25x specific map */
>>> +   { "pxa25x-ssp.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
>>> +   { "pxa25x-ssp.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
>>> +   { "pxa25x-nssp.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>>> +   { "pxa25x-nssp.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>>> +   { "pxa25x-nssp.2", "rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>>> +   { "pxa25x-nssp.2", "tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>>> +   { "pxa-pcm-audio", "nssp2_rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>>> +   { "pxa-pcm-audio", "nssp2_tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>>> +   { "pxa-pcm-audio", "nssp3_rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>>> +   { "pxa-pcm-audio", "nssp3_tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>>> +
>>> +   /* PXA27x specific map */
>>> +   { "pxa-pcm-audio", "ssp3_rx", PDMA_FILTER_PARAM(LOWEST, 66) },
>>> +   { "pxa-pcm-audio", "ssp3_tx", PDMA_FILTER_PARAM(LOWEST, 67) },
>>> +   { "pxa27x-camera.0", "CI_Y", PDMA_FILTER_PARAM(HIGHEST, 68) },
>>> +   { "pxa27x-camera.0", "CI_U", PDMA_FILTER_PARAM(HIGHEST, 69) },
>>> +   { "pxa27x-camera.0", "CI_V", PDMA_FILTER_PARAM(HIGHEST, 70) },
>>> +
>>> +   /* PXA3xx specific map */
>>> +   { "pxa-pcm-audio", "ssp4_rx", PDMA_FILTER_PARAM(LOWEST, 2) },
>>> +   { "pxa-pcm-audio", "ssp4_tx", PDMA_FILTER_PARAM(LOWEST, 3) },
>>> +   { "pxa2xx-mci.1", "rx", PDMA_FILTER_PARAM(LOWEST, 93) },
>>> +   { "pxa2xx-mci.1", "tx", PDMA_FILTER_PARAM(LOWEST, 94) },
>>> +   { "pxa3xx-nand", "data", PDMA_FILTER_PARAM(LOWEST, 97) },
>>> +   { "pxa2xx-mci.2", "rx", PDMA_FILTER_PARAM(LOWEST, 100) },
>>> +   { "pxa2xx-mci.2", "tx", PDMA_FILTER_PARAM(LOWEST, 101) },
>>> +};
>>
>> Since more than half the entries in here are chip specific, maybe it would be
>> better to split that table into three and have a copy for each one in
>> arch/arm/mach-pxa/pxa{25x.27x.3xx}.c?
> Mmmh, today the split is :
>  - 16 common entries
>  - 10 pxa25x specific entries
>  - 5 pxa27x specific entries
>  - 7 pxa3xx specific entries
>  => total of 38 lines
>
> After the split we'll have :
>  - 26 pxa25x specific entries
>  - 21 pxa27x specific entries
>  - 23 pxa3xx specific entries
>  => total of 70 lines
>
> That doubles the number of lines, not counting the declarations, and amending 
> of
> pxa2xx_set_dmac_info().
>
> If you think it's worth it, what is the driving benefit behind ?

It seems a bit cleaner to only register the tables for the dma lines that
are actually present on a given chip.

>> Does that mean it's actually a memory-to-memory transfer with a device being
>> on the external SRAM interface?
> I'm taking this is the follow up to the "-1" question :0

Right.

Arnd


Re: [PATCH v2 5/6] i2c: i2c-stm32f7: Add DMA support

2018-04-03 Thread Wolfram Sang

> +#define STM32F7_I2C_DMA_LEN_MIN  0x1
...

> + if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {

Are you using DMA for every message with a length >= 1? The setup of
that might be more expensive than the DMA gain, if so.



signature.asc
Description: PGP signature


Re: [PATCH v2 5/6] i2c: i2c-stm32f7: Add DMA support

2018-04-03 Thread Wolfram Sang

> +#define STM32F7_I2C_DMA_LEN_MIN  0x1
...

> + if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {

Are you using DMA for every message with a length >= 1? The setup of
that might be more expensive than the DMA gain, if so.



signature.asc
Description: PGP signature


[PATCH v2 0/2] iio: add unit converter

2018-04-03 Thread Peter Rosin
Hi!

This driver implements support for voltage dividers and current
sense circuits. It's pretty generic and should be easily adaptable
to other linear scaling purposes...

The driver is still named "unit converter", because it was not
clear to me that there was a real problem with the driver being
named that. I got the impression that the naming discussion in
v1 was mainly about the category, and that it kind of looked odd
and non-specific with unit-converter in the DT bindings, but
what do I know?

Cheers,
Peter

Changes since v1:https://lkml.org/lkml/2018/3/19/801
- Put the driver in the new afe category (Analog Front Ends) and do not
  move the iio-mux driver.
- Do not refer to the source channel as "parent", use "source" instead.
- Have the DT compatible drive the target unit, instead of relying on a
  "type" DT-property for that.
- In the DT bindings, use an unnamed source channel.
- Do not set up writes to _RAW (sorry Phil) as I don't need it and have
  not tested it. It's easy to add back if needed.
- Fail if the source channel does not support _RAW or _SCALE.
- Fix various spelling issues.
- Fix various code style issues.

Peter Rosin (2):
  dt-bindings: iio: afe: add current-sense-cuicuit and voltage-divider
  iio: afe: unit-converter: new driver

 .../bindings/iio/afe/current-sense-circuit.txt |  45 
 .../bindings/iio/afe/voltage-divider.txt   |  45 
 MAINTAINERS|   8 +
 drivers/iio/Kconfig|   1 +
 drivers/iio/Makefile   |   1 +
 drivers/iio/afe/Kconfig|  18 ++
 drivers/iio/afe/Makefile   |   6 +
 drivers/iio/afe/iio-unit-converter.c   | 257 +
 8 files changed, 381 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
 create mode 100644 drivers/iio/afe/Kconfig
 create mode 100644 drivers/iio/afe/Makefile
 create mode 100644 drivers/iio/afe/iio-unit-converter.c

-- 
2.11.0



[PATCH v2 0/2] iio: add unit converter

2018-04-03 Thread Peter Rosin
Hi!

This driver implements support for voltage dividers and current
sense circuits. It's pretty generic and should be easily adaptable
to other linear scaling purposes...

The driver is still named "unit converter", because it was not
clear to me that there was a real problem with the driver being
named that. I got the impression that the naming discussion in
v1 was mainly about the category, and that it kind of looked odd
and non-specific with unit-converter in the DT bindings, but
what do I know?

Cheers,
Peter

Changes since v1:https://lkml.org/lkml/2018/3/19/801
- Put the driver in the new afe category (Analog Front Ends) and do not
  move the iio-mux driver.
- Do not refer to the source channel as "parent", use "source" instead.
- Have the DT compatible drive the target unit, instead of relying on a
  "type" DT-property for that.
- In the DT bindings, use an unnamed source channel.
- Do not set up writes to _RAW (sorry Phil) as I don't need it and have
  not tested it. It's easy to add back if needed.
- Fail if the source channel does not support _RAW or _SCALE.
- Fix various spelling issues.
- Fix various code style issues.

Peter Rosin (2):
  dt-bindings: iio: afe: add current-sense-cuicuit and voltage-divider
  iio: afe: unit-converter: new driver

 .../bindings/iio/afe/current-sense-circuit.txt |  45 
 .../bindings/iio/afe/voltage-divider.txt   |  45 
 MAINTAINERS|   8 +
 drivers/iio/Kconfig|   1 +
 drivers/iio/Makefile   |   1 +
 drivers/iio/afe/Kconfig|  18 ++
 drivers/iio/afe/Makefile   |   6 +
 drivers/iio/afe/iio-unit-converter.c   | 257 +
 8 files changed, 381 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
 create mode 100644 drivers/iio/afe/Kconfig
 create mode 100644 drivers/iio/afe/Makefile
 create mode 100644 drivers/iio/afe/iio-unit-converter.c

-- 
2.11.0



[PATCH v2 1/2] dt-bindings: iio: afe: add current-sense-cuicuit and voltage-divider

2018-04-03 Thread Peter Rosin
An ADC is often used to measure other quantities indirectly. These
bindings describe two cases, a current through a sense resistor, and
a "big" voltage measured with the help of a voltage divider.

Signed-off-by: Peter Rosin 
---
 .../bindings/iio/afe/current-sense-circuit.txt | 45 ++
 .../bindings/iio/afe/voltage-divider.txt   | 45 ++
 MAINTAINERS|  7 
 3 files changed, 97 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/voltage-divider.txt

diff --git 
a/Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt 
b/Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
new file mode 100644
index ..0bc7d89387c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
@@ -0,0 +1,45 @@
+Current Sense Curcuit
+=
+
+When an io-channel measures the voltage over a current sense resistor,
+the interesting mesaurement is often the current through the resistor,
+not the voltage over it. This binding describes such a current sense
+curcuit.
+
+Required properties:
+- compatible : "current-sense-circuit"
+- io-channels : Channel node of a voltage io-channel.
+
+Optional properties:
+- numerator : The io-channel scale is multiplied by this value (default 1).
+- denominator : The io-channel scale is divided by this value (default 1).
+
+Example:
+The system current is measured by measuring the voltage over a
+3.3 ohms sense resistor.
+
+sysi {
+   compatible = "current-sense-circuit";
+   io-channels = < 0>;
+
+   /* Divide the ADC voltage by 33/10 (i.e. 3.3) to get the current. */
+   numerator = <10>;
+   denominator = <33>;
+};
+
+ {
+   tiadc: adc@48 {
+   compatible = "ti,ads1015";
+   reg = <0x48>;
+   #io-channel-cells = <1>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   channel@0 { /* IN0,IN1 differential */
+   reg = <0>;
+   ti,gain = <1>;
+   ti,datarate = <4>;
+   };
+   };
+};
diff --git a/Documentation/devicetree/bindings/iio/afe/voltage-divider.txt 
b/Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
new file mode 100644
index ..fd4a215d9e6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
@@ -0,0 +1,45 @@
+Voltage divider
+===
+
+When an io-channel measures the midpoint of a voltage divider, the
+interesting voltage is often the voltage over the full resistance
+of the divider. This binding describes the voltage divider in such
+a curcuit.
+
+Required properties:
+- compatible : "voltage-divider"
+- io-channels : Channel node of a voltage io-channel.
+
+Optional properties:
+- numerator : The io-channel scale is multiplied by this value (default 1).
+- denominator : The io-channel scale is divided by this value (default 1).
+
+Example:
+The system voltage is circa 12V, but divided down with a 22/200
+voltage divider to adjust it to the ADC range.
+
+SYSVADC   GND
+  +  + +
+  |  .-. | ..  |
+  '--| 200 |-+-| 22 |--'
+ '-'   ''
+
+sysv {
+   compatible = "voltage-divider";
+   io-channels = < 1>;
+
+   /* Multiply the ADC voltage by 222/22 to get the system voltage. */
+   numerator = <222>; /* 200 + 22 */
+   denominator = <22>;
+};
+
+ {
+   maxadc: adc@0 {
+   compatible = "maxim,max1027";
+   reg = <0>;
+   #io-channel-cells = <1>;
+   interrupt-parent = <>;
+   interrupts = <15 IRQ_TYPE_EDGE_RISING>;
+   spi-max-frequency = <100>;
+   };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 36a28e979e9a..9dbe5019c6bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6889,6 +6889,13 @@ F:   drivers/staging/iio/
 F: include/linux/iio/
 F: tools/iio/
 
+IIO UNIT CONVERTER
+M: Peter Rosin 
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
+F: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
+
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M: Matthieu Castet 
 M: Stanislaw Gruszka 
-- 
2.11.0



[PATCH v2 2/2] iio: afe: unit-converter: new driver

2018-04-03 Thread Peter Rosin
If an ADC channel measures the midpoint of a voltage divider, the
interesting voltage is often the voltage over the full resistance.
E.g. if the full voltage is too big for the ADC to handle.
Likewise, if an ADC channel measures the voltage across a resistor,
the interesting value is often the current through the resistor.

This driver solves both problems by allowing to linearly scale a channel
and by allowing changes to the type of the channel. Or both.

Signed-off-by: Peter Rosin 
---
 MAINTAINERS  |   1 +
 drivers/iio/Kconfig  |   1 +
 drivers/iio/Makefile |   1 +
 drivers/iio/afe/Kconfig  |  18 +++
 drivers/iio/afe/Makefile |   6 +
 drivers/iio/afe/iio-unit-converter.c | 257 +++
 6 files changed, 284 insertions(+)
 create mode 100644 drivers/iio/afe/Kconfig
 create mode 100644 drivers/iio/afe/Makefile
 create mode 100644 drivers/iio/afe/iio-unit-converter.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9dbe5019c6bd..f9835521eec6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6895,6 +6895,7 @@ L:linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
 F: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
+F: drivers/iio/afe/iio-unit-converter.c
 
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M: Matthieu Castet 
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index b3c8c6ef0dff..d69e85a8bdc3 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -70,6 +70,7 @@ config IIO_TRIGGERED_EVENT
 
 source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
+source "drivers/iio/afe/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
 source "drivers/iio/chemical/Kconfig"
 source "drivers/iio/common/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index b16b2e9ddc40..d8cba9c229c0 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += 
industrialio-triggered-event.o
 
 obj-y += accel/
 obj-y += adc/
+obj-y += afe/
 obj-y += amplifiers/
 obj-y += buffer/
 obj-y += chemical/
diff --git a/drivers/iio/afe/Kconfig b/drivers/iio/afe/Kconfig
new file mode 100644
index ..75acbe7eed15
--- /dev/null
+++ b/drivers/iio/afe/Kconfig
@@ -0,0 +1,18 @@
+#
+# Analog Front End drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Analog Front Ends"
+
+config IIO_UNIT_CONVERTER
+   tristate "IIO unit converter"
+   depends on OF || COMPILE_TEST
+   help
+ Say yes here to build support for the IIO unit converter
+ that handles voltage dividers and current sense circuits.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-unit-converter.
+
+endmenu
diff --git a/drivers/iio/afe/Makefile b/drivers/iio/afe/Makefile
new file mode 100644
index ..7691cc5b809a
--- /dev/null
+++ b/drivers/iio/afe/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O Analog Front Ends (AFE)
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_UNIT_CONVERTER) += iio-unit-converter.o
diff --git a/drivers/iio/afe/iio-unit-converter.c 
b/drivers/iio/afe/iio-unit-converter.c
new file mode 100644
index ..43429543cc29
--- /dev/null
+++ b/drivers/iio/afe/iio-unit-converter.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IIO unit converter
+ *
+ * Copyright (C) 2018 Axentia Technologies AB
+ *
+ * Author: Peter Rosin 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct unit_converter_cfg {
+   enum iio_chan_type type;
+};
+
+enum unit_converter_variant {
+   CURRENT_SENSE_CIRCUIT,
+   VOLTAGE_DIVIDER,
+};
+
+static const struct unit_converter_cfg unit_converter_cfg[] = {
+   [CURRENT_SENSE_CIRCUIT] = {
+   .type = IIO_CURRENT,
+   },
+   [VOLTAGE_DIVIDER] = {
+   .type = IIO_VOLTAGE,
+   },
+};
+
+struct unit_converter {
+   const struct unit_converter_cfg *cfg;
+   struct iio_channel *source;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   s32 numerator;
+   s32 denominator;
+};
+
+static int unit_converter_read_raw(struct iio_dev *indio_dev,
+  struct iio_chan_spec const *chan,
+  int *val, int *val2, long mask)
+{
+   struct unit_converter *uc = iio_priv(indio_dev);
+   unsigned long long tmp;
+   int ret;
+
+   switch (mask) {
+   case IIO_CHAN_INFO_RAW:
+   return iio_read_channel_raw(uc->source, val);
+
+   case IIO_CHAN_INFO_SCALE:
+   ret = iio_read_channel_scale(uc->source, val, val2);
+   switch (ret) 

[PATCH v2 1/2] dt-bindings: iio: afe: add current-sense-cuicuit and voltage-divider

2018-04-03 Thread Peter Rosin
An ADC is often used to measure other quantities indirectly. These
bindings describe two cases, a current through a sense resistor, and
a "big" voltage measured with the help of a voltage divider.

Signed-off-by: Peter Rosin 
---
 .../bindings/iio/afe/current-sense-circuit.txt | 45 ++
 .../bindings/iio/afe/voltage-divider.txt   | 45 ++
 MAINTAINERS|  7 
 3 files changed, 97 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
 create mode 100644 
Documentation/devicetree/bindings/iio/afe/voltage-divider.txt

diff --git 
a/Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt 
b/Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
new file mode 100644
index ..0bc7d89387c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
@@ -0,0 +1,45 @@
+Current Sense Curcuit
+=
+
+When an io-channel measures the voltage over a current sense resistor,
+the interesting mesaurement is often the current through the resistor,
+not the voltage over it. This binding describes such a current sense
+curcuit.
+
+Required properties:
+- compatible : "current-sense-circuit"
+- io-channels : Channel node of a voltage io-channel.
+
+Optional properties:
+- numerator : The io-channel scale is multiplied by this value (default 1).
+- denominator : The io-channel scale is divided by this value (default 1).
+
+Example:
+The system current is measured by measuring the voltage over a
+3.3 ohms sense resistor.
+
+sysi {
+   compatible = "current-sense-circuit";
+   io-channels = < 0>;
+
+   /* Divide the ADC voltage by 33/10 (i.e. 3.3) to get the current. */
+   numerator = <10>;
+   denominator = <33>;
+};
+
+ {
+   tiadc: adc@48 {
+   compatible = "ti,ads1015";
+   reg = <0x48>;
+   #io-channel-cells = <1>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   channel@0 { /* IN0,IN1 differential */
+   reg = <0>;
+   ti,gain = <1>;
+   ti,datarate = <4>;
+   };
+   };
+};
diff --git a/Documentation/devicetree/bindings/iio/afe/voltage-divider.txt 
b/Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
new file mode 100644
index ..fd4a215d9e6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
@@ -0,0 +1,45 @@
+Voltage divider
+===
+
+When an io-channel measures the midpoint of a voltage divider, the
+interesting voltage is often the voltage over the full resistance
+of the divider. This binding describes the voltage divider in such
+a curcuit.
+
+Required properties:
+- compatible : "voltage-divider"
+- io-channels : Channel node of a voltage io-channel.
+
+Optional properties:
+- numerator : The io-channel scale is multiplied by this value (default 1).
+- denominator : The io-channel scale is divided by this value (default 1).
+
+Example:
+The system voltage is circa 12V, but divided down with a 22/200
+voltage divider to adjust it to the ADC range.
+
+SYSVADC   GND
+  +  + +
+  |  .-. | ..  |
+  '--| 200 |-+-| 22 |--'
+ '-'   ''
+
+sysv {
+   compatible = "voltage-divider";
+   io-channels = < 1>;
+
+   /* Multiply the ADC voltage by 222/22 to get the system voltage. */
+   numerator = <222>; /* 200 + 22 */
+   denominator = <22>;
+};
+
+ {
+   maxadc: adc@0 {
+   compatible = "maxim,max1027";
+   reg = <0>;
+   #io-channel-cells = <1>;
+   interrupt-parent = <>;
+   interrupts = <15 IRQ_TYPE_EDGE_RISING>;
+   spi-max-frequency = <100>;
+   };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 36a28e979e9a..9dbe5019c6bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6889,6 +6889,13 @@ F:   drivers/staging/iio/
 F: include/linux/iio/
 F: tools/iio/
 
+IIO UNIT CONVERTER
+M: Peter Rosin 
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
+F: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
+
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M: Matthieu Castet 
 M: Stanislaw Gruszka 
-- 
2.11.0



[PATCH v2 2/2] iio: afe: unit-converter: new driver

2018-04-03 Thread Peter Rosin
If an ADC channel measures the midpoint of a voltage divider, the
interesting voltage is often the voltage over the full resistance.
E.g. if the full voltage is too big for the ADC to handle.
Likewise, if an ADC channel measures the voltage across a resistor,
the interesting value is often the current through the resistor.

This driver solves both problems by allowing to linearly scale a channel
and by allowing changes to the type of the channel. Or both.

Signed-off-by: Peter Rosin 
---
 MAINTAINERS  |   1 +
 drivers/iio/Kconfig  |   1 +
 drivers/iio/Makefile |   1 +
 drivers/iio/afe/Kconfig  |  18 +++
 drivers/iio/afe/Makefile |   6 +
 drivers/iio/afe/iio-unit-converter.c | 257 +++
 6 files changed, 284 insertions(+)
 create mode 100644 drivers/iio/afe/Kconfig
 create mode 100644 drivers/iio/afe/Makefile
 create mode 100644 drivers/iio/afe/iio-unit-converter.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9dbe5019c6bd..f9835521eec6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6895,6 +6895,7 @@ L:linux-...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/iio/afe/current-sense-circuit.txt
 F: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
+F: drivers/iio/afe/iio-unit-converter.c
 
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M: Matthieu Castet 
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index b3c8c6ef0dff..d69e85a8bdc3 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -70,6 +70,7 @@ config IIO_TRIGGERED_EVENT
 
 source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
+source "drivers/iio/afe/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
 source "drivers/iio/chemical/Kconfig"
 source "drivers/iio/common/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index b16b2e9ddc40..d8cba9c229c0 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += 
industrialio-triggered-event.o
 
 obj-y += accel/
 obj-y += adc/
+obj-y += afe/
 obj-y += amplifiers/
 obj-y += buffer/
 obj-y += chemical/
diff --git a/drivers/iio/afe/Kconfig b/drivers/iio/afe/Kconfig
new file mode 100644
index ..75acbe7eed15
--- /dev/null
+++ b/drivers/iio/afe/Kconfig
@@ -0,0 +1,18 @@
+#
+# Analog Front End drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Analog Front Ends"
+
+config IIO_UNIT_CONVERTER
+   tristate "IIO unit converter"
+   depends on OF || COMPILE_TEST
+   help
+ Say yes here to build support for the IIO unit converter
+ that handles voltage dividers and current sense circuits.
+
+ To compile this driver as a module, choose M here: the
+ module will be called iio-unit-converter.
+
+endmenu
diff --git a/drivers/iio/afe/Makefile b/drivers/iio/afe/Makefile
new file mode 100644
index ..7691cc5b809a
--- /dev/null
+++ b/drivers/iio/afe/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O Analog Front Ends (AFE)
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_UNIT_CONVERTER) += iio-unit-converter.o
diff --git a/drivers/iio/afe/iio-unit-converter.c 
b/drivers/iio/afe/iio-unit-converter.c
new file mode 100644
index ..43429543cc29
--- /dev/null
+++ b/drivers/iio/afe/iio-unit-converter.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IIO unit converter
+ *
+ * Copyright (C) 2018 Axentia Technologies AB
+ *
+ * Author: Peter Rosin 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct unit_converter_cfg {
+   enum iio_chan_type type;
+};
+
+enum unit_converter_variant {
+   CURRENT_SENSE_CIRCUIT,
+   VOLTAGE_DIVIDER,
+};
+
+static const struct unit_converter_cfg unit_converter_cfg[] = {
+   [CURRENT_SENSE_CIRCUIT] = {
+   .type = IIO_CURRENT,
+   },
+   [VOLTAGE_DIVIDER] = {
+   .type = IIO_VOLTAGE,
+   },
+};
+
+struct unit_converter {
+   const struct unit_converter_cfg *cfg;
+   struct iio_channel *source;
+   struct iio_dev *indio_dev;
+   struct iio_chan_spec chan;
+   struct iio_chan_spec_ext_info *ext_info;
+   s32 numerator;
+   s32 denominator;
+};
+
+static int unit_converter_read_raw(struct iio_dev *indio_dev,
+  struct iio_chan_spec const *chan,
+  int *val, int *val2, long mask)
+{
+   struct unit_converter *uc = iio_priv(indio_dev);
+   unsigned long long tmp;
+   int ret;
+
+   switch (mask) {
+   case IIO_CHAN_INFO_RAW:
+   return iio_read_channel_raw(uc->source, val);
+
+   case IIO_CHAN_INFO_SCALE:
+   ret = iio_read_channel_scale(uc->source, val, val2);
+   switch (ret) {
+   case IIO_VAL_FRACTIONAL:
+   

Re: [PATCH 14/15] ARM: pxa: change SSP devices allocation

2018-04-03 Thread Robert Jarzmik
Arnd Bergmann  writes:

chop chop ... removed several mail recipients to leave only the ASoC / PXA
subset ...

> On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik  wrote:
>
>>
>> +static struct pxa_ssp_info pxa_ssp_infos[] = {
>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>> +};
>
> This part looks odd to me, you're adding an extra level of indirection to
> do two stages of lookups in some form of platform data.
That's unfortunately right.

> Why can't you just always use "rx" and "tx" as the names here?
Well I couldn't. I'll explain you why, and maybe you'll find a better solution.

That all is related to how ASoC and SSP interact.
If I remember correctly, here is how it works :
 - the DMA channel is requested in sound/arm/pxa2xx-pcm-lib.c:128
return snd_dmaengine_pcm_open(
substream, dma_request_slave_channel(rtd->platform->dev,
   The trick is that the device here is _not_ the SSP one, it's if memory serves
   me well the pxa-pcm-audio one.

   As a consequence, the device cannot be used to differenciate which SSP
   exactly is providing the sound samples stream. This information is
   nevertheless required to choose the correct requestor line, which is a 1-to-1
   match to the SSP port.

   The indirection in the channel name is used to choose the correct requestor
   line for a given SSP port providing the samples.

   It also must be underlined that this dma request serves both AC97 and SSP as
   sample providers.

> (also, I don't see why each line is duplicated, but I'm sure there's
> an easy answer for that).
Ahh that is an unfortunate rebase most probably :)

Cheers.

-- 
Robert


Re: [PATCH 14/15] ARM: pxa: change SSP devices allocation

2018-04-03 Thread Robert Jarzmik
Arnd Bergmann  writes:

chop chop ... removed several mail recipients to leave only the ASoC / PXA
subset ...

> On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik  wrote:
>
>>
>> +static struct pxa_ssp_info pxa_ssp_infos[] = {
>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>> +   { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>> +   { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>> +   { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>> +   { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>> +};
>
> This part looks odd to me, you're adding an extra level of indirection to
> do two stages of lookups in some form of platform data.
That's unfortunately right.

> Why can't you just always use "rx" and "tx" as the names here?
Well I couldn't. I'll explain you why, and maybe you'll find a better solution.

That all is related to how ASoC and SSP interact.
If I remember correctly, here is how it works :
 - the DMA channel is requested in sound/arm/pxa2xx-pcm-lib.c:128
return snd_dmaengine_pcm_open(
substream, dma_request_slave_channel(rtd->platform->dev,
   The trick is that the device here is _not_ the SSP one, it's if memory serves
   me well the pxa-pcm-audio one.

   As a consequence, the device cannot be used to differenciate which SSP
   exactly is providing the sound samples stream. This information is
   nevertheless required to choose the correct requestor line, which is a 1-to-1
   match to the SSP port.

   The indirection in the channel name is used to choose the correct requestor
   line for a given SSP port providing the samples.

   It also must be underlined that this dma request serves both AC97 and SSP as
   sample providers.

> (also, I don't see why each line is duplicated, but I'm sure there's
> an easy answer for that).
Ahh that is an unfortunate rebase most probably :)

Cheers.

-- 
Robert


[GIT] Sparc

2018-04-03 Thread David Miller

1) Add support for ADI (Application Data Integrity) found in more recent
   sparc64 cpus.  Essentially this is keyed based access to virtual memory,
   and if the key encoded in the virual address is wrong you get a trap.

   The mm changes were reviewed by Andrew Morton and others.

   Work by Khalid Aziz.

2) Validate DAX completion index range properly, from Rob Gardner.

3) Add proper Kconfig deps for DAX driver.  From Guenter Roeck.

Please pull, thanks a lot.

The following changes since commit 8f5fd927c3a7576d57248a2d7a0861c3f2795973:

  Merge tag 'for-4.16-rc5-tag' of 
git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux (2018-03-16 13:37:42 
-0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git 

for you to fetch changes up to d13864b68e41c11e4231de90cf358658f6ecea45:

  sparc64: Make atomic_xchg() an inline function rather than a macro. 
(2018-04-03 08:24:35 -0700)


David S. Miller (3):
  Merge branch 'sparc64-ADI'
  Merge git://git.kernel.org/.../davem/sparc
  sparc64: Make atomic_xchg() an inline function rather than a macro.

Guenter Roeck (1):
  sparc64: Oracle DAX driver depends on SPARC64

Khalid Aziz (12):
  signals, sparc: Add signal codes for ADI violations
  mm, swap: Add infrastructure for saving page metadata on swap
  sparc64: Add support for ADI register fields, ASIs and traps
  sparc64: Add HV fault type handlers for ADI related faults
  sparc64: Add handler for "Memory Corruption Detected" trap
  sparc64: Add auxiliary vectors to report platform ADI properties
  mm: Add address parameter to arch_validate_prot()
  mm: Clear arch specific VM flags on protection change
  mm: Allow arch code to override copy_highpage()
  sparc64: Add support for ADI (Application Data Integrity)
  sparc64: Update signal delivery to use new helper functions
  sparc: Make auxiliary vectors for ADI available on 32-bit as well

Rob Gardner (1):
  sparc64: Properly range check DAX completion index

 Documentation/sparc/adi.txt | 278 

 arch/powerpc/include/asm/mman.h |   4 +-
 arch/powerpc/kernel/syscalls.c  |   2 +-
 arch/sparc/include/asm/adi.h|   6 ++
 arch/sparc/include/asm/adi_64.h |  47 +
 arch/sparc/include/asm/atomic_64.h  |   6 +-
 arch/sparc/include/asm/elf_64.h |   5 ++
 arch/sparc/include/asm/hypervisor.h |   2 +
 arch/sparc/include/asm/mman.h   |  84 ++-
 arch/sparc/include/asm/mmu_64.h |  17 +
 arch/sparc/include/asm/mmu_context_64.h |  51 ++
 arch/sparc/include/asm/page_64.h|   6 ++
 arch/sparc/include/asm/pgtable_64.h |  48 ++
 arch/sparc/include/asm/thread_info_64.h |   2 +-
 arch/sparc/include/asm/trap_block.h |   2 +
 arch/sparc/include/asm/ttable.h |  10 +++
 arch/sparc/include/uapi/asm/asi.h   |   5 ++
 arch/sparc/include/uapi/asm/auxvec.h|   9 ++-
 arch/sparc/include/uapi/asm/mman.h  |   2 +
 arch/sparc/include/uapi/asm/pstate.h|  10 +++
 arch/sparc/kernel/Makefile  |   1 +
 arch/sparc/kernel/adi_64.c  | 397 
+
 arch/sparc/kernel/entry.h   |   3 +
 arch/sparc/kernel/etrap_64.S|  27 +++-
 arch/sparc/kernel/head_64.S |   1 +
 arch/sparc/kernel/mdesc.c   |   2 +
 arch/sparc/kernel/process_64.c  |  25 +++
 arch/sparc/kernel/rtrap_64.S|  33 -
 arch/sparc/kernel/setup_64.c|   2 +
 arch/sparc/kernel/sun4v_mcd.S   |  18 +
 arch/sparc/kernel/traps_64.c| 130 
++--
 arch/sparc/kernel/ttable_64.S   |   6 +-
 arch/sparc/kernel/urtt_fill.S   |   7 +-
 arch/sparc/kernel/vmlinux.lds.S |   5 ++
 arch/sparc/mm/gup.c |  37 +++
 arch/sparc/mm/hugetlbpage.c |  14 +++-
 arch/sparc/mm/init_64.c |  69 +++
 arch/sparc/mm/tsb.c |  21 ++
 arch/x86/kernel/signal_compat.c |   2 +-
 drivers/sbus/char/Kconfig   |   3 +-
 drivers/sbus/char/oradax.c  |   2 +-
 include/asm-generic/pgtable.h   |  36 ++
 include/linux/highmem.h |   4 ++
 include/linux/mm.h  |   9 +++
 include/linux/mman.h|   2 +-
 include/uapi/asm-generic/siginfo.h  |   5 +-
 mm/ksm.c|   4 ++
 mm/memory.c |   1 +
 mm/mprotect.c   |   4 +-
 mm/rmap.c   |  14 
 50 files changed, 1451 

[GIT] Sparc

2018-04-03 Thread David Miller

1) Add support for ADI (Application Data Integrity) found in more recent
   sparc64 cpus.  Essentially this is keyed based access to virtual memory,
   and if the key encoded in the virual address is wrong you get a trap.

   The mm changes were reviewed by Andrew Morton and others.

   Work by Khalid Aziz.

2) Validate DAX completion index range properly, from Rob Gardner.

3) Add proper Kconfig deps for DAX driver.  From Guenter Roeck.

Please pull, thanks a lot.

The following changes since commit 8f5fd927c3a7576d57248a2d7a0861c3f2795973:

  Merge tag 'for-4.16-rc5-tag' of 
git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux (2018-03-16 13:37:42 
-0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git 

for you to fetch changes up to d13864b68e41c11e4231de90cf358658f6ecea45:

  sparc64: Make atomic_xchg() an inline function rather than a macro. 
(2018-04-03 08:24:35 -0700)


David S. Miller (3):
  Merge branch 'sparc64-ADI'
  Merge git://git.kernel.org/.../davem/sparc
  sparc64: Make atomic_xchg() an inline function rather than a macro.

Guenter Roeck (1):
  sparc64: Oracle DAX driver depends on SPARC64

Khalid Aziz (12):
  signals, sparc: Add signal codes for ADI violations
  mm, swap: Add infrastructure for saving page metadata on swap
  sparc64: Add support for ADI register fields, ASIs and traps
  sparc64: Add HV fault type handlers for ADI related faults
  sparc64: Add handler for "Memory Corruption Detected" trap
  sparc64: Add auxiliary vectors to report platform ADI properties
  mm: Add address parameter to arch_validate_prot()
  mm: Clear arch specific VM flags on protection change
  mm: Allow arch code to override copy_highpage()
  sparc64: Add support for ADI (Application Data Integrity)
  sparc64: Update signal delivery to use new helper functions
  sparc: Make auxiliary vectors for ADI available on 32-bit as well

Rob Gardner (1):
  sparc64: Properly range check DAX completion index

 Documentation/sparc/adi.txt | 278 

 arch/powerpc/include/asm/mman.h |   4 +-
 arch/powerpc/kernel/syscalls.c  |   2 +-
 arch/sparc/include/asm/adi.h|   6 ++
 arch/sparc/include/asm/adi_64.h |  47 +
 arch/sparc/include/asm/atomic_64.h  |   6 +-
 arch/sparc/include/asm/elf_64.h |   5 ++
 arch/sparc/include/asm/hypervisor.h |   2 +
 arch/sparc/include/asm/mman.h   |  84 ++-
 arch/sparc/include/asm/mmu_64.h |  17 +
 arch/sparc/include/asm/mmu_context_64.h |  51 ++
 arch/sparc/include/asm/page_64.h|   6 ++
 arch/sparc/include/asm/pgtable_64.h |  48 ++
 arch/sparc/include/asm/thread_info_64.h |   2 +-
 arch/sparc/include/asm/trap_block.h |   2 +
 arch/sparc/include/asm/ttable.h |  10 +++
 arch/sparc/include/uapi/asm/asi.h   |   5 ++
 arch/sparc/include/uapi/asm/auxvec.h|   9 ++-
 arch/sparc/include/uapi/asm/mman.h  |   2 +
 arch/sparc/include/uapi/asm/pstate.h|  10 +++
 arch/sparc/kernel/Makefile  |   1 +
 arch/sparc/kernel/adi_64.c  | 397 
+
 arch/sparc/kernel/entry.h   |   3 +
 arch/sparc/kernel/etrap_64.S|  27 +++-
 arch/sparc/kernel/head_64.S |   1 +
 arch/sparc/kernel/mdesc.c   |   2 +
 arch/sparc/kernel/process_64.c  |  25 +++
 arch/sparc/kernel/rtrap_64.S|  33 -
 arch/sparc/kernel/setup_64.c|   2 +
 arch/sparc/kernel/sun4v_mcd.S   |  18 +
 arch/sparc/kernel/traps_64.c| 130 
++--
 arch/sparc/kernel/ttable_64.S   |   6 +-
 arch/sparc/kernel/urtt_fill.S   |   7 +-
 arch/sparc/kernel/vmlinux.lds.S |   5 ++
 arch/sparc/mm/gup.c |  37 +++
 arch/sparc/mm/hugetlbpage.c |  14 +++-
 arch/sparc/mm/init_64.c |  69 +++
 arch/sparc/mm/tsb.c |  21 ++
 arch/x86/kernel/signal_compat.c |   2 +-
 drivers/sbus/char/Kconfig   |   3 +-
 drivers/sbus/char/oradax.c  |   2 +-
 include/asm-generic/pgtable.h   |  36 ++
 include/linux/highmem.h |   4 ++
 include/linux/mm.h  |   9 +++
 include/linux/mman.h|   2 +-
 include/uapi/asm-generic/siginfo.h  |   5 +-
 mm/ksm.c|   4 ++
 mm/memory.c |   1 +
 mm/mprotect.c   |   4 +-
 mm/rmap.c   |  14 
 50 files changed, 1451 

Re: [PATCH v2 3/6] i2c: i2c-stm32f7: Add initial SMBus protocols support

2018-04-03 Thread Wolfram Sang

> >> All SMBus protocols are implemented except SMBus-specific protocols.
> > 
> > What does that mean?
> 
> It miss SMBus Host Notification and SMBBus Alert. They are almost ready but 
> I'm
> struggling to put them back to operational state after recent changes related 
> to
> SMBust Host Notification. A more "classic" interrupt base solution has been 
> put
> in place but I fail to use implement it in my side.
> Another patch set is going to be delivered for these 2 commands.

This is totally fine to implement it incrementally. Please just update the
commit message with the more detailed explanation above.

> > That is quite some complexity considering we have I2C_FUNC_SMBUS_EMUL. I
> > don't mind, but you really want that?
> > 
> 
> All SMBBus commands are implemented as such. I never try to emulation 
> commands.
> Should we use emulation SMBus commands or real commands... Don't know.

You won't see any difference on the wire. I don't know your HW. It might
be that SMBus mode is more "automatic" and uses less interrupts. Or
stuff like Alert or HostNotification only works in this mode. If you and
the driver maintainers think it is worth the added complexity, I am
fine, too.



signature.asc
Description: PGP signature


Re: [PATCH v2 3/6] i2c: i2c-stm32f7: Add initial SMBus protocols support

2018-04-03 Thread Wolfram Sang

> >> All SMBus protocols are implemented except SMBus-specific protocols.
> > 
> > What does that mean?
> 
> It miss SMBus Host Notification and SMBBus Alert. They are almost ready but 
> I'm
> struggling to put them back to operational state after recent changes related 
> to
> SMBust Host Notification. A more "classic" interrupt base solution has been 
> put
> in place but I fail to use implement it in my side.
> Another patch set is going to be delivered for these 2 commands.

This is totally fine to implement it incrementally. Please just update the
commit message with the more detailed explanation above.

> > That is quite some complexity considering we have I2C_FUNC_SMBUS_EMUL. I
> > don't mind, but you really want that?
> > 
> 
> All SMBBus commands are implemented as such. I never try to emulation 
> commands.
> Should we use emulation SMBus commands or real commands... Don't know.

You won't see any difference on the wire. I don't know your HW. It might
be that SMBus mode is more "automatic" and uses less interrupts. Or
stuff like Alert or HostNotification only works in this mode. If you and
the driver maintainers think it is worth the added complexity, I am
fine, too.



signature.asc
Description: PGP signature


[PATCH v2 1/6] spi: core: handle timeout error from transfer_one()

2018-04-03 Thread Sergey Suloev
As long as sun4i/sun6i SPI drivers have overriden the default
"wait for completion" procedure then we need to properly
handle -ETIMEDOUT error from transfer_one().

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b33a727..2dcd4f6 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1028,7 +1028,7 @@ static int spi_transfer_one_message(struct spi_controller 
*ctlr,
reinit_completion(>xfer_completion);
 
ret = ctlr->transfer_one(ctlr, msg->spi, xfer);
-   if (ret < 0) {
+   if (ret < 0 && ret != -ETIMEDOUT) {
SPI_STATISTICS_INCREMENT_FIELD(statm,
   errors);
SPI_STATISTICS_INCREMENT_FIELD(stats,
@@ -1051,7 +1051,7 @@ static int spi_transfer_one_message(struct spi_controller 
*ctlr,
 
msecs_to_jiffies(ms));
}
 
-   if (ms == 0) {
+   if (ms == 0 || ret == -ETIMEDOUT) {
SPI_STATISTICS_INCREMENT_FIELD(statm,
   timedout);
SPI_STATISTICS_INCREMENT_FIELD(stats,
@@ -1059,6 +1059,7 @@ static int spi_transfer_one_message(struct spi_controller 
*ctlr,
dev_err(>spi->dev,
"SPI transfer timed out\n");
msg->status = -ETIMEDOUT;
+   ret = 0;
}
} else {
if (xfer->len)
-- 
2.16.2



[PATCH v2 1/6] spi: core: handle timeout error from transfer_one()

2018-04-03 Thread Sergey Suloev
As long as sun4i/sun6i SPI drivers have overriden the default
"wait for completion" procedure then we need to properly
handle -ETIMEDOUT error from transfer_one().

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b33a727..2dcd4f6 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1028,7 +1028,7 @@ static int spi_transfer_one_message(struct spi_controller 
*ctlr,
reinit_completion(>xfer_completion);
 
ret = ctlr->transfer_one(ctlr, msg->spi, xfer);
-   if (ret < 0) {
+   if (ret < 0 && ret != -ETIMEDOUT) {
SPI_STATISTICS_INCREMENT_FIELD(statm,
   errors);
SPI_STATISTICS_INCREMENT_FIELD(stats,
@@ -1051,7 +1051,7 @@ static int spi_transfer_one_message(struct spi_controller 
*ctlr,
 
msecs_to_jiffies(ms));
}
 
-   if (ms == 0) {
+   if (ms == 0 || ret == -ETIMEDOUT) {
SPI_STATISTICS_INCREMENT_FIELD(statm,
   timedout);
SPI_STATISTICS_INCREMENT_FIELD(stats,
@@ -1059,6 +1059,7 @@ static int spi_transfer_one_message(struct spi_controller 
*ctlr,
dev_err(>spi->dev,
"SPI transfer timed out\n");
msg->status = -ETIMEDOUT;
+   ret = 0;
}
} else {
if (xfer->len)
-- 
2.16.2



[PATCH v2 3/6] spi: sun4i: coding style/readability improvements

2018-04-03 Thread Sergey Suloev
Minor changes to fulfill the coding style and
improve the readability.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 32 +---
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 08fd007..899e956 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -83,8 +83,11 @@
 #define SUN4I_FIFO_STA_TF_CNT_MASK 0x7f
 #define SUN4I_FIFO_STA_TF_CNT_BITS 16
 
+#define SUN4I_SPI_MAX_SPEED_HZ 100 * 1000 * 1000
+#define SUN4I_SPI_MIN_SPEED_HZ 3 * 1000
+#define SUN4I_SPI_MODE_BITS(SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | 
SPI_LSB_FIRST)
+
 struct sun4i_spi {
-   struct spi_master   *master;
void __iomem*base_addr;
struct clk  *hclk;
struct clk  *mclk;
@@ -418,12 +421,23 @@ static int sun4i_spi_probe(struct platform_device *pdev)
struct resource *res;
int ret = 0, irq;
 
-   master = spi_alloc_master(>dev, sizeof(struct sun4i_spi));
+   master = spi_alloc_master(>dev, sizeof(*sspi));
if (!master) {
dev_err(>dev, "Unable to allocate SPI Master\n");
return -ENOMEM;
}
 
+   master->max_speed_hz = SUN4I_SPI_MAX_SPEED_HZ;
+   master->min_speed_hz = SUN4I_SPI_MIN_SPEED_HZ;
+   master->num_chipselect = 4;
+   master->mode_bits = SUN4I_SPI_MODE_BITS;
+   master->bits_per_word_mask = SPI_BPW_MASK(8);
+   master->set_cs = sun4i_spi_set_cs;
+   master->transfer_one = sun4i_spi_transfer_one;
+   master->max_transfer_size = sun4i_spi_max_transfer_size;
+   master->dev.of_node = pdev->dev.of_node;
+   master->auto_runtime_pm = true;
+
platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master);
 
@@ -442,24 +456,12 @@ static int sun4i_spi_probe(struct platform_device *pdev)
}
 
ret = devm_request_irq(>dev, irq, sun4i_spi_handler,
-  0, "sun4i-spi", sspi);
+  0, dev_name(>dev), sspi);
if (ret) {
dev_err(>dev, "Cannot request IRQ\n");
goto err_free_master;
}
 
-   sspi->master = master;
-   master->max_speed_hz = 100 * 1000 * 1000;
-   master->min_speed_hz = 3 * 1000;
-   master->set_cs = sun4i_spi_set_cs;
-   master->transfer_one = sun4i_spi_transfer_one;
-   master->num_chipselect = 4;
-   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
-   master->bits_per_word_mask = SPI_BPW_MASK(8);
-   master->dev.of_node = pdev->dev.of_node;
-   master->auto_runtime_pm = true;
-   master->max_transfer_size = sun4i_spi_max_transfer_size;
-
sspi->hclk = devm_clk_get(>dev, "ahb");
if (IS_ERR(sspi->hclk)) {
dev_err(>dev, "Unable to acquire AHB clock\n");
-- 
2.16.2



[PATCH v2 3/6] spi: sun4i: coding style/readability improvements

2018-04-03 Thread Sergey Suloev
Minor changes to fulfill the coding style and
improve the readability.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 32 +---
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 08fd007..899e956 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -83,8 +83,11 @@
 #define SUN4I_FIFO_STA_TF_CNT_MASK 0x7f
 #define SUN4I_FIFO_STA_TF_CNT_BITS 16
 
+#define SUN4I_SPI_MAX_SPEED_HZ 100 * 1000 * 1000
+#define SUN4I_SPI_MIN_SPEED_HZ 3 * 1000
+#define SUN4I_SPI_MODE_BITS(SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | 
SPI_LSB_FIRST)
+
 struct sun4i_spi {
-   struct spi_master   *master;
void __iomem*base_addr;
struct clk  *hclk;
struct clk  *mclk;
@@ -418,12 +421,23 @@ static int sun4i_spi_probe(struct platform_device *pdev)
struct resource *res;
int ret = 0, irq;
 
-   master = spi_alloc_master(>dev, sizeof(struct sun4i_spi));
+   master = spi_alloc_master(>dev, sizeof(*sspi));
if (!master) {
dev_err(>dev, "Unable to allocate SPI Master\n");
return -ENOMEM;
}
 
+   master->max_speed_hz = SUN4I_SPI_MAX_SPEED_HZ;
+   master->min_speed_hz = SUN4I_SPI_MIN_SPEED_HZ;
+   master->num_chipselect = 4;
+   master->mode_bits = SUN4I_SPI_MODE_BITS;
+   master->bits_per_word_mask = SPI_BPW_MASK(8);
+   master->set_cs = sun4i_spi_set_cs;
+   master->transfer_one = sun4i_spi_transfer_one;
+   master->max_transfer_size = sun4i_spi_max_transfer_size;
+   master->dev.of_node = pdev->dev.of_node;
+   master->auto_runtime_pm = true;
+
platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master);
 
@@ -442,24 +456,12 @@ static int sun4i_spi_probe(struct platform_device *pdev)
}
 
ret = devm_request_irq(>dev, irq, sun4i_spi_handler,
-  0, "sun4i-spi", sspi);
+  0, dev_name(>dev), sspi);
if (ret) {
dev_err(>dev, "Cannot request IRQ\n");
goto err_free_master;
}
 
-   sspi->master = master;
-   master->max_speed_hz = 100 * 1000 * 1000;
-   master->min_speed_hz = 3 * 1000;
-   master->set_cs = sun4i_spi_set_cs;
-   master->transfer_one = sun4i_spi_transfer_one;
-   master->num_chipselect = 4;
-   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
-   master->bits_per_word_mask = SPI_BPW_MASK(8);
-   master->dev.of_node = pdev->dev.of_node;
-   master->auto_runtime_pm = true;
-   master->max_transfer_size = sun4i_spi_max_transfer_size;
-
sspi->hclk = devm_clk_get(>dev, "ahb");
if (IS_ERR(sspi->hclk)) {
dev_err(>dev, "Unable to acquire AHB clock\n");
-- 
2.16.2



[PATCH v2 4/6] spi: sun4i: use completion provided by SPI core driver

2018-04-03 Thread Sergey Suloev
As long as the completion already provided by the SPI core
then there is no need to waste extra-memory on this.
Also a waiting function was added to avoid code duplication.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 62 -
 1 file changed, 35 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 899e956..9d1bc20 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -92,8 +92,6 @@ struct sun4i_spi {
struct clk  *hclk;
struct clk  *mclk;
 
-   struct completion   done;
-
const u8*tx_buf;
u8  *rx_buf;
int len;
@@ -213,13 +211,36 @@ static size_t sun4i_spi_max_transfer_size(struct 
spi_device *spi)
return SUN4I_FIFO_DEPTH;
 }
 
+static int sun4i_spi_wait_for_transfer(struct spi_device *spi,
+  struct spi_transfer *tfr)
+{
+   struct spi_master *master = spi->master;
+   unsigned int start, end, tx_time;
+   unsigned int timeout;
+
+   /* calc required timeout from given speed & len values */
+   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+   start = jiffies;
+   timeout = wait_for_completion_timeout(>xfer_completion,
+ msecs_to_jiffies(tx_time));
+   end = jiffies;
+   if (!timeout) {
+   dev_warn(>dev,
+"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+dev_name(>dev), tfr->len, tfr->speed_hz,
+jiffies_to_msecs(end - start), tx_time);
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
+
 static int sun4i_spi_transfer_one(struct spi_master *master,
  struct spi_device *spi,
  struct spi_transfer *tfr)
 {
struct sun4i_spi *sspi = spi_master_get_devdata(master);
-   unsigned int mclk_rate, div, timeout;
-   unsigned int start, end, tx_time;
+   unsigned int mclk_rate, div;
unsigned int tx_len = 0;
int ret = 0;
u32 reg;
@@ -228,7 +249,6 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
if (tfr->len > SUN4I_FIFO_DEPTH)
return -EMSGSIZE;
 
-   reinit_completion(>done);
sspi->tx_buf = tfr->tx_buf;
sspi->rx_buf = tfr->rx_buf;
sspi->len = tfr->len;
@@ -329,22 +349,8 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
 
-   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
-   start = jiffies;
-   timeout = wait_for_completion_timeout(>done,
- msecs_to_jiffies(tx_time));
-   end = jiffies;
-   if (!timeout) {
-   dev_warn(>dev,
-"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
-dev_name(>dev), tfr->len, tfr->speed_hz,
-jiffies_to_msecs(end - start), tx_time);
-   ret = -ETIMEDOUT;
-   goto out;
-   }
-
+   ret = sun4i_spi_wait_for_transfer(spi, tfr);
 
-out:
sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
 
return ret;
@@ -352,14 +358,18 @@ out:
 
 static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
 {
-   struct sun4i_spi *sspi = dev_id;
-   u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
+   struct spi_master *master = dev_id;
+   struct sun4i_spi *sspi = spi_master_get_devdata(master);
+   u32 status;
+
+   status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
 
/* Transfer complete */
if (status & SUN4I_INT_CTL_TC) {
-   sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC);
+   sun4i_spi_write(sspi, SUN4I_INT_STA_REG,
+   SUN4I_INT_CTL_TC);
sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
-   complete(>done);
+   spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
@@ -456,7 +466,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
}
 
ret = devm_request_irq(>dev, irq, sun4i_spi_handler,
-  0, dev_name(>dev), sspi);
+  0, dev_name(>dev), master);
if (ret) {
dev_err(>dev, "Cannot request IRQ\n");
goto err_free_master;
@@ -476,8 +486,6 @@ static int sun4i_spi_probe(struct platform_device *pdev)
goto err_free_master;
}
 
-   init_completion(>done);
-
/*
 * This wake-up/shutdown pattern is to be able to have the
 * device woken up, even if 

[PATCH v2 4/6] spi: sun4i: use completion provided by SPI core driver

2018-04-03 Thread Sergey Suloev
As long as the completion already provided by the SPI core
then there is no need to waste extra-memory on this.
Also a waiting function was added to avoid code duplication.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 62 -
 1 file changed, 35 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 899e956..9d1bc20 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -92,8 +92,6 @@ struct sun4i_spi {
struct clk  *hclk;
struct clk  *mclk;
 
-   struct completion   done;
-
const u8*tx_buf;
u8  *rx_buf;
int len;
@@ -213,13 +211,36 @@ static size_t sun4i_spi_max_transfer_size(struct 
spi_device *spi)
return SUN4I_FIFO_DEPTH;
 }
 
+static int sun4i_spi_wait_for_transfer(struct spi_device *spi,
+  struct spi_transfer *tfr)
+{
+   struct spi_master *master = spi->master;
+   unsigned int start, end, tx_time;
+   unsigned int timeout;
+
+   /* calc required timeout from given speed & len values */
+   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+   start = jiffies;
+   timeout = wait_for_completion_timeout(>xfer_completion,
+ msecs_to_jiffies(tx_time));
+   end = jiffies;
+   if (!timeout) {
+   dev_warn(>dev,
+"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+dev_name(>dev), tfr->len, tfr->speed_hz,
+jiffies_to_msecs(end - start), tx_time);
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
+
 static int sun4i_spi_transfer_one(struct spi_master *master,
  struct spi_device *spi,
  struct spi_transfer *tfr)
 {
struct sun4i_spi *sspi = spi_master_get_devdata(master);
-   unsigned int mclk_rate, div, timeout;
-   unsigned int start, end, tx_time;
+   unsigned int mclk_rate, div;
unsigned int tx_len = 0;
int ret = 0;
u32 reg;
@@ -228,7 +249,6 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
if (tfr->len > SUN4I_FIFO_DEPTH)
return -EMSGSIZE;
 
-   reinit_completion(>done);
sspi->tx_buf = tfr->tx_buf;
sspi->rx_buf = tfr->rx_buf;
sspi->len = tfr->len;
@@ -329,22 +349,8 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
 
-   tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
-   start = jiffies;
-   timeout = wait_for_completion_timeout(>done,
- msecs_to_jiffies(tx_time));
-   end = jiffies;
-   if (!timeout) {
-   dev_warn(>dev,
-"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
-dev_name(>dev), tfr->len, tfr->speed_hz,
-jiffies_to_msecs(end - start), tx_time);
-   ret = -ETIMEDOUT;
-   goto out;
-   }
-
+   ret = sun4i_spi_wait_for_transfer(spi, tfr);
 
-out:
sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
 
return ret;
@@ -352,14 +358,18 @@ out:
 
 static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
 {
-   struct sun4i_spi *sspi = dev_id;
-   u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
+   struct spi_master *master = dev_id;
+   struct sun4i_spi *sspi = spi_master_get_devdata(master);
+   u32 status;
+
+   status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
 
/* Transfer complete */
if (status & SUN4I_INT_CTL_TC) {
-   sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC);
+   sun4i_spi_write(sspi, SUN4I_INT_STA_REG,
+   SUN4I_INT_CTL_TC);
sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
-   complete(>done);
+   spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
@@ -456,7 +466,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
}
 
ret = devm_request_irq(>dev, irq, sun4i_spi_handler,
-  0, dev_name(>dev), sspi);
+  0, dev_name(>dev), master);
if (ret) {
dev_err(>dev, "Cannot request IRQ\n");
goto err_free_master;
@@ -476,8 +486,6 @@ static int sun4i_spi_probe(struct platform_device *pdev)
goto err_free_master;
}
 
-   init_completion(>done);
-
/*
 * This wake-up/shutdown pattern is to be able to have the
 * device woken up, even if runtime_pm is disabled
-- 

[PATCH v2 5/6] spi: sun4i: introduce register set/unset helpers

2018-04-03 Thread Sergey Suloev
Two helper functions were added in order to set/unset
specified flags in registers.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 40 +++-
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 9d1bc20..d81d31c 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -107,29 +107,29 @@ static inline void sun4i_spi_write(struct sun4i_spi 
*sspi, u32 reg, u32 value)
writel(value, sspi->base_addr + reg);
 }
 
-static inline u32 sun4i_spi_get_tx_fifo_count(struct sun4i_spi *sspi)
+static inline void sun4i_spi_set(struct sun4i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
-
-   reg >>= SUN4I_FIFO_STA_TF_CNT_BITS;
+   u32 reg = sun4i_spi_read(sspi, addr);
 
-   return reg & SUN4I_FIFO_STA_TF_CNT_MASK;
+   reg |= val;
+   sun4i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun4i_spi_enable_interrupt(struct sun4i_spi *sspi, u32 mask)
+static inline void sun4i_spi_unset(struct sun4i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG);
+   u32 reg = sun4i_spi_read(sspi, addr);
 
-   reg |= mask;
-   sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg);
+   reg &= ~val;
+   sun4i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun4i_spi_disable_interrupt(struct sun4i_spi *sspi, u32 
mask)
+static inline u32 sun4i_spi_get_tx_fifo_count(struct sun4i_spi *sspi)
 {
-   u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG);
+   u32 reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
 
-   reg &= ~mask;
-   sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg);
+   reg >>= SUN4I_FIFO_STA_TF_CNT_BITS;
+
+   return reg & SUN4I_FIFO_STA_TF_CNT_MASK;
 }
 
 static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
@@ -256,13 +256,12 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
/* Clear pending interrupts */
sun4i_spi_write(sspi, SUN4I_INT_STA_REG, ~0);
 
+   /* Reset FIFOs */
+   sun4i_spi_set(sspi, SUN4I_CTL_REG,
+ SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
 
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
 
-   /* Reset FIFOs */
-   sun4i_spi_write(sspi, SUN4I_CTL_REG,
-   reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
-
/*
 * Setup the transfer control register: Chip Select,
 * polarities, etc.
@@ -342,12 +341,11 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
 
/* Enable the interrupts */
-   sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TC |
-SUN4I_INT_CTL_RF_F34);
+   sun4i_spi_set(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC |
+  SUN4I_INT_CTL_RF_F34);
 
/* Start the transfer */
-   reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
-   sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
+   sun4i_spi_set(sspi, SUN4I_CTL_REG, SUN4I_CTL_XCH);
 
ret = sun4i_spi_wait_for_transfer(spi, tfr);
 
-- 
2.16.2



[PATCH v2 5/6] spi: sun4i: introduce register set/unset helpers

2018-04-03 Thread Sergey Suloev
Two helper functions were added in order to set/unset
specified flags in registers.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 40 +++-
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 9d1bc20..d81d31c 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -107,29 +107,29 @@ static inline void sun4i_spi_write(struct sun4i_spi 
*sspi, u32 reg, u32 value)
writel(value, sspi->base_addr + reg);
 }
 
-static inline u32 sun4i_spi_get_tx_fifo_count(struct sun4i_spi *sspi)
+static inline void sun4i_spi_set(struct sun4i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
-
-   reg >>= SUN4I_FIFO_STA_TF_CNT_BITS;
+   u32 reg = sun4i_spi_read(sspi, addr);
 
-   return reg & SUN4I_FIFO_STA_TF_CNT_MASK;
+   reg |= val;
+   sun4i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun4i_spi_enable_interrupt(struct sun4i_spi *sspi, u32 mask)
+static inline void sun4i_spi_unset(struct sun4i_spi *sspi, u32 addr, u32 val)
 {
-   u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG);
+   u32 reg = sun4i_spi_read(sspi, addr);
 
-   reg |= mask;
-   sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg);
+   reg &= ~val;
+   sun4i_spi_write(sspi, addr, reg);
 }
 
-static inline void sun4i_spi_disable_interrupt(struct sun4i_spi *sspi, u32 
mask)
+static inline u32 sun4i_spi_get_tx_fifo_count(struct sun4i_spi *sspi)
 {
-   u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG);
+   u32 reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
 
-   reg &= ~mask;
-   sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg);
+   reg >>= SUN4I_FIFO_STA_TF_CNT_BITS;
+
+   return reg & SUN4I_FIFO_STA_TF_CNT_MASK;
 }
 
 static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
@@ -256,13 +256,12 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
/* Clear pending interrupts */
sun4i_spi_write(sspi, SUN4I_INT_STA_REG, ~0);
 
+   /* Reset FIFOs */
+   sun4i_spi_set(sspi, SUN4I_CTL_REG,
+ SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
 
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
 
-   /* Reset FIFOs */
-   sun4i_spi_write(sspi, SUN4I_CTL_REG,
-   reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
-
/*
 * Setup the transfer control register: Chip Select,
 * polarities, etc.
@@ -342,12 +341,11 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
 
/* Enable the interrupts */
-   sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TC |
-SUN4I_INT_CTL_RF_F34);
+   sun4i_spi_set(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC |
+  SUN4I_INT_CTL_RF_F34);
 
/* Start the transfer */
-   reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
-   sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
+   sun4i_spi_set(sspi, SUN4I_CTL_REG, SUN4I_CTL_XCH);
 
ret = sun4i_spi_wait_for_transfer(spi, tfr);
 
-- 
2.16.2



[PATCH v2 6/6] spi: sun4i: add DMA transfers support

2018-04-03 Thread Sergey Suloev
DMA transfers are now available for sun4i-family SoCs.
The DMA mode is used automatically as soon as requested
transfer length is more than FIFO length.

Changes in v2:
1) Debug log enhancements.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 299 
 1 file changed, 277 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index d81d31c..dda7922 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -39,6 +41,7 @@
 #define SUN4I_CTL_CPHA BIT(2)
 #define SUN4I_CTL_CPOL BIT(3)
 #define SUN4I_CTL_CS_ACTIVE_LOWBIT(4)
+#define SUN4I_CTL_DMA_DEDICATEDBIT(5)
 #define SUN4I_CTL_LMTF BIT(6)
 #define SUN4I_CTL_TF_RST   BIT(8)
 #define SUN4I_CTL_RF_RST   BIT(9)
@@ -58,6 +61,8 @@
 #define SUN4I_INT_STA_REG  0x10
 
 #define SUN4I_DMA_CTL_REG  0x14
+#define SUN4I_CTL_DMA_RF_READY BIT(0)
+#define SUN4I_CTL_DMA_TF_NOT_FULL  BIT(10)
 
 #define SUN4I_WAIT_REG 0x18
 
@@ -169,6 +174,13 @@ static inline void sun4i_spi_fill_fifo(struct sun4i_spi 
*sspi, int len)
}
 }
 
+static bool sun4i_spi_can_dma(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+   return tfr->len > SUN4I_FIFO_DEPTH;
+}
+
 static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
 {
struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
@@ -208,6 +220,11 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
 {
+   struct spi_master *master = spi->master;
+
+   if (master->can_dma)
+   return SUN4I_MAX_XFER_SIZE;
+
return SUN4I_FIFO_DEPTH;
 }
 
@@ -235,6 +252,164 @@ static int sun4i_spi_wait_for_transfer(struct spi_device 
*spi,
return 0;
 }
 
+static void sun4i_spi_dma_callback(void *param)
+{
+   struct spi_master *master = param;
+
+   dev_dbg(>dev, "DMA transfer complete\n");
+   spi_finalize_current_transfer(master);
+}
+
+static int sun4i_spi_dmap_prep_tx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_tx,
+   tfr->tx_sg.sgl, tfr->tx_sg.nents,
+   DMA_TO_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!chan_desc) {
+   dev_err(>dev,
+   "Couldn't prepare TX DMA slave\n");
+   return -EIO;
+   }
+
+   chan_desc->callback = sun4i_spi_dma_callback;
+   chan_desc->callback_param = master;
+
+   *cookie = dmaengine_submit(chan_desc);
+   dma_async_issue_pending(master->dma_tx);
+
+   return 0;
+}
+
+static int sun4i_spi_dmap_prep_rx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_rx,
+   tfr->rx_sg.sgl, tfr->rx_sg.nents,
+   DMA_FROM_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!chan_desc) {
+   dev_err(>dev,
+   "Couldn't prepare RX DMA slave\n");
+   return -EIO;
+   }
+
+   chan_desc->callback = sun4i_spi_dma_callback;
+   chan_desc->callback_param = master;
+
+   *cookie = dmaengine_submit(chan_desc);
+   dma_async_issue_pending(master->dma_rx);
+
+   return 0;
+}
+
+static int sun4i_spi_transfer_one_dma(struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+   struct spi_master *master = spi->master;
+   struct sun4i_spi *sspi = spi_master_get_devdata(master);
+   dma_cookie_t tx_cookie = 0, rx_cookie = 0;
+   enum dma_status status;
+   int ret;
+   u32 reg = 0;
+
+   dev_dbg(>dev, "Using DMA mode for transfer\n");
+
+   /* Disable interrupts */
+   sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
+
+   if (sspi->tx_buf) {
+   ret = sun4i_spi_dmap_prep_tx(master, tfr, _cookie);
+   if (ret)
+   goto out;
+
+   reg |= SUN4I_CTL_DMA_TF_NOT_FULL;
+   }
+
+   if (sspi->rx_buf) {
+

[PATCH v2 6/6] spi: sun4i: add DMA transfers support

2018-04-03 Thread Sergey Suloev
DMA transfers are now available for sun4i-family SoCs.
The DMA mode is used automatically as soon as requested
transfer length is more than FIFO length.

Changes in v2:
1) Debug log enhancements.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 299 
 1 file changed, 277 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index d81d31c..dda7922 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -39,6 +41,7 @@
 #define SUN4I_CTL_CPHA BIT(2)
 #define SUN4I_CTL_CPOL BIT(3)
 #define SUN4I_CTL_CS_ACTIVE_LOWBIT(4)
+#define SUN4I_CTL_DMA_DEDICATEDBIT(5)
 #define SUN4I_CTL_LMTF BIT(6)
 #define SUN4I_CTL_TF_RST   BIT(8)
 #define SUN4I_CTL_RF_RST   BIT(9)
@@ -58,6 +61,8 @@
 #define SUN4I_INT_STA_REG  0x10
 
 #define SUN4I_DMA_CTL_REG  0x14
+#define SUN4I_CTL_DMA_RF_READY BIT(0)
+#define SUN4I_CTL_DMA_TF_NOT_FULL  BIT(10)
 
 #define SUN4I_WAIT_REG 0x18
 
@@ -169,6 +174,13 @@ static inline void sun4i_spi_fill_fifo(struct sun4i_spi 
*sspi, int len)
}
 }
 
+static bool sun4i_spi_can_dma(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+   return tfr->len > SUN4I_FIFO_DEPTH;
+}
+
 static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
 {
struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
@@ -208,6 +220,11 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
 {
+   struct spi_master *master = spi->master;
+
+   if (master->can_dma)
+   return SUN4I_MAX_XFER_SIZE;
+
return SUN4I_FIFO_DEPTH;
 }
 
@@ -235,6 +252,164 @@ static int sun4i_spi_wait_for_transfer(struct spi_device 
*spi,
return 0;
 }
 
+static void sun4i_spi_dma_callback(void *param)
+{
+   struct spi_master *master = param;
+
+   dev_dbg(>dev, "DMA transfer complete\n");
+   spi_finalize_current_transfer(master);
+}
+
+static int sun4i_spi_dmap_prep_tx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_tx,
+   tfr->tx_sg.sgl, tfr->tx_sg.nents,
+   DMA_TO_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!chan_desc) {
+   dev_err(>dev,
+   "Couldn't prepare TX DMA slave\n");
+   return -EIO;
+   }
+
+   chan_desc->callback = sun4i_spi_dma_callback;
+   chan_desc->callback_param = master;
+
+   *cookie = dmaengine_submit(chan_desc);
+   dma_async_issue_pending(master->dma_tx);
+
+   return 0;
+}
+
+static int sun4i_spi_dmap_prep_rx(struct spi_master *master,
+ struct spi_transfer *tfr,
+ dma_cookie_t *cookie)
+{
+   struct dma_async_tx_descriptor *chan_desc = NULL;
+
+   chan_desc = dmaengine_prep_slave_sg(master->dma_rx,
+   tfr->rx_sg.sgl, tfr->rx_sg.nents,
+   DMA_FROM_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!chan_desc) {
+   dev_err(>dev,
+   "Couldn't prepare RX DMA slave\n");
+   return -EIO;
+   }
+
+   chan_desc->callback = sun4i_spi_dma_callback;
+   chan_desc->callback_param = master;
+
+   *cookie = dmaengine_submit(chan_desc);
+   dma_async_issue_pending(master->dma_rx);
+
+   return 0;
+}
+
+static int sun4i_spi_transfer_one_dma(struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+   struct spi_master *master = spi->master;
+   struct sun4i_spi *sspi = spi_master_get_devdata(master);
+   dma_cookie_t tx_cookie = 0, rx_cookie = 0;
+   enum dma_status status;
+   int ret;
+   u32 reg = 0;
+
+   dev_dbg(>dev, "Using DMA mode for transfer\n");
+
+   /* Disable interrupts */
+   sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
+
+   if (sspi->tx_buf) {
+   ret = sun4i_spi_dmap_prep_tx(master, tfr, _cookie);
+   if (ret)
+   goto out;
+
+   reg |= SUN4I_CTL_DMA_TF_NOT_FULL;
+   }
+
+   if (sspi->rx_buf) {
+   ret = 

[PATCH v2 0/6] spi: Add support for DMA transfers in sun4i SPI driver

2018-04-03 Thread Sergey Suloev
The following patchset provides corrections for PIO-mode
and support for DMA transfers in sun4i SPI driver.

Changes in v2:
1) Restored processing of 3/4 FIFO full interrupt.

2) Debug log enhancements.

Sergey Suloev (6):
  spi: core: handle timeout error from transfer_one()
  spi: sun4i: restrict transfer length in PIO-mode
  spi: sun4i: coding style/readability improvements
  spi: sun4i: use completion provided by SPI core driver
  spi: sun4i: introduce register set/unset helpers
  spi: sun4i: add DMA transfers support

 drivers/spi/spi-sun4i.c | 442 +---
 drivers/spi/spi.c   |   5 +-
 2 files changed, 347 insertions(+), 100 deletions(-)

-- 
2.16.2



[PATCH v2 2/6] spi: sun4i: restrict transfer length in PIO-mode

2018-04-03 Thread Sergey Suloev
There is no need to handle the 3/4 FIFO empty interrupt
as the maximum supported transfer length in PIO mode
is 64 bytes.
As long as a problem was reported previously with filling FIFO
on A10s we want to stick with 63 bytes depth.

Changes in v2:
1) Restored processing of 3/4 FIFO full interrupt.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 37 ++---
 1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 4141003..08fd007 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -22,7 +22,12 @@
 
 #include 
 
-#define SUN4I_FIFO_DEPTH   64
+/*
+ * FIFO length is 64 bytes
+ * But filling the FIFO fully might cause a timeout
+ * on some devices, for example on spi2 on A10s
+ */
+#define SUN4I_FIFO_DEPTH   63
 
 #define SUN4I_RXDATA_REG   0x00
 
@@ -202,7 +207,7 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
 {
-   return SUN4I_FIFO_DEPTH - 1;
+   return SUN4I_FIFO_DEPTH;
 }
 
 static int sun4i_spi_transfer_one(struct spi_master *master,
@@ -216,11 +221,8 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
int ret = 0;
u32 reg;
 
-   /* We don't support transfer larger than the FIFO */
-   if (tfr->len > SUN4I_MAX_XFER_SIZE)
-   return -EMSGSIZE;
-
-   if (tfr->tx_buf && tfr->len >= SUN4I_MAX_XFER_SIZE)
+   /* We don't support transfers larger than FIFO depth */
+   if (tfr->len > SUN4I_FIFO_DEPTH)
return -EMSGSIZE;
 
reinit_completion(>done);
@@ -313,17 +315,12 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
 
/*
 * Fill the TX FIFO
-* Filling the FIFO fully causes timeout for some reason
-* at least on spi2 on A10s
 */
-   sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
+   sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
 
/* Enable the interrupts */
sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TC |
 SUN4I_INT_CTL_RF_F34);
-   /* Only enable Tx FIFO interrupt if we really need it */
-   if (tx_len > SUN4I_FIFO_DEPTH)
-   sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TF_E34);
 
/* Start the transfer */
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
@@ -371,20 +368,6 @@ static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
 
-   /* Transmit FIFO 3/4 empty */
-   if (status & SUN4I_INT_CTL_TF_E34) {
-   sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
-
-   if (!sspi->len)
-   /* nothing left to transmit */
-   sun4i_spi_disable_interrupt(sspi, SUN4I_INT_CTL_TF_E34);
-
-   /* Only clear the interrupt _after_ re-seeding the FIFO */
-   sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TF_E34);
-
-   return IRQ_HANDLED;
-   }
-
return IRQ_NONE;
 }
 
-- 
2.16.2



[PATCH v2 0/6] spi: Add support for DMA transfers in sun4i SPI driver

2018-04-03 Thread Sergey Suloev
The following patchset provides corrections for PIO-mode
and support for DMA transfers in sun4i SPI driver.

Changes in v2:
1) Restored processing of 3/4 FIFO full interrupt.

2) Debug log enhancements.

Sergey Suloev (6):
  spi: core: handle timeout error from transfer_one()
  spi: sun4i: restrict transfer length in PIO-mode
  spi: sun4i: coding style/readability improvements
  spi: sun4i: use completion provided by SPI core driver
  spi: sun4i: introduce register set/unset helpers
  spi: sun4i: add DMA transfers support

 drivers/spi/spi-sun4i.c | 442 +---
 drivers/spi/spi.c   |   5 +-
 2 files changed, 347 insertions(+), 100 deletions(-)

-- 
2.16.2



[PATCH v2 2/6] spi: sun4i: restrict transfer length in PIO-mode

2018-04-03 Thread Sergey Suloev
There is no need to handle the 3/4 FIFO empty interrupt
as the maximum supported transfer length in PIO mode
is 64 bytes.
As long as a problem was reported previously with filling FIFO
on A10s we want to stick with 63 bytes depth.

Changes in v2:
1) Restored processing of 3/4 FIFO full interrupt.

Signed-off-by: Sergey Suloev 
---
 drivers/spi/spi-sun4i.c | 37 ++---
 1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 4141003..08fd007 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -22,7 +22,12 @@
 
 #include 
 
-#define SUN4I_FIFO_DEPTH   64
+/*
+ * FIFO length is 64 bytes
+ * But filling the FIFO fully might cause a timeout
+ * on some devices, for example on spi2 on A10s
+ */
+#define SUN4I_FIFO_DEPTH   63
 
 #define SUN4I_RXDATA_REG   0x00
 
@@ -202,7 +207,7 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
 {
-   return SUN4I_FIFO_DEPTH - 1;
+   return SUN4I_FIFO_DEPTH;
 }
 
 static int sun4i_spi_transfer_one(struct spi_master *master,
@@ -216,11 +221,8 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
int ret = 0;
u32 reg;
 
-   /* We don't support transfer larger than the FIFO */
-   if (tfr->len > SUN4I_MAX_XFER_SIZE)
-   return -EMSGSIZE;
-
-   if (tfr->tx_buf && tfr->len >= SUN4I_MAX_XFER_SIZE)
+   /* We don't support transfers larger than FIFO depth */
+   if (tfr->len > SUN4I_FIFO_DEPTH)
return -EMSGSIZE;
 
reinit_completion(>done);
@@ -313,17 +315,12 @@ static int sun4i_spi_transfer_one(struct spi_master 
*master,
 
/*
 * Fill the TX FIFO
-* Filling the FIFO fully causes timeout for some reason
-* at least on spi2 on A10s
 */
-   sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
+   sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
 
/* Enable the interrupts */
sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TC |
 SUN4I_INT_CTL_RF_F34);
-   /* Only enable Tx FIFO interrupt if we really need it */
-   if (tx_len > SUN4I_FIFO_DEPTH)
-   sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TF_E34);
 
/* Start the transfer */
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
@@ -371,20 +368,6 @@ static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
 
-   /* Transmit FIFO 3/4 empty */
-   if (status & SUN4I_INT_CTL_TF_E34) {
-   sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
-
-   if (!sspi->len)
-   /* nothing left to transmit */
-   sun4i_spi_disable_interrupt(sspi, SUN4I_INT_CTL_TF_E34);
-
-   /* Only clear the interrupt _after_ re-seeding the FIFO */
-   sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TF_E34);
-
-   return IRQ_HANDLED;
-   }
-
return IRQ_NONE;
 }
 
-- 
2.16.2



Re: [PATCH v2 2/6] i2c: i2c-stm32f7: Add slave support

2018-04-03 Thread Wolfram Sang
On Mon, Mar 26, 2018 at 10:41:51AM +0200, Pierre Yves MORDRET wrote:
> 
> 
> On 03/25/2018 08:16 PM, Wolfram Sang wrote:
> > On Wed, Mar 21, 2018 at 05:48:56PM +0100, Pierre-Yves MORDRET wrote:
> >> This patch adds slave support for I2C controller embedded in STM32F7 SoC
> >>
> >> Signed-off-by: M'boumba Cedric Madianga 
> >> Signed-off-by: Pierre-Yves MORDRET 
> > 
> > Looks OK from a first look. What kind of tests did you do?
> 
> As mentioned for 10-bit, I'm using 2 I2C instances from the SoC.
> Here are the tests I dit:
>  - Master/slave send in 7 and 10 bits
>  - master/slave recv in 7 and 10 bits
>  - E2PROM Read/Write

As far as I understand the code now, both instances can be master /
slave simultanously on the same bus?



signature.asc
Description: PGP signature


Re: [PATCH v2 2/6] i2c: i2c-stm32f7: Add slave support

2018-04-03 Thread Wolfram Sang
On Mon, Mar 26, 2018 at 10:41:51AM +0200, Pierre Yves MORDRET wrote:
> 
> 
> On 03/25/2018 08:16 PM, Wolfram Sang wrote:
> > On Wed, Mar 21, 2018 at 05:48:56PM +0100, Pierre-Yves MORDRET wrote:
> >> This patch adds slave support for I2C controller embedded in STM32F7 SoC
> >>
> >> Signed-off-by: M'boumba Cedric Madianga 
> >> Signed-off-by: Pierre-Yves MORDRET 
> > 
> > Looks OK from a first look. What kind of tests did you do?
> 
> As mentioned for 10-bit, I'm using 2 I2C instances from the SoC.
> Here are the tests I dit:
>  - Master/slave send in 7 and 10 bits
>  - master/slave recv in 7 and 10 bits
>  - E2PROM Read/Write

As far as I understand the code now, both instances can be master /
slave simultanously on the same bus?



signature.asc
Description: PGP signature


Re: [GIT PULL] siginfo fix for v4.16-rc5

2018-04-03 Thread Josh Juran
On Apr 3, 2018, at 10:27 AM, Eric W. Biederman  wrote:

> Geert Uytterhoeven  writes:
> 
>> On Mon, Apr 2, 2018 at 10:17 PM, Eric W. Biederman  
>> wrote:
>> 
>>> A 2-byte alignment for 4 byte pointers.  That is a new one to me.
>> 
>> Not just for pointers, also for int and long.
> 
> The smallest I have seen previously has been 64bit integers having
> 32bit alignment.  32bit entities having only 16bit alignment on a 32bit
> arch was simply a surprise.  Even when it works there tend to be good
> reasons not to do that by default.

The 68K architecture began as 16-bit with the 68000.  Rather than tightening 
requirements, the 68020 not only maintained compatibility with 16-bit 
alignment, but also forgave byte-misaligned data accesses (albeit with a 
performance penalty).  Jumping to an odd address is still an error, though.

Josh



Re: [GIT PULL] siginfo fix for v4.16-rc5

2018-04-03 Thread Josh Juran
On Apr 3, 2018, at 10:27 AM, Eric W. Biederman  wrote:

> Geert Uytterhoeven  writes:
> 
>> On Mon, Apr 2, 2018 at 10:17 PM, Eric W. Biederman  
>> wrote:
>> 
>>> A 2-byte alignment for 4 byte pointers.  That is a new one to me.
>> 
>> Not just for pointers, also for int and long.
> 
> The smallest I have seen previously has been 64bit integers having
> 32bit alignment.  32bit entities having only 16bit alignment on a 32bit
> arch was simply a surprise.  Even when it works there tend to be good
> reasons not to do that by default.

The 68K architecture began as 16-bit with the 68000.  Rather than tightening 
requirements, the 68020 not only maintained compatibility with 16-bit 
alignment, but also forgave byte-misaligned data accesses (albeit with a 
performance penalty).  Jumping to an odd address is still an error, though.

Josh



Re: [PATCH] locking/hung_task: Show all hung tasks before panic

2018-04-03 Thread Dmitry Vyukov
On Mon, Apr 2, 2018 at 5:35 PM, Paul E. McKenney
 wrote:
> On Mon, Apr 02, 2018 at 11:12:04PM +0900, Tetsuo Handa wrote:
>> When we get a hung task it can often be valuable to see _all_ the hung
>> tasks on the system before calling panic().
>>
>> Quoting from 
>> https://syzkaller.appspot.com/text?tag=CrashReport=5412451675799552
>> 
>> INFO: task syz-executor3:13421 blocked for more than 120 seconds.
>>   Not tainted 4.16.0-rc7+ #9
>> "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
>> syz-executor3   D24672 13421   4481 0x0004
>> Call Trace:
>>  context_switch kernel/sched/core.c:2862 [inline]
>>  __schedule+0x8fb/0x1ec0 kernel/sched/core.c:3440
>>  schedule+0xf5/0x430 kernel/sched/core.c:3499
>>  __rwsem_down_read_failed_common kernel/locking/rwsem-xadd.c:269 [inline]
>>  rwsem_down_read_failed+0x401/0x6e0 kernel/locking/rwsem-xadd.c:286
>>  call_rwsem_down_read_failed+0x18/0x30 arch/x86/lib/rwsem.S:94
>>  __down_read arch/x86/include/asm/rwsem.h:83 [inline]
>>  down_read+0xa4/0x150 kernel/locking/rwsem.c:26
>>  __get_super.part.9+0x1d3/0x280 fs/super.c:663
>>  __get_super include/linux/spinlock.h:310 [inline]
>>  get_super+0x2d/0x40 fs/super.c:692
>>  fsync_bdev+0x19/0x80 fs/block_dev.c:468
>>  invalidate_partition+0x35/0x60 block/genhd.c:1566
>>  drop_partitions.isra.12+0xcd/0x1d0 block/partition-generic.c:440
>>  rescan_partitions+0x72/0x900 block/partition-generic.c:513
>>  __blkdev_reread_part+0x15f/0x1e0 block/ioctl.c:173
>>  blkdev_reread_part+0x26/0x40 block/ioctl.c:193
>>  loop_reread_partitions+0x12f/0x1a0 drivers/block/loop.c:619
>>  loop_set_status+0x9bb/0xf60 drivers/block/loop.c:1161
>>  loop_set_status64+0x9d/0x110 drivers/block/loop.c:1271
>>  lo_ioctl+0xd86/0x1b70 drivers/block/loop.c:1381
>> (...snipped...)
>> Showing all locks held in the system:
>> (...snipped...)
>> 3 locks held by syz-executor3/13421:
>>  #0:  (>lo_ctl_mutex/1){+.+.}, at: [<834f78af>] 
>> lo_ioctl+0x8b/0x1b70 drivers/block/loop.c:1355 /* 
>> mutex_lock_nested(>lo_ctl_mutex, 1); */
>>  #1:  (>bd_mutex){+.+.}, at: [<03605603>] 
>> blkdev_reread_part+0x1e/0x40 block/ioctl.c:192
>>  #2:  (>s_umount_key#77){.+.+}, at: [<77701649>] 
>> __get_super.part.9+0x1d3/0x280 fs/super.c:663 /* down_read(>s_umount); */
>> (...snipped...)
>> 2 locks held by syz-executor0/13428:
>>  #0:  (>s_umount_key#76/1){+.+.}, at: [] alloc_super 
>> fs/super.c:211 [inline]
>>  #0:  (>s_umount_key#76/1){+.+.}, at: [] 
>> sget_userns+0x3a1/0xe40 fs/super.c:502 /* down_write_nested(>s_umount, 
>> SINGLE_DEPTH_NESTING); */
>>  #1:  (>lo_ctl_mutex/1){+.+.}, at: [<834f78af>] 
>> lo_ioctl+0x8b/0x1b70 drivers/block/loop.c:1355 /* 
>> mutex_lock_nested(>lo_ctl_mutex, 1); */
>> 
>>
>> In addition to showing hashed address of lock instances, it would be
>> nice if trace of 13428 is printed as well as 13421.
>>
>> Showing hung tasks up to /proc/sys/kernel/hung_task_warnings could delay
>> calling panic() but normally there should not be so many hung tasks.
>>
>> Signed-off-by: Tetsuo Handa 
>> Cc: Vegard Nossum 
>> Cc: Andrew Morton 
>> Cc: Linus Torvalds 
>> Cc: Mandeep Singh Baines 
>> Cc: Paul E. McKenney 
>
> I just know that I am going to regret this the first time this happens
> on a low-speed console port, but...
>
> Acked-by: Paul E. McKenney 


Thanks! I think getting these last bits of debugging tools to be more
useful is very important in the context of syzbot. So:

Acked-by: Dmitry Vyukov 




>> Cc: Peter Zijlstra 
>> Cc: Thomas Gleixner 
>> Cc: Ingo Molnar 
>> ---
>>  kernel/hung_task.c | 11 +++
>>  1 file changed, 7 insertions(+), 4 deletions(-)
>>
>> diff --git a/kernel/hung_task.c b/kernel/hung_task.c
>> index 751593e..32b4794 100644
>> --- a/kernel/hung_task.c
>> +++ b/kernel/hung_task.c
>> @@ -44,6 +44,7 @@
>>
>>  static int __read_mostly did_panic;
>>  static bool hung_task_show_lock;
>> +static bool hung_task_call_panic;
>>
>>  static struct task_struct *watchdog_task;
>>
>> @@ -127,10 +128,8 @@ static void check_hung_task(struct task_struct *t, 
>> unsigned long timeout)
>>   touch_nmi_watchdog();
>>
>>   if (sysctl_hung_task_panic) {
>> - if (hung_task_show_lock)
>> - debug_show_all_locks();
>> - trigger_all_cpu_backtrace();
>> - panic("hung_task: blocked tasks");
>> + hung_task_show_lock = true;
>> + hung_task_call_panic = true;
>>   }
>>  }
>>
>> @@ -193,6 +192,10 @@ static void check_hung_uninterruptible_tasks(unsigned 
>> long timeout)
>>   

Re: [PATCH] locking/hung_task: Show all hung tasks before panic

2018-04-03 Thread Dmitry Vyukov
On Mon, Apr 2, 2018 at 5:35 PM, Paul E. McKenney
 wrote:
> On Mon, Apr 02, 2018 at 11:12:04PM +0900, Tetsuo Handa wrote:
>> When we get a hung task it can often be valuable to see _all_ the hung
>> tasks on the system before calling panic().
>>
>> Quoting from 
>> https://syzkaller.appspot.com/text?tag=CrashReport=5412451675799552
>> 
>> INFO: task syz-executor3:13421 blocked for more than 120 seconds.
>>   Not tainted 4.16.0-rc7+ #9
>> "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
>> syz-executor3   D24672 13421   4481 0x0004
>> Call Trace:
>>  context_switch kernel/sched/core.c:2862 [inline]
>>  __schedule+0x8fb/0x1ec0 kernel/sched/core.c:3440
>>  schedule+0xf5/0x430 kernel/sched/core.c:3499
>>  __rwsem_down_read_failed_common kernel/locking/rwsem-xadd.c:269 [inline]
>>  rwsem_down_read_failed+0x401/0x6e0 kernel/locking/rwsem-xadd.c:286
>>  call_rwsem_down_read_failed+0x18/0x30 arch/x86/lib/rwsem.S:94
>>  __down_read arch/x86/include/asm/rwsem.h:83 [inline]
>>  down_read+0xa4/0x150 kernel/locking/rwsem.c:26
>>  __get_super.part.9+0x1d3/0x280 fs/super.c:663
>>  __get_super include/linux/spinlock.h:310 [inline]
>>  get_super+0x2d/0x40 fs/super.c:692
>>  fsync_bdev+0x19/0x80 fs/block_dev.c:468
>>  invalidate_partition+0x35/0x60 block/genhd.c:1566
>>  drop_partitions.isra.12+0xcd/0x1d0 block/partition-generic.c:440
>>  rescan_partitions+0x72/0x900 block/partition-generic.c:513
>>  __blkdev_reread_part+0x15f/0x1e0 block/ioctl.c:173
>>  blkdev_reread_part+0x26/0x40 block/ioctl.c:193
>>  loop_reread_partitions+0x12f/0x1a0 drivers/block/loop.c:619
>>  loop_set_status+0x9bb/0xf60 drivers/block/loop.c:1161
>>  loop_set_status64+0x9d/0x110 drivers/block/loop.c:1271
>>  lo_ioctl+0xd86/0x1b70 drivers/block/loop.c:1381
>> (...snipped...)
>> Showing all locks held in the system:
>> (...snipped...)
>> 3 locks held by syz-executor3/13421:
>>  #0:  (>lo_ctl_mutex/1){+.+.}, at: [<834f78af>] 
>> lo_ioctl+0x8b/0x1b70 drivers/block/loop.c:1355 /* 
>> mutex_lock_nested(>lo_ctl_mutex, 1); */
>>  #1:  (>bd_mutex){+.+.}, at: [<03605603>] 
>> blkdev_reread_part+0x1e/0x40 block/ioctl.c:192
>>  #2:  (>s_umount_key#77){.+.+}, at: [<77701649>] 
>> __get_super.part.9+0x1d3/0x280 fs/super.c:663 /* down_read(>s_umount); */
>> (...snipped...)
>> 2 locks held by syz-executor0/13428:
>>  #0:  (>s_umount_key#76/1){+.+.}, at: [] alloc_super 
>> fs/super.c:211 [inline]
>>  #0:  (>s_umount_key#76/1){+.+.}, at: [] 
>> sget_userns+0x3a1/0xe40 fs/super.c:502 /* down_write_nested(>s_umount, 
>> SINGLE_DEPTH_NESTING); */
>>  #1:  (>lo_ctl_mutex/1){+.+.}, at: [<834f78af>] 
>> lo_ioctl+0x8b/0x1b70 drivers/block/loop.c:1355 /* 
>> mutex_lock_nested(>lo_ctl_mutex, 1); */
>> 
>>
>> In addition to showing hashed address of lock instances, it would be
>> nice if trace of 13428 is printed as well as 13421.
>>
>> Showing hung tasks up to /proc/sys/kernel/hung_task_warnings could delay
>> calling panic() but normally there should not be so many hung tasks.
>>
>> Signed-off-by: Tetsuo Handa 
>> Cc: Vegard Nossum 
>> Cc: Andrew Morton 
>> Cc: Linus Torvalds 
>> Cc: Mandeep Singh Baines 
>> Cc: Paul E. McKenney 
>
> I just know that I am going to regret this the first time this happens
> on a low-speed console port, but...
>
> Acked-by: Paul E. McKenney 


Thanks! I think getting these last bits of debugging tools to be more
useful is very important in the context of syzbot. So:

Acked-by: Dmitry Vyukov 




>> Cc: Peter Zijlstra 
>> Cc: Thomas Gleixner 
>> Cc: Ingo Molnar 
>> ---
>>  kernel/hung_task.c | 11 +++
>>  1 file changed, 7 insertions(+), 4 deletions(-)
>>
>> diff --git a/kernel/hung_task.c b/kernel/hung_task.c
>> index 751593e..32b4794 100644
>> --- a/kernel/hung_task.c
>> +++ b/kernel/hung_task.c
>> @@ -44,6 +44,7 @@
>>
>>  static int __read_mostly did_panic;
>>  static bool hung_task_show_lock;
>> +static bool hung_task_call_panic;
>>
>>  static struct task_struct *watchdog_task;
>>
>> @@ -127,10 +128,8 @@ static void check_hung_task(struct task_struct *t, 
>> unsigned long timeout)
>>   touch_nmi_watchdog();
>>
>>   if (sysctl_hung_task_panic) {
>> - if (hung_task_show_lock)
>> - debug_show_all_locks();
>> - trigger_all_cpu_backtrace();
>> - panic("hung_task: blocked tasks");
>> + hung_task_show_lock = true;
>> + hung_task_call_panic = true;
>>   }
>>  }
>>
>> @@ -193,6 +192,10 @@ static void check_hung_uninterruptible_tasks(unsigned 
>> long timeout)
>>   rcu_read_unlock();
>>   if (hung_task_show_lock)
>>   debug_show_all_locks();
>> + if (hung_task_call_panic) {
>> + trigger_all_cpu_backtrace();
>> + panic("hung_task: blocked tasks");
>> + }
>>  }
>>
>>  static long hung_timeout_jiffies(unsigned long last_checked,

Re: [PATCH v2 1/3] locking: Document the semantics of spin_is_locked()

2018-04-03 Thread David Howells
Andrea Parri  wrote:

> Sorry, but I don't understand your objection: are you suggesting to add
> something like "Always return 0 on !SMP" to the comment?  what else?

Something like that, possibly along with a warning that this might not be what
you want.  You might actually want it to return true on !SMP, it depends on
what you're using it for.

David


Re: [PATCH v2 1/3] locking: Document the semantics of spin_is_locked()

2018-04-03 Thread David Howells
Andrea Parri  wrote:

> Sorry, but I don't understand your objection: are you suggesting to add
> something like "Always return 0 on !SMP" to the comment?  what else?

Something like that, possibly along with a warning that this might not be what
you want.  You might actually want it to return true on !SMP, it depends on
what you're using it for.

David


Re: [PATCH v1] perf stat: enable 1ms interval for printing event counters values

2018-04-03 Thread Jiri Olsa
On Tue, Apr 03, 2018 at 06:04:13PM +0300, Alexey Budankov wrote:
> 
> Currently print count interval for performance counters values is 
> limited by 10ms so reading the values at frequencies higher than 100Hz 
> is restricted by the tool.
> 
> This change makes perf stat -I possible on frequencies up to 1KHz and, 
> to some extent, makes perf stat -I to be on-par with perf record 
> sampling profiling.
> 
> When running perf stat -I for monitoring e.g. PCIe uncore counters and 
> at the same time profiling some I/O workload by perf record e.g. for 
> cpu-cycles and context switches, it is then possible to observe 
> consolidated CPU/OS/IO(Uncore) performance picture for that workload.
> 
> Tool overhead warning printed when specifying -v option can be missed 
> due to screen scrolling in case you have output to the console 
> so message is moved into help available by running perf stat -h.
> 
> Signed-off-by: Alexey Budankov 
> ---
>  tools/perf/builtin-stat.c | 14 ++
>  1 file changed, 2 insertions(+), 12 deletions(-)

I don't mind taking out the limit, but please update also
the stat man page, it mentiones the 10ms minimum

thanks,
jirka

> 
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index f5c454855908..147a27e8c937 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -1943,7 +1943,8 @@ static const struct option stat_options[] = {
>   OPT_STRING(0, "post", _cmd, "command",
>   "command to run after to the measured command"),
>   OPT_UINTEGER('I', "interval-print", _config.interval,
> - "print counts at regular interval in ms (>= 10)"),
> + "print counts at regular interval in ms "
> + "(overhead is possible for values <= 100ms)"),
>   OPT_INTEGER(0, "interval-count", _config.times,
>   "print counts for fixed number of times"),
>   OPT_UINTEGER(0, "timeout", _config.timeout,
> @@ -2923,17 +2924,6 @@ int cmd_stat(int argc, const char **argv)
>   }
>   }
>  
> - if (interval && interval < 100) {
> - if (interval < 10) {
> - pr_err("print interval must be >= 10ms\n");
> - parse_options_usage(stat_usage, stat_options, "I", 1);
> - goto out;
> - } else
> - pr_warning("print interval < 100ms. "
> -"The overhead percentage could be high in 
> some cases. "
> -"Please proceed with caution.\n");
> - }
> -
>   if (stat_config.times && interval)
>   interval_count = true;
>   else if (stat_config.times && !interval) {


Re: [PATCH v1] perf stat: enable 1ms interval for printing event counters values

2018-04-03 Thread Jiri Olsa
On Tue, Apr 03, 2018 at 06:04:13PM +0300, Alexey Budankov wrote:
> 
> Currently print count interval for performance counters values is 
> limited by 10ms so reading the values at frequencies higher than 100Hz 
> is restricted by the tool.
> 
> This change makes perf stat -I possible on frequencies up to 1KHz and, 
> to some extent, makes perf stat -I to be on-par with perf record 
> sampling profiling.
> 
> When running perf stat -I for monitoring e.g. PCIe uncore counters and 
> at the same time profiling some I/O workload by perf record e.g. for 
> cpu-cycles and context switches, it is then possible to observe 
> consolidated CPU/OS/IO(Uncore) performance picture for that workload.
> 
> Tool overhead warning printed when specifying -v option can be missed 
> due to screen scrolling in case you have output to the console 
> so message is moved into help available by running perf stat -h.
> 
> Signed-off-by: Alexey Budankov 
> ---
>  tools/perf/builtin-stat.c | 14 ++
>  1 file changed, 2 insertions(+), 12 deletions(-)

I don't mind taking out the limit, but please update also
the stat man page, it mentiones the 10ms minimum

thanks,
jirka

> 
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index f5c454855908..147a27e8c937 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -1943,7 +1943,8 @@ static const struct option stat_options[] = {
>   OPT_STRING(0, "post", _cmd, "command",
>   "command to run after to the measured command"),
>   OPT_UINTEGER('I', "interval-print", _config.interval,
> - "print counts at regular interval in ms (>= 10)"),
> + "print counts at regular interval in ms "
> + "(overhead is possible for values <= 100ms)"),
>   OPT_INTEGER(0, "interval-count", _config.times,
>   "print counts for fixed number of times"),
>   OPT_UINTEGER(0, "timeout", _config.timeout,
> @@ -2923,17 +2924,6 @@ int cmd_stat(int argc, const char **argv)
>   }
>   }
>  
> - if (interval && interval < 100) {
> - if (interval < 10) {
> - pr_err("print interval must be >= 10ms\n");
> - parse_options_usage(stat_usage, stat_options, "I", 1);
> - goto out;
> - } else
> - pr_warning("print interval < 100ms. "
> -"The overhead percentage could be high in 
> some cases. "
> -"Please proceed with caution.\n");
> - }
> -
>   if (stat_config.times && interval)
>   interval_count = true;
>   else if (stat_config.times && !interval) {


Re: [PATCH 02/15] ARM: pxa: add dma slave map

2018-04-03 Thread Robert Jarzmik
Arnd Bergmann  writes:

>> +   { "smc911x.0", "rx", PDMA_FILTER_PARAM(LOWEST, -1) },
>> +   { "smc911x.0", "tx", PDMA_FILTER_PARAM(LOWEST, -1) },
>> +   { "smc91x.0", "data", PDMA_FILTER_PARAM(LOWEST, -1) },
>
> This one is interesting, as you are dealing with an off-chip device,
> and the channel number is '-'1. How does this even work? Does it
> mean

This relies on pxa_dma, in which the "-1" for a requestor line means "no
requestor" or said in another way "always requesting". As a consequence, as soon
as the DMA descriptors are queued, the transfer begins, and it is supposed
implicitely that the FIFO output availability is at least as quick as the system
bus and the DMA size is perfectly fit for the FIFO available bytes.

This is what has been the underlying of DMA transfers of smc91x(x) on the PXA
platforms, where the smc91x(s) are directly wired on the system bus (the same
bus having DRAM, SRAM, IO-mapped devices).

>
>> +   /* PXA25x specific map */
>> +   { "pxa25x-ssp.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
>> +   { "pxa25x-ssp.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
>> +   { "pxa25x-nssp.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>> +   { "pxa25x-nssp.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>> +   { "pxa25x-nssp.2", "rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>> +   { "pxa25x-nssp.2", "tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>> +   { "pxa-pcm-audio", "nssp2_rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>> +   { "pxa-pcm-audio", "nssp2_tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>> +   { "pxa-pcm-audio", "nssp3_rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>> +   { "pxa-pcm-audio", "nssp3_tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>> +
>> +   /* PXA27x specific map */
>> +   { "pxa-pcm-audio", "ssp3_rx", PDMA_FILTER_PARAM(LOWEST, 66) },
>> +   { "pxa-pcm-audio", "ssp3_tx", PDMA_FILTER_PARAM(LOWEST, 67) },
>> +   { "pxa27x-camera.0", "CI_Y", PDMA_FILTER_PARAM(HIGHEST, 68) },
>> +   { "pxa27x-camera.0", "CI_U", PDMA_FILTER_PARAM(HIGHEST, 69) },
>> +   { "pxa27x-camera.0", "CI_V", PDMA_FILTER_PARAM(HIGHEST, 70) },
>> +
>> +   /* PXA3xx specific map */
>> +   { "pxa-pcm-audio", "ssp4_rx", PDMA_FILTER_PARAM(LOWEST, 2) },
>> +   { "pxa-pcm-audio", "ssp4_tx", PDMA_FILTER_PARAM(LOWEST, 3) },
>> +   { "pxa2xx-mci.1", "rx", PDMA_FILTER_PARAM(LOWEST, 93) },
>> +   { "pxa2xx-mci.1", "tx", PDMA_FILTER_PARAM(LOWEST, 94) },
>> +   { "pxa3xx-nand", "data", PDMA_FILTER_PARAM(LOWEST, 97) },
>> +   { "pxa2xx-mci.2", "rx", PDMA_FILTER_PARAM(LOWEST, 100) },
>> +   { "pxa2xx-mci.2", "tx", PDMA_FILTER_PARAM(LOWEST, 101) },
>> +};
>
> Since more than half the entries in here are chip specific, maybe it would be
> better to split that table into three and have a copy for each one in
> arch/arm/mach-pxa/pxa{25x.27x.3xx}.c?
Mmmh, today the split is :
 - 16 common entries
 - 10 pxa25x specific entries
 - 5 pxa27x specific entries
 - 7 pxa3xx specific entries
 => total of 38 lines

After the split we'll have :
 - 26 pxa25x specific entries
 - 21 pxa27x specific entries
 - 23 pxa3xx specific entries
 => total of 70 lines

That doubles the number of lines, not counting the declarations, and amending of
pxa2xx_set_dmac_info().

If you think it's worth it, what is the driving benefit behind ?

> Does that mean it's actually a memory-to-memory transfer with a device being
> on the external SRAM interface?
I'm taking this is the follow up to the "-1" question :0

Cheers.

-- 
Robert


Re: [PATCH 02/15] ARM: pxa: add dma slave map

2018-04-03 Thread Robert Jarzmik
Arnd Bergmann  writes:

>> +   { "smc911x.0", "rx", PDMA_FILTER_PARAM(LOWEST, -1) },
>> +   { "smc911x.0", "tx", PDMA_FILTER_PARAM(LOWEST, -1) },
>> +   { "smc91x.0", "data", PDMA_FILTER_PARAM(LOWEST, -1) },
>
> This one is interesting, as you are dealing with an off-chip device,
> and the channel number is '-'1. How does this even work? Does it
> mean

This relies on pxa_dma, in which the "-1" for a requestor line means "no
requestor" or said in another way "always requesting". As a consequence, as soon
as the DMA descriptors are queued, the transfer begins, and it is supposed
implicitely that the FIFO output availability is at least as quick as the system
bus and the DMA size is perfectly fit for the FIFO available bytes.

This is what has been the underlying of DMA transfers of smc91x(x) on the PXA
platforms, where the smc91x(s) are directly wired on the system bus (the same
bus having DRAM, SRAM, IO-mapped devices).

>
>> +   /* PXA25x specific map */
>> +   { "pxa25x-ssp.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
>> +   { "pxa25x-ssp.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
>> +   { "pxa25x-nssp.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>> +   { "pxa25x-nssp.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>> +   { "pxa25x-nssp.2", "rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>> +   { "pxa25x-nssp.2", "tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>> +   { "pxa-pcm-audio", "nssp2_rx", PDMA_FILTER_PARAM(LOWEST, 15) },
>> +   { "pxa-pcm-audio", "nssp2_tx", PDMA_FILTER_PARAM(LOWEST, 16) },
>> +   { "pxa-pcm-audio", "nssp3_rx", PDMA_FILTER_PARAM(LOWEST, 23) },
>> +   { "pxa-pcm-audio", "nssp3_tx", PDMA_FILTER_PARAM(LOWEST, 24) },
>> +
>> +   /* PXA27x specific map */
>> +   { "pxa-pcm-audio", "ssp3_rx", PDMA_FILTER_PARAM(LOWEST, 66) },
>> +   { "pxa-pcm-audio", "ssp3_tx", PDMA_FILTER_PARAM(LOWEST, 67) },
>> +   { "pxa27x-camera.0", "CI_Y", PDMA_FILTER_PARAM(HIGHEST, 68) },
>> +   { "pxa27x-camera.0", "CI_U", PDMA_FILTER_PARAM(HIGHEST, 69) },
>> +   { "pxa27x-camera.0", "CI_V", PDMA_FILTER_PARAM(HIGHEST, 70) },
>> +
>> +   /* PXA3xx specific map */
>> +   { "pxa-pcm-audio", "ssp4_rx", PDMA_FILTER_PARAM(LOWEST, 2) },
>> +   { "pxa-pcm-audio", "ssp4_tx", PDMA_FILTER_PARAM(LOWEST, 3) },
>> +   { "pxa2xx-mci.1", "rx", PDMA_FILTER_PARAM(LOWEST, 93) },
>> +   { "pxa2xx-mci.1", "tx", PDMA_FILTER_PARAM(LOWEST, 94) },
>> +   { "pxa3xx-nand", "data", PDMA_FILTER_PARAM(LOWEST, 97) },
>> +   { "pxa2xx-mci.2", "rx", PDMA_FILTER_PARAM(LOWEST, 100) },
>> +   { "pxa2xx-mci.2", "tx", PDMA_FILTER_PARAM(LOWEST, 101) },
>> +};
>
> Since more than half the entries in here are chip specific, maybe it would be
> better to split that table into three and have a copy for each one in
> arch/arm/mach-pxa/pxa{25x.27x.3xx}.c?
Mmmh, today the split is :
 - 16 common entries
 - 10 pxa25x specific entries
 - 5 pxa27x specific entries
 - 7 pxa3xx specific entries
 => total of 38 lines

After the split we'll have :
 - 26 pxa25x specific entries
 - 21 pxa27x specific entries
 - 23 pxa3xx specific entries
 => total of 70 lines

That doubles the number of lines, not counting the declarations, and amending of
pxa2xx_set_dmac_info().

If you think it's worth it, what is the driving benefit behind ?

> Does that mean it's actually a memory-to-memory transfer with a device being
> on the external SRAM interface?
I'm taking this is the follow up to the "-1" question :0

Cheers.

-- 
Robert


Re: [PATCH v3 09/14] s390: vfio-ap: sysfs interfaces to configure domains

2018-04-03 Thread Cornelia Huck
On Tue, 3 Apr 2018 11:12:45 -0400
Tony Krowiak  wrote:

> On 04/03/2018 07:17 AM, Cornelia Huck wrote:
> > On Wed, 14 Mar 2018 14:25:49 -0400
> > Tony Krowiak  wrote:
> >  
> >> Provides the sysfs interfaces for assigning AP domains to
> >> and unassigning AP domains from a mediated matrix device.
> >>
> >> An AP domain ID corresponds to an AP queue index (APQI). For
> >> each domain assigned to the mediated matrix device, its
> >> corresponging APQI is stored in an AP queue mask (AQM).
> >> The bits in the AQM, from most significant to least
> >> significant bit, correspond to AP domain numbers 0 to 255.
> >> When a domain is assigned, the bit corresponding to its
> >> APQI will be set in the AQM. Likewise, when a domain is
> >> unassigned, the bit corresponding to its APQI will be
> >> cleared from the AQM.
> >>
> >> The relevant sysfs structures are:
> >>
> >> /sys/devices/vfio_ap
> >> ... [matrix]
> >> .. [mdev_supported_types]
> >> . [vfio_ap-passthrough]
> >>  [devices]
> >> ...[$uuid]
> >> .. assign_domain
> >> .. unassign_domain
> >>
> >> To assign a domain to the $uuid mediated matrix device,
> >> write the domain's ID to the assign_domain file. To
> >> unassign a domain, write the domain's ID to the
> >> unassign_domain file. The ID is specified using
> >> conventional semantics: If it begins with 0x, the number
> >> will be parsed as a hexadecimal (case insensitive) number;
> >> otherwise, it will be parsed as a decimal number.
> >>
> >> For example, to assign domain 173 (0xad) to the mediated matrix
> >> device $uuid:
> >>
> >>echo 173 > assign_domain
> >>
> >>or
> >>
> >>echo 0xad > assign_domain
> >>
> >> To unassign domain 173 (0xad):
> >>
> >>echo 173 > unassign_domain
> >>
> >>or
> >>
> >>echo 0xad > unassign_domain
> >>
> >> The assignment will be rejected:
> >>
> >> * If the domain ID exceeds the maximum value for an AP domain:
> >>
> >>* If the AP Extended Addressing (APXA) facility is installed,
> >>  the max value is 255
> >>
> >>* Else the max value is 15
> >>
> >> * If no AP adapters have yet been assigned and there are
> >>no AP queues reserved by the VFIO AP driver that have an APQN
> >>with an APQI matching that of the AP domain number being
> >>assigned.
> >>
> >> * If any of the APQNs that can be derived from the intersection
> >>of the APQI being assigned and the AP adapter ID (APID) of
> >>each of the AP adapters previously assigned can not be matched
> >>with an APQN of an AP queue device reserved by the VFIO AP
> >>driver.
> >>
> >> Signed-off-by: Tony Krowiak 
> >> ---
> >>   arch/s390/include/asm/kvm-ap.h|1 +
> >>   drivers/s390/crypto/vfio_ap_ops.c |  215 
> >> -
> >>   2 files changed, 215 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
> >> b/drivers/s390/crypto/vfio_ap_ops.c
> >> index 90512a6..c448835 100644
> >> --- a/drivers/s390/crypto/vfio_ap_ops.c
> >> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> >> @@ -377,10 +377,223 @@ static ssize_t unassign_adapter_store(struct device 
> >> *dev,
> >>   }
> >>   DEVICE_ATTR_WO(unassign_adapter);
> >>   
> >> +/**
> >> + * vfio_ap_validate_queues_for_apqi
> >> + *
> >> + * @ap_matrix: the matrix device
> >> + * @matrix_mdev: the mediated matrix device
> >> + * @apqi: an AP queue index (APQI) - corresponds to a domain ID
> >> + *
> >> + * Verifies that each APQN that is derived from the intersection of @apqi 
> >> and
> >> + * each AP adapter ID (APID) corresponding to an AP domain assigned to the
> >> + * @matrix_mdev matches the APQN of an AP queue reserved by the VFIO AP 
> >> device
> >> + * driver.
> >> + *
> >> + * Returns 0 if validation succeeds; otherwise, returns an error.
> >> + */
> >> +static int vfio_ap_validate_queues_for_apqi(struct ap_matrix *ap_matrix,
> >> +  struct ap_matrix_mdev *matrix_mdev,
> >> +  unsigned long apqi)
> >> +{
> >> +  int ret;
> >> +  struct vfio_ap_qid_match qid_match;
> >> +  unsigned long apid;
> >> +  struct device_driver *drv = ap_matrix->device.driver;
> >> +
> >> +  /**
> >> +   * Examine each APQN with the specified APQI
> >> +   */
> >> +  for_each_set_bit_inv(apid, matrix_mdev->matrix->apm,
> >> +   matrix_mdev->matrix->apm_max) {
> >> +  qid_match.qid = AP_MKQID(apid, apqi);
> >> +  qid_match.dev = NULL;
> >> +
> >> +  ret = driver_for_each_device(drv, NULL, _match,
> >> +   vfio_ap_queue_match);
> >> +  if (ret)
> >> +  return ret;  
> > Hm, I'm wondering whether jumping out of the outer loop is the correct
> > thing to do here - and if yes, whether we should log an error?  
> If you look at the 

Re: [PATCH v3 09/14] s390: vfio-ap: sysfs interfaces to configure domains

2018-04-03 Thread Cornelia Huck
On Tue, 3 Apr 2018 11:12:45 -0400
Tony Krowiak  wrote:

> On 04/03/2018 07:17 AM, Cornelia Huck wrote:
> > On Wed, 14 Mar 2018 14:25:49 -0400
> > Tony Krowiak  wrote:
> >  
> >> Provides the sysfs interfaces for assigning AP domains to
> >> and unassigning AP domains from a mediated matrix device.
> >>
> >> An AP domain ID corresponds to an AP queue index (APQI). For
> >> each domain assigned to the mediated matrix device, its
> >> corresponging APQI is stored in an AP queue mask (AQM).
> >> The bits in the AQM, from most significant to least
> >> significant bit, correspond to AP domain numbers 0 to 255.
> >> When a domain is assigned, the bit corresponding to its
> >> APQI will be set in the AQM. Likewise, when a domain is
> >> unassigned, the bit corresponding to its APQI will be
> >> cleared from the AQM.
> >>
> >> The relevant sysfs structures are:
> >>
> >> /sys/devices/vfio_ap
> >> ... [matrix]
> >> .. [mdev_supported_types]
> >> . [vfio_ap-passthrough]
> >>  [devices]
> >> ...[$uuid]
> >> .. assign_domain
> >> .. unassign_domain
> >>
> >> To assign a domain to the $uuid mediated matrix device,
> >> write the domain's ID to the assign_domain file. To
> >> unassign a domain, write the domain's ID to the
> >> unassign_domain file. The ID is specified using
> >> conventional semantics: If it begins with 0x, the number
> >> will be parsed as a hexadecimal (case insensitive) number;
> >> otherwise, it will be parsed as a decimal number.
> >>
> >> For example, to assign domain 173 (0xad) to the mediated matrix
> >> device $uuid:
> >>
> >>echo 173 > assign_domain
> >>
> >>or
> >>
> >>echo 0xad > assign_domain
> >>
> >> To unassign domain 173 (0xad):
> >>
> >>echo 173 > unassign_domain
> >>
> >>or
> >>
> >>echo 0xad > unassign_domain
> >>
> >> The assignment will be rejected:
> >>
> >> * If the domain ID exceeds the maximum value for an AP domain:
> >>
> >>* If the AP Extended Addressing (APXA) facility is installed,
> >>  the max value is 255
> >>
> >>* Else the max value is 15
> >>
> >> * If no AP adapters have yet been assigned and there are
> >>no AP queues reserved by the VFIO AP driver that have an APQN
> >>with an APQI matching that of the AP domain number being
> >>assigned.
> >>
> >> * If any of the APQNs that can be derived from the intersection
> >>of the APQI being assigned and the AP adapter ID (APID) of
> >>each of the AP adapters previously assigned can not be matched
> >>with an APQN of an AP queue device reserved by the VFIO AP
> >>driver.
> >>
> >> Signed-off-by: Tony Krowiak 
> >> ---
> >>   arch/s390/include/asm/kvm-ap.h|1 +
> >>   drivers/s390/crypto/vfio_ap_ops.c |  215 
> >> -
> >>   2 files changed, 215 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
> >> b/drivers/s390/crypto/vfio_ap_ops.c
> >> index 90512a6..c448835 100644
> >> --- a/drivers/s390/crypto/vfio_ap_ops.c
> >> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> >> @@ -377,10 +377,223 @@ static ssize_t unassign_adapter_store(struct device 
> >> *dev,
> >>   }
> >>   DEVICE_ATTR_WO(unassign_adapter);
> >>   
> >> +/**
> >> + * vfio_ap_validate_queues_for_apqi
> >> + *
> >> + * @ap_matrix: the matrix device
> >> + * @matrix_mdev: the mediated matrix device
> >> + * @apqi: an AP queue index (APQI) - corresponds to a domain ID
> >> + *
> >> + * Verifies that each APQN that is derived from the intersection of @apqi 
> >> and
> >> + * each AP adapter ID (APID) corresponding to an AP domain assigned to the
> >> + * @matrix_mdev matches the APQN of an AP queue reserved by the VFIO AP 
> >> device
> >> + * driver.
> >> + *
> >> + * Returns 0 if validation succeeds; otherwise, returns an error.
> >> + */
> >> +static int vfio_ap_validate_queues_for_apqi(struct ap_matrix *ap_matrix,
> >> +  struct ap_matrix_mdev *matrix_mdev,
> >> +  unsigned long apqi)
> >> +{
> >> +  int ret;
> >> +  struct vfio_ap_qid_match qid_match;
> >> +  unsigned long apid;
> >> +  struct device_driver *drv = ap_matrix->device.driver;
> >> +
> >> +  /**
> >> +   * Examine each APQN with the specified APQI
> >> +   */
> >> +  for_each_set_bit_inv(apid, matrix_mdev->matrix->apm,
> >> +   matrix_mdev->matrix->apm_max) {
> >> +  qid_match.qid = AP_MKQID(apid, apqi);
> >> +  qid_match.dev = NULL;
> >> +
> >> +  ret = driver_for_each_device(drv, NULL, _match,
> >> +   vfio_ap_queue_match);
> >> +  if (ret)
> >> +  return ret;  
> > Hm, I'm wondering whether jumping out of the outer loop is the correct
> > thing to do here - and if yes, whether we should log an error?  
> If you look at the vfio_ap_queue_match() function which is passed to the
> driver_for_each_device() function, it never 

Re: [PATCH RFC tools/memory-model] Add s390.{cfg,cat}

2018-04-03 Thread Paul E. McKenney
On Tue, Apr 03, 2018 at 09:50:19AM -0400, Alan Stern wrote:
> On Mon, 2 Apr 2018, Paul E. McKenney wrote:
> 
> > > > I will look at this more later, reaching end of both battery and useful
> > > > attention span...
> > 
> > Like the following, perhaps?
> > 
> > Thanx, Paul
> > 
> > 
> > 
> > s390
> > 
> > include "fences.cat"
> > include "cos.cat"
> > 
> > (* Fundamental coherence ordering *)
> > let com = rf | co | fr
> > acyclic po-loc | com as coherence
> > 
> > (* Atomic *)
> > empty rmw & (fre;coe) as atom 
> > 
> > (* Fences *)
> > let mb = [M] ; fencerel(Mb) ; [M]
> > 
> > (* TSO with multicopy atomicity *)
> > let po-ghb = ([R] ; po ; [M]) | ([M] ; po ; [W]) 
> > acyclic mb | po-ghb | fr | rf | co as sc
> 
> Yes, that should work okay (apart from issues related to ordering of
> atomic accesses).
> 
> By the way, what does that last "sc" stand for?  Surely not Sequential
> Consistency!  You might consider renaming it to "tso-mca".

Good point, fixed.

But it is the closest to SC in commercial computing systems, for whatever
that is worth.  ;-)

Thanx, Paul



Re: [PATCH RFC tools/memory-model] Add s390.{cfg,cat}

2018-04-03 Thread Paul E. McKenney
On Tue, Apr 03, 2018 at 09:50:19AM -0400, Alan Stern wrote:
> On Mon, 2 Apr 2018, Paul E. McKenney wrote:
> 
> > > > I will look at this more later, reaching end of both battery and useful
> > > > attention span...
> > 
> > Like the following, perhaps?
> > 
> > Thanx, Paul
> > 
> > 
> > 
> > s390
> > 
> > include "fences.cat"
> > include "cos.cat"
> > 
> > (* Fundamental coherence ordering *)
> > let com = rf | co | fr
> > acyclic po-loc | com as coherence
> > 
> > (* Atomic *)
> > empty rmw & (fre;coe) as atom 
> > 
> > (* Fences *)
> > let mb = [M] ; fencerel(Mb) ; [M]
> > 
> > (* TSO with multicopy atomicity *)
> > let po-ghb = ([R] ; po ; [M]) | ([M] ; po ; [W]) 
> > acyclic mb | po-ghb | fr | rf | co as sc
> 
> Yes, that should work okay (apart from issues related to ordering of
> atomic accesses).
> 
> By the way, what does that last "sc" stand for?  Surely not Sequential
> Consistency!  You might consider renaming it to "tso-mca".

Good point, fixed.

But it is the closest to SC in commercial computing systems, for whatever
that is worth.  ;-)

Thanx, Paul



<    5   6   7   8   9   10   11   12   13   14   >