Re: ipv6 redefinition build issue with 4.15-rc8

2018-01-16 Thread Daniel Wagner

Hi Neil,

On 01/16/2018 07:51 PM, Neil MacLeod wrote:

Since this commit in 4.15-rc8:

https://github.com/torvalds/linux/commit/6926e041a8920c8ec27e4e155efa760aa01551fd

building connman 1.35 with glibc 2.26 now fails as follows:

http://ix.io/EbP

I'm not sure if this is a kernel issue, a glibc issue, or a connman issue.

Reverting the kernel commit resolves the issue, but isn't ideal (unless 
it's the correct solution, of course).


Does anyone have any better ideas?


Since ConnMan does not redefine 'struct in6_addr' and friends I would 
say it is kernel/glibc header include problem. But I might be wrong here.


@Hauke: Do you happen to know what is going on?

Thanks,
Daniel


Re: ipv6 redefinition build issue with 4.15-rc8

2018-01-16 Thread Daniel Wagner

Hi Neil,

On 01/16/2018 07:51 PM, Neil MacLeod wrote:

Since this commit in 4.15-rc8:

https://github.com/torvalds/linux/commit/6926e041a8920c8ec27e4e155efa760aa01551fd

building connman 1.35 with glibc 2.26 now fails as follows:

http://ix.io/EbP

I'm not sure if this is a kernel issue, a glibc issue, or a connman issue.

Reverting the kernel commit resolves the issue, but isn't ideal (unless 
it's the correct solution, of course).


Does anyone have any better ideas?


Since ConnMan does not redefine 'struct in6_addr' and friends I would 
say it is kernel/glibc header include problem. But I might be wrong here.


@Hauke: Do you happen to know what is going on?

Thanks,
Daniel


linux-next: Tree for Jan 17

2018-01-16 Thread Stephen Rothwell
Hi all,

Changes since 20180116:

The arm64 tree gained conflicts against Linus' tree.

The net-next tree gained conflicts against the net tree.

The rdma tree gained a conflict against the rdma-fixes tree.

The block tree gained a conflict against the dma-mapping tree.

The kvm tree gained a conflict against Linus' tree.

Non-merge commits (relative to Linus' tree): 9267
 9407 files changed, 381995 insertions(+), 245677 deletions(-)



I have created today's linux-next tree at
git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
(patches at http://www.kernel.org/pub/linux/kernel/next/ ).  If you
are tracking the linux-next tree using git, you should not use "git pull"
to do so as that will try to merge the new linux-next release with the
old one.  You should use "git fetch" and checkout or reset to the new
master.

You can see which trees have been included by looking in the Next/Trees
file in the source.  There are also quilt-import.log and merge.log
files in the Next directory.  Between each merge, the tree was built
with a ppc64_defconfig for powerpc, an allmodconfig for x86_64, a
multi_v7_defconfig for arm and a native build of tools/perf. After
the final fixups (if any), I do an x86_64 modules_install followed by
builds for x86_64 allnoconfig, powerpc allnoconfig (32 and 64 bit),
ppc44x_defconfig, allyesconfig and pseries_le_defconfig and i386, sparc
and sparc64 defconfig. And finally, a simple boot test of the powerpc
pseries_le_defconfig kernel in qemu (with and without kvm enabled).

Below is a summary of the state of the merge.

I am currently merging 256 trees (counting Linus' and 44 trees of bug
fix patches pending for the current merge release).

Stats about the size of the tree over time can be seen at
http://neuling.org/linux-next-size.html .

Status of my local build tests will be at
http://kisskb.ellerman.id.au/linux-next .  If maintainers want to give
advice about cross compilers/configs that work, we are always open to add
more builds.

Thanks to Randy Dunlap for doing many randconfig builds.  And to Paul
Gortmaker for triage and bug fixes.

-- 
Cheers,
Stephen Rothwell

$ git checkout master
$ git reset --hard stable
Merging origin/master (41aa5e5d712b Merge tag 'sound-4.15' of 
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound)
Merging fixes/master (820bf5c419e4 Merge tag 'scsi-fixes' of 
git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi)
Merging kbuild-current/fixes (36c1681678b5 genksyms: drop *.hash.c from 
.gitignore)
Merging arc-current/for-curr (b2cd1df66037 Linux 4.15-rc7)
Merging arm-current/fixes (36b0cb84ee85 ARM: 8731/1: Fix 
csum_partial_copy_from_user() stack mismatch)
Merging m68k-current/for-linus (5e387199c17c m68k/defconfig: Update defconfigs 
for v4.14-rc7)
Merging metag-fixes/fixes (b884a190afce metag/usercopy: Add missing fixups)
Merging powerpc-fixes/fixes (349524bc0da6 powerpc: Don't preempt_disable() in 
show_cpuinfo())
Merging sparc/master (59585b4be9ae sparc64: repair calling incorrect hweight 
function from stubs)
Merging fscrypt-current/for-stable (ae64f9bd1d36 Linux 4.15-rc2)
Merging net/master (81d947e2b8dd net, sched: fix panic when updating miniq 
{b,q}stats)
Merging bpf/master (a2284d912bfc bpf, arm64: fix stack_depth tracking in 
combination with tail calls)
Merging ipsec/master (76a420119181 xfrm: Fix a race in the xdst pcpu cache.)
Merging netfilter/master (889c604fd0b5 netfilter: x_tables: fix int overflow in 
xt_alloc_table_info())
Merging ipvs/master (f7fb77fc1235 netfilter: nft_compat: check extension hook 
mask only if set)
Merging wireless-drivers/master (cc124d5cc8d8 brcmfmac: fix CLM load error for 
legacy chips when user helper is enabled)
Merging mac80211/master (59b179b48ce2 cfg80211: check dev_set_name() return 
value)
Merging rdma-fixes/for-rc (ae59c3f0b6cf RDMA/mlx5: Fix out-of-bound access 
while querying AH)
Merging sound-current/for-linus (b3defb791b26 ALSA: seq: Make ioctls race-free)
Merging pci-current/for-linus (d6c1efecd1e1 x86/PCI: Enable AMD 64-bit window 
on resume)
Merging driver-core.current/driver-core-linus (30a7acd57389 Linux 4.15-rc6)
Merging tty.current/tty-linus (30a7acd57389 Linux 4.15-rc6)
Merging usb.current/usb-linus (a8750ddca918 Linux 4.15-rc8)
Merging usb-gadget-fixes/fixes (b2cd1df66037 Linux 4.15-rc7)
Merging usb-serial-fixes/usb-linus (d14ac576d10f USB: serial: cp210x: add new 
device ID ELV ALC 8xxx)
Merging usb-chipidea-fixes/ci-for-usb-stable (964728f9f407 USB: chipidea: msm: 
fix ulpi-node lookup)
Merging phy/fixes (2b88212c4cc6 phy: rcar-gen3-usb2: select USB_COMMON)
Merging staging.current/staging-linus (a8750ddca918 Linux 4.15-rc8)
Merging char-misc.current/char-misc-linus (a8750ddca918 Linux 4.15-rc8)
Merging input-current/for-linus (4d94e776bd29 Input: ALPS - fix multi-touch 
decoding on SS4 plus touchpads)
Merging crypto-current/master (9a00674213a3 crypto: algapi - f

linux-next: Tree for Jan 17

2018-01-16 Thread Stephen Rothwell
Hi all,

Changes since 20180116:

The arm64 tree gained conflicts against Linus' tree.

The net-next tree gained conflicts against the net tree.

The rdma tree gained a conflict against the rdma-fixes tree.

The block tree gained a conflict against the dma-mapping tree.

The kvm tree gained a conflict against Linus' tree.

Non-merge commits (relative to Linus' tree): 9267
 9407 files changed, 381995 insertions(+), 245677 deletions(-)



I have created today's linux-next tree at
git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
(patches at http://www.kernel.org/pub/linux/kernel/next/ ).  If you
are tracking the linux-next tree using git, you should not use "git pull"
to do so as that will try to merge the new linux-next release with the
old one.  You should use "git fetch" and checkout or reset to the new
master.

You can see which trees have been included by looking in the Next/Trees
file in the source.  There are also quilt-import.log and merge.log
files in the Next directory.  Between each merge, the tree was built
with a ppc64_defconfig for powerpc, an allmodconfig for x86_64, a
multi_v7_defconfig for arm and a native build of tools/perf. After
the final fixups (if any), I do an x86_64 modules_install followed by
builds for x86_64 allnoconfig, powerpc allnoconfig (32 and 64 bit),
ppc44x_defconfig, allyesconfig and pseries_le_defconfig and i386, sparc
and sparc64 defconfig. And finally, a simple boot test of the powerpc
pseries_le_defconfig kernel in qemu (with and without kvm enabled).

Below is a summary of the state of the merge.

I am currently merging 256 trees (counting Linus' and 44 trees of bug
fix patches pending for the current merge release).

Stats about the size of the tree over time can be seen at
http://neuling.org/linux-next-size.html .

Status of my local build tests will be at
http://kisskb.ellerman.id.au/linux-next .  If maintainers want to give
advice about cross compilers/configs that work, we are always open to add
more builds.

Thanks to Randy Dunlap for doing many randconfig builds.  And to Paul
Gortmaker for triage and bug fixes.

-- 
Cheers,
Stephen Rothwell

$ git checkout master
$ git reset --hard stable
Merging origin/master (41aa5e5d712b Merge tag 'sound-4.15' of 
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound)
Merging fixes/master (820bf5c419e4 Merge tag 'scsi-fixes' of 
git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi)
Merging kbuild-current/fixes (36c1681678b5 genksyms: drop *.hash.c from 
.gitignore)
Merging arc-current/for-curr (b2cd1df66037 Linux 4.15-rc7)
Merging arm-current/fixes (36b0cb84ee85 ARM: 8731/1: Fix 
csum_partial_copy_from_user() stack mismatch)
Merging m68k-current/for-linus (5e387199c17c m68k/defconfig: Update defconfigs 
for v4.14-rc7)
Merging metag-fixes/fixes (b884a190afce metag/usercopy: Add missing fixups)
Merging powerpc-fixes/fixes (349524bc0da6 powerpc: Don't preempt_disable() in 
show_cpuinfo())
Merging sparc/master (59585b4be9ae sparc64: repair calling incorrect hweight 
function from stubs)
Merging fscrypt-current/for-stable (ae64f9bd1d36 Linux 4.15-rc2)
Merging net/master (81d947e2b8dd net, sched: fix panic when updating miniq 
{b,q}stats)
Merging bpf/master (a2284d912bfc bpf, arm64: fix stack_depth tracking in 
combination with tail calls)
Merging ipsec/master (76a420119181 xfrm: Fix a race in the xdst pcpu cache.)
Merging netfilter/master (889c604fd0b5 netfilter: x_tables: fix int overflow in 
xt_alloc_table_info())
Merging ipvs/master (f7fb77fc1235 netfilter: nft_compat: check extension hook 
mask only if set)
Merging wireless-drivers/master (cc124d5cc8d8 brcmfmac: fix CLM load error for 
legacy chips when user helper is enabled)
Merging mac80211/master (59b179b48ce2 cfg80211: check dev_set_name() return 
value)
Merging rdma-fixes/for-rc (ae59c3f0b6cf RDMA/mlx5: Fix out-of-bound access 
while querying AH)
Merging sound-current/for-linus (b3defb791b26 ALSA: seq: Make ioctls race-free)
Merging pci-current/for-linus (d6c1efecd1e1 x86/PCI: Enable AMD 64-bit window 
on resume)
Merging driver-core.current/driver-core-linus (30a7acd57389 Linux 4.15-rc6)
Merging tty.current/tty-linus (30a7acd57389 Linux 4.15-rc6)
Merging usb.current/usb-linus (a8750ddca918 Linux 4.15-rc8)
Merging usb-gadget-fixes/fixes (b2cd1df66037 Linux 4.15-rc7)
Merging usb-serial-fixes/usb-linus (d14ac576d10f USB: serial: cp210x: add new 
device ID ELV ALC 8xxx)
Merging usb-chipidea-fixes/ci-for-usb-stable (964728f9f407 USB: chipidea: msm: 
fix ulpi-node lookup)
Merging phy/fixes (2b88212c4cc6 phy: rcar-gen3-usb2: select USB_COMMON)
Merging staging.current/staging-linus (a8750ddca918 Linux 4.15-rc8)
Merging char-misc.current/char-misc-linus (a8750ddca918 Linux 4.15-rc8)
Merging input-current/for-linus (4d94e776bd29 Input: ALPS - fix multi-touch 
decoding on SS4 plus touchpads)
Merging crypto-current/master (9a00674213a3 crypto: algapi - f

Re: [PATCH v2 12/13] iommu/rockchip: Add runtime PM support

2018-01-16 Thread JeffyChen

Hi Tomasz,

On 01/17/2018 03:38 PM, Tomasz Figa wrote:

>>Don't we need to check here (and in _shutdown() too) if we have a
>>domain attached?

>
>hmmm, right, the startup might been called by resume, so should check
>iommu->domain here.
>
>but the shutdown would be called at the end of detach or suspend, it could
>be not attached or attached.

If startup might be called by resume, without domain attached, what
prevents shutdown from being called by suspend after that resume,
still without domain attached? Is it guaranteed that if resume is
called, someone will attach a domain before suspend is called?


no, the shutdown would be called by:
1/ end of detach_dev
so it would be not attached at that time

2/ suspend
so it could be attached, and also could be not attached


anyway, i think the shutdown would work without domain attached(just 
disable paging and clear the iommu bases) ;)



Best regards,
Tomasz








Re: [PATCH v2 12/13] iommu/rockchip: Add runtime PM support

2018-01-16 Thread JeffyChen

Hi Tomasz,

On 01/17/2018 03:38 PM, Tomasz Figa wrote:

>>Don't we need to check here (and in _shutdown() too) if we have a
>>domain attached?

>
>hmmm, right, the startup might been called by resume, so should check
>iommu->domain here.
>
>but the shutdown would be called at the end of detach or suspend, it could
>be not attached or attached.

If startup might be called by resume, without domain attached, what
prevents shutdown from being called by suspend after that resume,
still without domain attached? Is it guaranteed that if resume is
called, someone will attach a domain before suspend is called?


no, the shutdown would be called by:
1/ end of detach_dev
so it would be not attached at that time

2/ suspend
so it could be attached, and also could be not attached


anyway, i think the shutdown would work without domain attached(just 
disable paging and clear the iommu bases) ;)



Best regards,
Tomasz








Re: [BUG 4.15-rc7] IRQ matrix management errors

2018-01-16 Thread Keith Busch
On Wed, Jan 17, 2018 at 08:34:22AM +0100, Thomas Gleixner wrote:
> Can you trace the matrix allocations from the very beginning or tell me how
> to reproduce. I'd like to figure out why this is happening.

Sure, I'll get the irq_matrix events.

I reproduce this on a machine with 112 CPUs and 3 NVMe controllers. The
first two NVMe want 112 MSI-x vectors, and the last only 31 vectors. The
test runs 'modprobe nvme' and 'modprobe -r nvme' in a loop with 10
second delay between each step. Repro occurs within a few iterations,
sometimes already broken after the initial boot.


Re: [BUG 4.15-rc7] IRQ matrix management errors

2018-01-16 Thread Keith Busch
On Wed, Jan 17, 2018 at 08:34:22AM +0100, Thomas Gleixner wrote:
> Can you trace the matrix allocations from the very beginning or tell me how
> to reproduce. I'd like to figure out why this is happening.

Sure, I'll get the irq_matrix events.

I reproduce this on a machine with 112 CPUs and 3 NVMe controllers. The
first two NVMe want 112 MSI-x vectors, and the last only 31 vectors. The
test runs 'modprobe nvme' and 'modprobe -r nvme' in a loop with 10
second delay between each step. Repro occurs within a few iterations,
sometimes already broken after the initial boot.


Re: [PATCH v2 11/13] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-01-16 Thread JeffyChen

On 01/17/2018 03:30 PM, Tomasz Figa wrote:

>but it's possible the probe failed after calling iommu_device_set_fwnode, so
>i'll try to add some checks here, and maybe adjust probe() to prevent it
>too.

I think iommu_device_set_fwnode() is not enough for of_iommu_xlate()
to find the IOMMU. The IOMMU is actually added to the IOMMU list by
iommu_device_register(), which is last in the sequence, so I guess we
should be fine.


hmmm, the later patch would change that ;) i'll fix it in the next version.


Best regards,
Tomasz








Re: [PATCH v2 11/13] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-01-16 Thread JeffyChen

On 01/17/2018 03:30 PM, Tomasz Figa wrote:

>but it's possible the probe failed after calling iommu_device_set_fwnode, so
>i'll try to add some checks here, and maybe adjust probe() to prevent it
>too.

I think iommu_device_set_fwnode() is not enough for of_iommu_xlate()
to find the IOMMU. The IOMMU is actually added to the IOMMU list by
iommu_device_register(), which is last in the sequence, so I guess we
should be fine.


hmmm, the later patch would change that ;) i'll fix it in the next version.


Best regards,
Tomasz








Re: [PATCH v2 1/2] nvme: add tracepoint for nvme_setup_cmd

2018-01-16 Thread Johannes Thumshirn
On Tue, Jan 16, 2018 at 05:49:54PM +0100, Christoph Hellwig wrote:
> > +   trace_seq_printf(p, "slba=%llu, length=%u, control=0x%x, dsmgmt=%u, 
> > reftag=%u",
> 
> Overly long line.
> 
> > +(unsigned long long)le64_to_cpu(rw.slba),
> 
> u64 now always is an unsigned long long, no need for the cast.

Ah OK. Didn't know that. Will fix.

> > +le16_to_cpu(rw.length), le16_to_cpu(rw.control),
> > +le32_to_cpu(rw.dsmgmt), le32_to_cpu(rw.reftag));
> > +   trace_seq_putc(p, 0);
> 
> This look weird, is there a a good reason for putting a 0 character?
> 
> Also I'd be tempted to add a new trace.c file for these and make them
> dependent on whatever kernel option enables the tracing.

I was considering this as well so let's just do it. 

> 
> > --- /dev/null
> > +++ b/drivers/nvme/host/trace.h
> > @@ -0,0 +1,69 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> 
> Please add a real copyright header including the author.

I thought this is the new standard. OK will add a copyright header.

> const char *nvme_trace_parse_cmd(struct trace_seq *p, struct nvme_command 
> cmnd);
> 
> > +#define __parse_nvme_cmd(cmd) nvme_trace_parse_cmd(p, cmd)
> 
> This looks weird.

Why? For instance that's exactly what SCSI does as well and nicely hides the
implicit "p".

> > +TRACE_EVENT(nvme_setup_cmd,
> > +
> > +   TP_PROTO(struct nvme_command *cmd),
> > +
> > +   TP_ARGS(cmd),
> > +
> 
> Please remove these empty lines.

Standard coding style in include/trace/events/ that's why I adopted it.

> > +   TP_STRUCT__entry(
> > +   __field( __u8,opcode   )
> > +   __field( __u8,flags)
> > +   __field( __u16,   cid  )
> > +   __field( __le32,  nsid )
> > +   __field( __le64,  metadata )
> 
> > +   __field_struct( struct nvme_command, cmnd )
> And the additional whitespaces before and after the braces

See above.

> > +   TP_fast_assign(
> > +   __entry->opcode = cmd->common.opcode;
> > +   __entry->flags  = cmd->common.flags;
> > +   __entry->cid= cmd->common.command_id;
> > +   __entry->nsid   = cmd->common.nsid;
> > +   __entry->metadata   = cmd->common.metadata;
> > +   memcpy(&__entry->cmnd, cmd, sizeof(__entry->cmnd));
> 
> Copying the whole SQE in tracing seems rather excessive.
> 
> > +   TP_printk("nsid=%u, command_id=%u, flags=0x%x, metadata=0x%llx, 
> > cmd=(%s %s)",
> 
> Too long line.
> 
> > + le32_to_cpu(__entry->nsid), __entry->cid, __entry->flags,
> > + (unsigned long long) le64_to_cpu(__entry->metadata),
> 
> no need for the cast.
> 
> > +#undef TRACE_INCLUDE_PATH
> > +#define TRACE_INCLUDE_PATH ../../drivers/nvme/host
> 
> This seems wrong.  Instead you should make sure we include the srcdir
> in the makefile, take a look at fs/xfs/Makefile for example.

That's what dma-buf, drm and ras do so I copied it over when moving the TP
header out of include/trace/events

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850


Re: [PATCH v2 1/2] nvme: add tracepoint for nvme_setup_cmd

2018-01-16 Thread Johannes Thumshirn
On Tue, Jan 16, 2018 at 05:49:54PM +0100, Christoph Hellwig wrote:
> > +   trace_seq_printf(p, "slba=%llu, length=%u, control=0x%x, dsmgmt=%u, 
> > reftag=%u",
> 
> Overly long line.
> 
> > +(unsigned long long)le64_to_cpu(rw.slba),
> 
> u64 now always is an unsigned long long, no need for the cast.

Ah OK. Didn't know that. Will fix.

> > +le16_to_cpu(rw.length), le16_to_cpu(rw.control),
> > +le32_to_cpu(rw.dsmgmt), le32_to_cpu(rw.reftag));
> > +   trace_seq_putc(p, 0);
> 
> This look weird, is there a a good reason for putting a 0 character?
> 
> Also I'd be tempted to add a new trace.c file for these and make them
> dependent on whatever kernel option enables the tracing.

I was considering this as well so let's just do it. 

> 
> > --- /dev/null
> > +++ b/drivers/nvme/host/trace.h
> > @@ -0,0 +1,69 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> 
> Please add a real copyright header including the author.

I thought this is the new standard. OK will add a copyright header.

> const char *nvme_trace_parse_cmd(struct trace_seq *p, struct nvme_command 
> cmnd);
> 
> > +#define __parse_nvme_cmd(cmd) nvme_trace_parse_cmd(p, cmd)
> 
> This looks weird.

Why? For instance that's exactly what SCSI does as well and nicely hides the
implicit "p".

> > +TRACE_EVENT(nvme_setup_cmd,
> > +
> > +   TP_PROTO(struct nvme_command *cmd),
> > +
> > +   TP_ARGS(cmd),
> > +
> 
> Please remove these empty lines.

Standard coding style in include/trace/events/ that's why I adopted it.

> > +   TP_STRUCT__entry(
> > +   __field( __u8,opcode   )
> > +   __field( __u8,flags)
> > +   __field( __u16,   cid  )
> > +   __field( __le32,  nsid )
> > +   __field( __le64,  metadata )
> 
> > +   __field_struct( struct nvme_command, cmnd )
> And the additional whitespaces before and after the braces

See above.

> > +   TP_fast_assign(
> > +   __entry->opcode = cmd->common.opcode;
> > +   __entry->flags  = cmd->common.flags;
> > +   __entry->cid= cmd->common.command_id;
> > +   __entry->nsid   = cmd->common.nsid;
> > +   __entry->metadata   = cmd->common.metadata;
> > +   memcpy(&__entry->cmnd, cmd, sizeof(__entry->cmnd));
> 
> Copying the whole SQE in tracing seems rather excessive.
> 
> > +   TP_printk("nsid=%u, command_id=%u, flags=0x%x, metadata=0x%llx, 
> > cmd=(%s %s)",
> 
> Too long line.
> 
> > + le32_to_cpu(__entry->nsid), __entry->cid, __entry->flags,
> > + (unsigned long long) le64_to_cpu(__entry->metadata),
> 
> no need for the cast.
> 
> > +#undef TRACE_INCLUDE_PATH
> > +#define TRACE_INCLUDE_PATH ../../drivers/nvme/host
> 
> This seems wrong.  Instead you should make sure we include the srcdir
> in the makefile, take a look at fs/xfs/Makefile for example.

That's what dma-buf, drm and ras do so I copied it over when moving the TP
header out of include/trace/events

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850


Re: [PATCH v2 01/13] iommu/rockchip: Request irqs in rk_iommu_probe()

2018-01-16 Thread JeffyChen

Hi Tomasz,

On 01/17/2018 03:16 PM, Tomasz Figa wrote:

>>
>>This lacks consistency. of_irq_count() is used for counting, but
>>platform_get_irq() is used for getting. Either platform_ or of_ API
>>should be used for both and I'd lean for platform_, since it's more
>>general.

>
>hmmm, right, i was thinking of removing num_irq, and do something like:
>while (nr++) {
>   err = platform_get_irq(dev, nr);
>   if (err == -EPROBE_DEFER)
>  break;
>   if (err < 0)
>  return err;
>   
>}
>
>but forgot to do that..

Was there anything wrong with platform_irq_count() used by existing code?


just thought the platform_irq_count might ignore some errors(except for 
EPROBE_DEFER):


int platform_irq_count(struct platform_device *dev)
{
int ret, nr = 0;

while ((ret = platform_get_irq(dev, nr)) >= 0)
nr++;

if (ret == -EPROBE_DEFER)
return ret;

return nr;
}

but guess that would not matter..




>

>>

>>>+   if (irq < 0) {
>>>+   dev_err(dev, "Failed to get IRQ, %d\n", irq);
>>>  return -ENXIO;
>>>  }
>>>+   err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
>>>+  IRQF_SHARED, dev_name(dev),
>>>iommu);
>>>+   if (err)
>>>+   return err;
>>>  }

>>
>>
>>Looks like there is some more initialization below. Is the driver okay
>>with the IRQ being potentially fired right here? (Shared IRQ handlers
>>might be run at request_irq() time for testing.)
>>

>right, forget about that. maybe we can check iommu->domain not NULL in
>rk_iommu_irq()

Maybe we could just move IRQ requesting to the end of probe?


ok, that should work too.

and maybe we should also check power status in the irq handler? if it 
get fired after powered off...



Best regards,
Tomasz








Re: [PATCH v2 01/13] iommu/rockchip: Request irqs in rk_iommu_probe()

2018-01-16 Thread JeffyChen

Hi Tomasz,

On 01/17/2018 03:16 PM, Tomasz Figa wrote:

>>
>>This lacks consistency. of_irq_count() is used for counting, but
>>platform_get_irq() is used for getting. Either platform_ or of_ API
>>should be used for both and I'd lean for platform_, since it's more
>>general.

>
>hmmm, right, i was thinking of removing num_irq, and do something like:
>while (nr++) {
>   err = platform_get_irq(dev, nr);
>   if (err == -EPROBE_DEFER)
>  break;
>   if (err < 0)
>  return err;
>   
>}
>
>but forgot to do that..

Was there anything wrong with platform_irq_count() used by existing code?


just thought the platform_irq_count might ignore some errors(except for 
EPROBE_DEFER):


int platform_irq_count(struct platform_device *dev)
{
int ret, nr = 0;

while ((ret = platform_get_irq(dev, nr)) >= 0)
nr++;

if (ret == -EPROBE_DEFER)
return ret;

return nr;
}

but guess that would not matter..




>

>>

>>>+   if (irq < 0) {
>>>+   dev_err(dev, "Failed to get IRQ, %d\n", irq);
>>>  return -ENXIO;
>>>  }
>>>+   err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
>>>+  IRQF_SHARED, dev_name(dev),
>>>iommu);
>>>+   if (err)
>>>+   return err;
>>>  }

>>
>>
>>Looks like there is some more initialization below. Is the driver okay
>>with the IRQ being potentially fired right here? (Shared IRQ handlers
>>might be run at request_irq() time for testing.)
>>

>right, forget about that. maybe we can check iommu->domain not NULL in
>rk_iommu_irq()

Maybe we could just move IRQ requesting to the end of probe?


ok, that should work too.

and maybe we should also check power status in the irq handler? if it 
get fired after powered off...



Best regards,
Tomasz








Re: Power domain clock warnings on recent next

2018-01-16 Thread Krzysztof Kozlowski
On Wed, Jan 17, 2018 at 7:25 AM, Marek Szyprowski
 wrote:
> Hi Krzysztof,
>
> On 2018-01-16 21:07, Krzysztof Kozlowski wrote:
>>
>> Hi everyone,
>>
>> Anyone already noticed or started bisecting warnings coming from
>> clk_core_disable_lock/exynos_pd_power on recent linux-next?
>
>
> Yes, I've noticed it early this week and prepared a patch:
> https://www.spinics.net/lists/arm-kernel/msg628881.html

Thanks!

Best regards,
Krzysztof


Re: Power domain clock warnings on recent next

2018-01-16 Thread Krzysztof Kozlowski
On Wed, Jan 17, 2018 at 7:25 AM, Marek Szyprowski
 wrote:
> Hi Krzysztof,
>
> On 2018-01-16 21:07, Krzysztof Kozlowski wrote:
>>
>> Hi everyone,
>>
>> Anyone already noticed or started bisecting warnings coming from
>> clk_core_disable_lock/exynos_pd_power on recent linux-next?
>
>
> Yes, I've noticed it early this week and prepared a patch:
> https://www.spinics.net/lists/arm-kernel/msg628881.html

Thanks!

Best regards,
Krzysztof


Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-16 Thread Changwei Ge
It looks good to me.

Reviewed-by: Changwei Ge 

On 2017/12/14 13:16, Gang He wrote:
> As you know, ocfs2 has support trim the underlying disk via
> fstrim command. But there is a problem, ocfs2 is a shared disk
> cluster file system, if the user configures a scheduled fstrim
> job on each file system node, this will trigger multiple nodes
> trim a shared disk simultaneously, it is very wasteful for CPU
> and IO consumption, also might negatively affect the lifetime
> of poor-quality SSD devices.
> Then, we introduce a trimfs dlm lock to communicate with each
> other in this case, which will make only one fstrim command to
> do the trimming on a shared disk among the cluster, the fstrim
> commands from the other nodes should wait for the first fstrim
> to finish and returned success directly, to avoid running a the
> same trim on the shared disk again.
> 
> Compare with first version, I change the fstrim commands' returned
> value and behavior in case which meets a fstrim command is running
> on a shared disk.
> 
> Signed-off-by: Gang He 
> ---
>   fs/ocfs2/alloc.c | 44 
>   1 file changed, 44 insertions(+)
> 
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index ab5105f..5c9c3e2 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, struct 
> fstrim_range *range)
>   struct buffer_head *gd_bh = NULL;
>   struct ocfs2_dinode *main_bm;
>   struct ocfs2_group_desc *gd = NULL;
> + struct ocfs2_trim_fs_info info, *pinfo = NULL;
>   
>   start = range->start >> osb->s_clustersize_bits;
>   len = range->len >> osb->s_clustersize_bits;
> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, struct 
> fstrim_range *range)
>   
>   trace_ocfs2_trim_fs(start, len, minlen);
>   
> + ocfs2_trim_fs_lock_res_init(osb);
> + ret = ocfs2_trim_fs_lock(osb, NULL, 1);
> + if (ret < 0) {
> + if (ret != -EAGAIN) {
> + mlog_errno(ret);
> + ocfs2_trim_fs_lock_res_uninit(osb);
> + goto out_unlock;
> + }
> +
> + mlog(ML_NOTICE, "Wait for trim on device (%s) to "
> +  "finish, which is running from another node.\n",
> +  osb->dev_str);
> + ret = ocfs2_trim_fs_lock(osb, , 0);
> + if (ret < 0) {
> + mlog_errno(ret);
> + ocfs2_trim_fs_lock_res_uninit(osb);
> + goto out_unlock;
> + }
> +
> + if (info.tf_valid && info.tf_success &&
> + info.tf_start == start && info.tf_len == len &&
> + info.tf_minlen == minlen) {
> + /* Avoid sending duplicated trim to a shared device */
> + mlog(ML_NOTICE, "The same trim on device (%s) was "
> +  "just done from node (%u), return.\n",
> +  osb->dev_str, info.tf_nodenum);
> + range->len = info.tf_trimlen;
> + goto out_trimunlock;
> + }
> + }
> +
> + info.tf_nodenum = osb->node_num;
> + info.tf_start = start;
> + info.tf_len = len;
> + info.tf_minlen = minlen;
> +
>   /* Determine first and last group to examine based on start and len */
>   first_group = ocfs2_which_cluster_group(main_bm_inode, start);
>   if (first_group == osb->first_cluster_group_blkno)
> @@ -7463,6 +7500,13 @@ int ocfs2_trim_fs(struct super_block *sb, struct 
> fstrim_range *range)
>   group += ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg);
>   }
>   range->len = trimmed * sb->s_blocksize;
> +
> + info.tf_trimlen = range->len;
> + info.tf_success = (ret ? 0 : 1);
> + pinfo = 
> +out_trimunlock:
> + ocfs2_trim_fs_unlock(osb, pinfo);
> + ocfs2_trim_fs_lock_res_uninit(osb);
>   out_unlock:
>   ocfs2_inode_unlock(main_bm_inode, 0);
>   brelse(main_bm_bh);
> 


Re: [Ocfs2-devel] [PATCH v2 2/2] ocfs2: add trimfs lock to avoid duplicated trims in cluster

2018-01-16 Thread Changwei Ge
It looks good to me.

Reviewed-by: Changwei Ge 

On 2017/12/14 13:16, Gang He wrote:
> As you know, ocfs2 has support trim the underlying disk via
> fstrim command. But there is a problem, ocfs2 is a shared disk
> cluster file system, if the user configures a scheduled fstrim
> job on each file system node, this will trigger multiple nodes
> trim a shared disk simultaneously, it is very wasteful for CPU
> and IO consumption, also might negatively affect the lifetime
> of poor-quality SSD devices.
> Then, we introduce a trimfs dlm lock to communicate with each
> other in this case, which will make only one fstrim command to
> do the trimming on a shared disk among the cluster, the fstrim
> commands from the other nodes should wait for the first fstrim
> to finish and returned success directly, to avoid running a the
> same trim on the shared disk again.
> 
> Compare with first version, I change the fstrim commands' returned
> value and behavior in case which meets a fstrim command is running
> on a shared disk.
> 
> Signed-off-by: Gang He 
> ---
>   fs/ocfs2/alloc.c | 44 
>   1 file changed, 44 insertions(+)
> 
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index ab5105f..5c9c3e2 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -7382,6 +7382,7 @@ int ocfs2_trim_fs(struct super_block *sb, struct 
> fstrim_range *range)
>   struct buffer_head *gd_bh = NULL;
>   struct ocfs2_dinode *main_bm;
>   struct ocfs2_group_desc *gd = NULL;
> + struct ocfs2_trim_fs_info info, *pinfo = NULL;
>   
>   start = range->start >> osb->s_clustersize_bits;
>   len = range->len >> osb->s_clustersize_bits;
> @@ -7419,6 +7420,42 @@ int ocfs2_trim_fs(struct super_block *sb, struct 
> fstrim_range *range)
>   
>   trace_ocfs2_trim_fs(start, len, minlen);
>   
> + ocfs2_trim_fs_lock_res_init(osb);
> + ret = ocfs2_trim_fs_lock(osb, NULL, 1);
> + if (ret < 0) {
> + if (ret != -EAGAIN) {
> + mlog_errno(ret);
> + ocfs2_trim_fs_lock_res_uninit(osb);
> + goto out_unlock;
> + }
> +
> + mlog(ML_NOTICE, "Wait for trim on device (%s) to "
> +  "finish, which is running from another node.\n",
> +  osb->dev_str);
> + ret = ocfs2_trim_fs_lock(osb, , 0);
> + if (ret < 0) {
> + mlog_errno(ret);
> + ocfs2_trim_fs_lock_res_uninit(osb);
> + goto out_unlock;
> + }
> +
> + if (info.tf_valid && info.tf_success &&
> + info.tf_start == start && info.tf_len == len &&
> + info.tf_minlen == minlen) {
> + /* Avoid sending duplicated trim to a shared device */
> + mlog(ML_NOTICE, "The same trim on device (%s) was "
> +  "just done from node (%u), return.\n",
> +  osb->dev_str, info.tf_nodenum);
> + range->len = info.tf_trimlen;
> + goto out_trimunlock;
> + }
> + }
> +
> + info.tf_nodenum = osb->node_num;
> + info.tf_start = start;
> + info.tf_len = len;
> + info.tf_minlen = minlen;
> +
>   /* Determine first and last group to examine based on start and len */
>   first_group = ocfs2_which_cluster_group(main_bm_inode, start);
>   if (first_group == osb->first_cluster_group_blkno)
> @@ -7463,6 +7500,13 @@ int ocfs2_trim_fs(struct super_block *sb, struct 
> fstrim_range *range)
>   group += ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg);
>   }
>   range->len = trimmed * sb->s_blocksize;
> +
> + info.tf_trimlen = range->len;
> + info.tf_success = (ret ? 0 : 1);
> + pinfo = 
> +out_trimunlock:
> + ocfs2_trim_fs_unlock(osb, pinfo);
> + ocfs2_trim_fs_lock_res_uninit(osb);
>   out_unlock:
>   ocfs2_inode_unlock(main_bm_inode, 0);
>   brelse(main_bm_bh);
> 


Re: [Ocfs2-devel] [PATCH v2 1/2] ocfs2: add trimfs dlm lock resource

2018-01-16 Thread Changwei Ge
It looks good to me.

Reviewed-by: Changwei Ge 

On 2017/12/14 13:16, Gang He wrote:
> Introduce a new dlm lock resource, which will be used to
> communicate during fstrim a ocfs2 device from cluster nodes.
> 
> Signed-off-by: Gang He 
> ---
>   fs/ocfs2/dlmglue.c  | 86 
> +
>   fs/ocfs2/dlmglue.h  | 29 +
>   fs/ocfs2/ocfs2.h|  1 +
>   fs/ocfs2/ocfs2_lockid.h |  5 +++
>   4 files changed, 121 insertions(+)
> 
> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 4689940..5615747 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -259,6 +259,10 @@ struct ocfs2_lock_res_ops {
>   .flags  = 0,
>   };
>   
> +static struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
> + .flags  = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
> +};
> +
>   static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
>   .flags  = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
>   };
> @@ -676,6 +680,24 @@ static void ocfs2_nfs_sync_lock_res_init(struct 
> ocfs2_lock_res *res,
>  _nfs_sync_lops, osb);
>   }
>   
> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
> +{
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + ocfs2_lock_res_init_once(lockres);
> + ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
> + ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
> +_trim_fs_lops, osb);
> +}
> +
> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
> +{
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + ocfs2_simple_drop_lockres(osb, lockres);
> + ocfs2_lock_res_free(lockres);
> +}
> +
>   static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
>   struct ocfs2_super *osb)
>   {
> @@ -2745,6 +2767,70 @@ void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, 
> int ex)
>ex ? LKM_EXMODE : LKM_PRMODE);
>   }
>   
> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
> +struct ocfs2_trim_fs_info *info, int trylock)
> +{
> + int status;
> + struct ocfs2_trim_fs_lvb *lvb;
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + if (info)
> + info->tf_valid = 0;
> +
> + if (ocfs2_is_hard_readonly(osb))
> + return -EROFS;
> +
> + if (ocfs2_mount_local(osb))
> + return 0;
> +
> + status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
> + trylock ? DLM_LKF_NOQUEUE : 0, 0);
> + if (status < 0) {
> + if (status != -EAGAIN)
> + mlog_errno(status);
> + return status;
> + }
> +
> + if (info) {
> + lvb = ocfs2_dlm_lvb(>l_lksb);
> + if (ocfs2_dlm_lvb_valid(>l_lksb) &&
> + lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
> + info->tf_valid = 1;
> + info->tf_success = lvb->lvb_success;
> + info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
> + info->tf_start = be64_to_cpu(lvb->lvb_start);
> + info->tf_len = be64_to_cpu(lvb->lvb_len);
> + info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
> + info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
> + }
> + }
> +
> + return status;
> +}
> +
> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
> +   struct ocfs2_trim_fs_info *info)
> +{
> + struct ocfs2_trim_fs_lvb *lvb;
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + if (ocfs2_mount_local(osb))
> + return;
> +
> + if (info) {
> + lvb = ocfs2_dlm_lvb(>l_lksb);
> + lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
> + lvb->lvb_success = info->tf_success;
> + lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
> + lvb->lvb_start = cpu_to_be64(info->tf_start);
> + lvb->lvb_len = cpu_to_be64(info->tf_len);
> + lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
> + lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
> + }
> +
> + ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
> +}
> +
>   int ocfs2_dentry_lock(struct dentry *dentry, int ex)
>   {
>   int ret;
> diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
> index a7fc18b..2253688 100644
> --- a/fs/ocfs2/dlmglue.h
> +++ b/fs/ocfs2/dlmglue.h
> @@ -70,6 +70,29 @@ struct ocfs2_orphan_scan_lvb {
>   __be32  lvb_os_seqno;
>   };
>   
> +#define OCFS2_TRIMFS_LVB_VERSION 1
> +
> +struct ocfs2_trim_fs_lvb {
> + __u8lvb_version;
> + __u8lvb_success;
> + __u8lvb_reserved[2];
> + __be32  lvb_nodenum;
> + __be64  

Re: [Ocfs2-devel] [PATCH v2 1/2] ocfs2: add trimfs dlm lock resource

2018-01-16 Thread Changwei Ge
It looks good to me.

Reviewed-by: Changwei Ge 

On 2017/12/14 13:16, Gang He wrote:
> Introduce a new dlm lock resource, which will be used to
> communicate during fstrim a ocfs2 device from cluster nodes.
> 
> Signed-off-by: Gang He 
> ---
>   fs/ocfs2/dlmglue.c  | 86 
> +
>   fs/ocfs2/dlmglue.h  | 29 +
>   fs/ocfs2/ocfs2.h|  1 +
>   fs/ocfs2/ocfs2_lockid.h |  5 +++
>   4 files changed, 121 insertions(+)
> 
> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 4689940..5615747 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -259,6 +259,10 @@ struct ocfs2_lock_res_ops {
>   .flags  = 0,
>   };
>   
> +static struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
> + .flags  = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
> +};
> +
>   static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
>   .flags  = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
>   };
> @@ -676,6 +680,24 @@ static void ocfs2_nfs_sync_lock_res_init(struct 
> ocfs2_lock_res *res,
>  _nfs_sync_lops, osb);
>   }
>   
> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
> +{
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + ocfs2_lock_res_init_once(lockres);
> + ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
> + ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
> +_trim_fs_lops, osb);
> +}
> +
> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
> +{
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + ocfs2_simple_drop_lockres(osb, lockres);
> + ocfs2_lock_res_free(lockres);
> +}
> +
>   static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
>   struct ocfs2_super *osb)
>   {
> @@ -2745,6 +2767,70 @@ void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, 
> int ex)
>ex ? LKM_EXMODE : LKM_PRMODE);
>   }
>   
> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
> +struct ocfs2_trim_fs_info *info, int trylock)
> +{
> + int status;
> + struct ocfs2_trim_fs_lvb *lvb;
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + if (info)
> + info->tf_valid = 0;
> +
> + if (ocfs2_is_hard_readonly(osb))
> + return -EROFS;
> +
> + if (ocfs2_mount_local(osb))
> + return 0;
> +
> + status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
> + trylock ? DLM_LKF_NOQUEUE : 0, 0);
> + if (status < 0) {
> + if (status != -EAGAIN)
> + mlog_errno(status);
> + return status;
> + }
> +
> + if (info) {
> + lvb = ocfs2_dlm_lvb(>l_lksb);
> + if (ocfs2_dlm_lvb_valid(>l_lksb) &&
> + lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
> + info->tf_valid = 1;
> + info->tf_success = lvb->lvb_success;
> + info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
> + info->tf_start = be64_to_cpu(lvb->lvb_start);
> + info->tf_len = be64_to_cpu(lvb->lvb_len);
> + info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
> + info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
> + }
> + }
> +
> + return status;
> +}
> +
> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
> +   struct ocfs2_trim_fs_info *info)
> +{
> + struct ocfs2_trim_fs_lvb *lvb;
> + struct ocfs2_lock_res *lockres = >osb_trim_fs_lockres;
> +
> + if (ocfs2_mount_local(osb))
> + return;
> +
> + if (info) {
> + lvb = ocfs2_dlm_lvb(>l_lksb);
> + lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
> + lvb->lvb_success = info->tf_success;
> + lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
> + lvb->lvb_start = cpu_to_be64(info->tf_start);
> + lvb->lvb_len = cpu_to_be64(info->tf_len);
> + lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
> + lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
> + }
> +
> + ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
> +}
> +
>   int ocfs2_dentry_lock(struct dentry *dentry, int ex)
>   {
>   int ret;
> diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
> index a7fc18b..2253688 100644
> --- a/fs/ocfs2/dlmglue.h
> +++ b/fs/ocfs2/dlmglue.h
> @@ -70,6 +70,29 @@ struct ocfs2_orphan_scan_lvb {
>   __be32  lvb_os_seqno;
>   };
>   
> +#define OCFS2_TRIMFS_LVB_VERSION 1
> +
> +struct ocfs2_trim_fs_lvb {
> + __u8lvb_version;
> + __u8lvb_success;
> + __u8lvb_reserved[2];
> + __be32  lvb_nodenum;
> + __be64  lvb_start;
> + __be64  lvb_len;
> + 

Re: WARNING in can_rcv

2018-01-16 Thread Dmitry Vyukov
On Wed, Jan 17, 2018 at 8:12 AM, Eric Biggers  wrote:
> On Wed, Jan 17, 2018 at 07:39:24AM +0100, Oliver Hartkopp wrote:
>>
>>
>> On 01/16/2018 07:11 PM, Dmitry Vyukov wrote:
>> > On Tue, Jan 16, 2018 at 7:07 PM, Marc Kleine-Budde  
>> > wrote:
>> > > On 01/16/2018 06:58 PM, syzbot wrote:
>> > > > Hello,
>> > > >
>> > > > syzkaller hit the following crash on
>> > > > a8750ddca918032d6349adbf9a4b6555e7db20da
>> > > > git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
>> > > > compiler: gcc (GCC) 7.1.1 20170620
>> > > > .config is attached
>> > > > Raw console output is attached.
>> > > > C reproducer is attached
>> > > > syzkaller reproducer is attached. See https://goo.gl/kgGztJ
>> > > > for information about syzkaller reproducers
>> > > >
>> > > >
>> > > > IMPORTANT: if you fix the bug, please add the following tag to the 
>> > > > commit:
>> > > > Reported-by: syzbot+4386709c0c1284dca...@syzkaller.appspotmail.com
>> > > > It will help syzbot understand when the bug is fixed. See footer for
>> > > > details.
>> > > > If you forward the report, please keep this part and the footer.
>> > > >
>> > > > device eql entered promiscuous mode
>> > > > [ cut here ]
>> > > > PF_CAN: dropped non conform CAN skbuf: dev type 65534, len 42, datalen >> > > > 0
>> > > > WARNING: CPU: 0 PID: 3650 at net/can/af_can.c:729 can_rcv+0x1c5/0x200
>> > > > net/can/af_can.c:724
>> > > > Kernel panic - not syncing: panic_on_warn set ...
>> > >
>> > > Invalid packages generate a warning (WARN_ONCE()), and you have
>> > > panic_on_warn active. Should we better silently drop these CAN packages?
>> >
>> > Hi,
>> >
>> > pr_warn_once() will be more appropriate. It prints a single line.
>> >
>>
>> The idea behind this WARN() is to detect really bad things that might have
>> happen on network driver level:
>>
>> The CAN subsystem registers with dev_add_pack() for ETH_P_CAN and
>> ETH_P_CANFD only. These ETH_P_ types are only allowed to be created by CAN
>> network devices (like vcan, vxcan, and real CAN drivers).
>>
>> I don't have any strong opinion on using WARN() or pr_warn_once().
>> Is this detected violation worth using WARN(), as something already must
>> have gone really wrong to trigger this issue?
>>
>
> WARN() indicates a kernel bug.  If it's instead "userspace did something
> stupid", or "someone sent some unexpected network packet", it needs to be
> pr_warn_once(), pr_warn_ratelimited(), or removed entirely.


The packet comes from tun device. We could change tun to filter out
such packages earlier. However, in the context of "syzkaller support
for AF_CAN" discussion, it would actually be useful for fuzzer to be
able emit can packets for testing purposes. For example, for tcp it
can not just emit random packets, it can build complex user<->network
interactions, for example, open a listening socket, connect to it
"from outside", accept the connection, and then exchange some data
over the active connection. It could do the same for can.
Is it possible to allow can packets via tun? Then we could leave this
WARNING in place. tun/vcan are contained within a net namespace, so
this should not be a security problem, right?
Or is there a way to do the same with vcan? If yes, then fuzzer could
use vcan. But then we need some fix for this WARNING: either change it
to pr_warn or change tun (I don't have strong preference which one).


Re: WARNING in can_rcv

2018-01-16 Thread Dmitry Vyukov
On Wed, Jan 17, 2018 at 8:12 AM, Eric Biggers  wrote:
> On Wed, Jan 17, 2018 at 07:39:24AM +0100, Oliver Hartkopp wrote:
>>
>>
>> On 01/16/2018 07:11 PM, Dmitry Vyukov wrote:
>> > On Tue, Jan 16, 2018 at 7:07 PM, Marc Kleine-Budde  
>> > wrote:
>> > > On 01/16/2018 06:58 PM, syzbot wrote:
>> > > > Hello,
>> > > >
>> > > > syzkaller hit the following crash on
>> > > > a8750ddca918032d6349adbf9a4b6555e7db20da
>> > > > git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
>> > > > compiler: gcc (GCC) 7.1.1 20170620
>> > > > .config is attached
>> > > > Raw console output is attached.
>> > > > C reproducer is attached
>> > > > syzkaller reproducer is attached. See https://goo.gl/kgGztJ
>> > > > for information about syzkaller reproducers
>> > > >
>> > > >
>> > > > IMPORTANT: if you fix the bug, please add the following tag to the 
>> > > > commit:
>> > > > Reported-by: syzbot+4386709c0c1284dca...@syzkaller.appspotmail.com
>> > > > It will help syzbot understand when the bug is fixed. See footer for
>> > > > details.
>> > > > If you forward the report, please keep this part and the footer.
>> > > >
>> > > > device eql entered promiscuous mode
>> > > > [ cut here ]
>> > > > PF_CAN: dropped non conform CAN skbuf: dev type 65534, len 42, datalen >> > > > 0
>> > > > WARNING: CPU: 0 PID: 3650 at net/can/af_can.c:729 can_rcv+0x1c5/0x200
>> > > > net/can/af_can.c:724
>> > > > Kernel panic - not syncing: panic_on_warn set ...
>> > >
>> > > Invalid packages generate a warning (WARN_ONCE()), and you have
>> > > panic_on_warn active. Should we better silently drop these CAN packages?
>> >
>> > Hi,
>> >
>> > pr_warn_once() will be more appropriate. It prints a single line.
>> >
>>
>> The idea behind this WARN() is to detect really bad things that might have
>> happen on network driver level:
>>
>> The CAN subsystem registers with dev_add_pack() for ETH_P_CAN and
>> ETH_P_CANFD only. These ETH_P_ types are only allowed to be created by CAN
>> network devices (like vcan, vxcan, and real CAN drivers).
>>
>> I don't have any strong opinion on using WARN() or pr_warn_once().
>> Is this detected violation worth using WARN(), as something already must
>> have gone really wrong to trigger this issue?
>>
>
> WARN() indicates a kernel bug.  If it's instead "userspace did something
> stupid", or "someone sent some unexpected network packet", it needs to be
> pr_warn_once(), pr_warn_ratelimited(), or removed entirely.


The packet comes from tun device. We could change tun to filter out
such packages earlier. However, in the context of "syzkaller support
for AF_CAN" discussion, it would actually be useful for fuzzer to be
able emit can packets for testing purposes. For example, for tcp it
can not just emit random packets, it can build complex user<->network
interactions, for example, open a listening socket, connect to it
"from outside", accept the connection, and then exchange some data
over the active connection. It could do the same for can.
Is it possible to allow can packets via tun? Then we could leave this
WARNING in place. tun/vcan are contained within a net namespace, so
this should not be a security problem, right?
Or is there a way to do the same with vcan? If yes, then fuzzer could
use vcan. But then we need some fix for this WARNING: either change it
to pr_warn or change tun (I don't have strong preference which one).


Re: [PATCH v2 12/13] iommu/rockchip: Add runtime PM support

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:26 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> Thanks for your reply.
>
> On 01/17/2018 02:20 PM, Tomasz Figa wrote:
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> [snip]
>>>
>>> +static int rk_iommu_startup(struct rk_iommu *iommu)
>>>   {
>>> -   struct rk_iommu *iommu;
>>> +   struct iommu_domain *domain = iommu->domain;
>>>  struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
>>> -   unsigned long flags;
>>>  int ret, i;
>>>
>>> -   /*
>>> -* Allow 'virtual devices' (e.g., drm) to attach to domain.
>>> -* Such a device does not belong to an iommu group.
>>> -*/
>>> -   iommu = rk_iommu_from_dev(dev);
>>> -   if (!iommu)
>>> -   return 0;
>>> -
>>> -   if (iommu->domain)
>>> -   rk_iommu_detach_device(iommu->domain, dev);
>>> -
>>>  ret = rk_iommu_enable_clocks(iommu);
>>>  if (ret)
>>>  return ret;
>>>
>>
>> Don't we need to check here (and in _shutdown() too) if we have a
>> domain attached?
>
> hmmm, right, the startup might been called by resume, so should check
> iommu->domain here.
>
> but the shutdown would be called at the end of detach or suspend, it could
> be not attached or attached.

If startup might be called by resume, without domain attached, what
prevents shutdown from being called by suspend after that resume,
still without domain attached? Is it guaranteed that if resume is
called, someone will attach a domain before suspend is called?

Best regards,
Tomasz


Re: [PATCH v2 12/13] iommu/rockchip: Add runtime PM support

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:26 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> Thanks for your reply.
>
> On 01/17/2018 02:20 PM, Tomasz Figa wrote:
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> [snip]
>>>
>>> +static int rk_iommu_startup(struct rk_iommu *iommu)
>>>   {
>>> -   struct rk_iommu *iommu;
>>> +   struct iommu_domain *domain = iommu->domain;
>>>  struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
>>> -   unsigned long flags;
>>>  int ret, i;
>>>
>>> -   /*
>>> -* Allow 'virtual devices' (e.g., drm) to attach to domain.
>>> -* Such a device does not belong to an iommu group.
>>> -*/
>>> -   iommu = rk_iommu_from_dev(dev);
>>> -   if (!iommu)
>>> -   return 0;
>>> -
>>> -   if (iommu->domain)
>>> -   rk_iommu_detach_device(iommu->domain, dev);
>>> -
>>>  ret = rk_iommu_enable_clocks(iommu);
>>>  if (ret)
>>>  return ret;
>>>
>>
>> Don't we need to check here (and in _shutdown() too) if we have a
>> domain attached?
>
> hmmm, right, the startup might been called by resume, so should check
> iommu->domain here.
>
> but the shutdown would be called at the end of detach or suspend, it could
> be not attached or attached.

If startup might be called by resume, without domain attached, what
prevents shutdown from being called by suspend after that resume,
still without domain attached? Is it guaranteed that if resume is
called, someone will attach a domain before suspend is called?

Best regards,
Tomasz


Re: [PATCH v3] retpoline: Add retpoline tag to VERMAGIC

2018-01-16 Thread Thomas Gleixner
On Tue, 16 Jan 2018, Andi Kleen wrote:

> On Tue, Jan 16, 2018 at 10:24:53PM +0100, Thomas Gleixner wrote:
> > On Tue, 16 Jan 2018, Andi Kleen wrote:
> > 
> > > From: Andi Kleen 
> > > 
> > > Add a marker for retpoline to the module VERMAGIC. This catches
> > > the case when a non RETPOLINE compiled module gets loaded into
> > > a retpoline kernel, making it insecure.
> > > 
> > > It doesn't handle the case when retpoline has been runtime disabled.
> > > Even in this case the match of the retcompile status will be enforced.
> > > This implies that even with retpoline run time disabled all modules
> > > loaded need to be recompiled.
> > > 
> > > This supersedes an earlier patch that did the same checking using
> > > a new module tag (so it's really a v3)
> > > 
> > > Signed-off-by: Andi Kleen 
> > 
> > Acked-by: Thomas Gleixner 
> 
> Thanks. Through which tree should this go?
> Or Linus, could you take it directly?

I can route it through x86/pti where I have still stuff to send linuswards.

Thanks,

tglx


Re: [PATCH v3] retpoline: Add retpoline tag to VERMAGIC

2018-01-16 Thread Thomas Gleixner
On Tue, 16 Jan 2018, Andi Kleen wrote:

> On Tue, Jan 16, 2018 at 10:24:53PM +0100, Thomas Gleixner wrote:
> > On Tue, 16 Jan 2018, Andi Kleen wrote:
> > 
> > > From: Andi Kleen 
> > > 
> > > Add a marker for retpoline to the module VERMAGIC. This catches
> > > the case when a non RETPOLINE compiled module gets loaded into
> > > a retpoline kernel, making it insecure.
> > > 
> > > It doesn't handle the case when retpoline has been runtime disabled.
> > > Even in this case the match of the retcompile status will be enforced.
> > > This implies that even with retpoline run time disabled all modules
> > > loaded need to be recompiled.
> > > 
> > > This supersedes an earlier patch that did the same checking using
> > > a new module tag (so it's really a v3)
> > > 
> > > Signed-off-by: Andi Kleen 
> > 
> > Acked-by: Thomas Gleixner 
> 
> Thanks. Through which tree should this go?
> Or Linus, could you take it directly?

I can route it through x86/pti where I have still stuff to send linuswards.

Thanks,

tglx


[PATCH] x86/apic: Replace the redundant macros with an empty stub

2018-01-16 Thread Dou Liyang
The X86_LOCAL_APIC is depended on CONFIG X86_64, that means if
CONFIG_X86_64=y, the X86_LOCAL_APIC must be y too.

So, using

  if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)

... is redundant.

Remove the redundant macros and add an empty stub instead. also add some
comments for init_bsp_APIC().

Signed-off-by: Dou Liyang 
---
 arch/x86/include/asm/apic.h | 1 +
 arch/x86/kernel/irqinit.c   | 9 +++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 98722773391d..6e1990d69865 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -183,6 +183,7 @@ static inline void disable_local_APIC(void) { }
 # define setup_boot_APIC_clock x86_init_noop
 # define setup_secondary_APIC_clock x86_init_noop
 static inline void lapic_update_tsc_freq(void) { }
+static inline void init_bsp_APIC(void) { }
 static inline void apic_intr_mode_init(void) { }
 static inline void lapic_assign_system_vectors(void) { }
 static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { }
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index a539410c4ea9..a0e41397558e 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -61,9 +61,14 @@ void __init init_ISA_irqs(void)
struct irq_chip *chip = legacy_pic->chip;
int i;
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+   /*
+* Try to setup the through-local-APIC virtual wire mode earlier.
+*
+* In some 32bit UP machines whose APIC has been disabled by BIOS
+* and re-enabled by "lapic", it hangs at boot time without this.
+*/
init_bsp_APIC();
-#endif
+
legacy_pic->init(0);
 
for (i = 0; i < nr_legacy_irqs(); i++)
-- 
2.14.3





[PATCH] x86/apic: Replace the redundant macros with an empty stub

2018-01-16 Thread Dou Liyang
The X86_LOCAL_APIC is depended on CONFIG X86_64, that means if
CONFIG_X86_64=y, the X86_LOCAL_APIC must be y too.

So, using

  if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)

... is redundant.

Remove the redundant macros and add an empty stub instead. also add some
comments for init_bsp_APIC().

Signed-off-by: Dou Liyang 
---
 arch/x86/include/asm/apic.h | 1 +
 arch/x86/kernel/irqinit.c   | 9 +++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 98722773391d..6e1990d69865 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -183,6 +183,7 @@ static inline void disable_local_APIC(void) { }
 # define setup_boot_APIC_clock x86_init_noop
 # define setup_secondary_APIC_clock x86_init_noop
 static inline void lapic_update_tsc_freq(void) { }
+static inline void init_bsp_APIC(void) { }
 static inline void apic_intr_mode_init(void) { }
 static inline void lapic_assign_system_vectors(void) { }
 static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { }
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index a539410c4ea9..a0e41397558e 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -61,9 +61,14 @@ void __init init_ISA_irqs(void)
struct irq_chip *chip = legacy_pic->chip;
int i;
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+   /*
+* Try to setup the through-local-APIC virtual wire mode earlier.
+*
+* In some 32bit UP machines whose APIC has been disabled by BIOS
+* and re-enabled by "lapic", it hangs at boot time without this.
+*/
init_bsp_APIC();
-#endif
+
legacy_pic->init(0);
 
for (i = 0; i < nr_legacy_irqs(); i++)
-- 
2.14.3





Re: [PATCH 32/32] aio: implement io_pgetevents

2018-01-16 Thread Christoph Hellwig
On Tue, Jan 16, 2018 at 07:41:24PM -0500, Jeff Moyer wrote:
> I'd be willing to bet the issue is in your io_syscall6 implementation.
> You pass in arg5 where arg6 should be used.  Don't feel bad, it took me
> the better part of today to figure that out.  :)
> 
> Here's an incremental diff on top of what you've posted.  Feel free to
> fold it into your patch (and format however you like).  You can find the
> libaio changes in my 'aio-poll' branch:
>   https://pagure.io/libaio/commits/aio-poll
> 
> These changes were run through the libaio test harness, 64 bit and 32
> bit, so the compat system call was tested.

Oops, yes.  Although I prefer the copy_from_user version, this is what
I had:


diff --git a/fs/aio.c b/fs/aio.c
index 9fe0a5539596..6c1bbfa9b06a 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1984,8 +1984,9 @@ SYSCALL_DEFINE6(io_pgetevents,
long, nr,
struct io_event __user *, events,
struct timespec __user *, timeout,
-   const sigset_t __user *, sigmask)
+   const struct __aio_sigset __user *, usig)
 {
+   struct __aio_sigset ksig = { NULL, };
sigset_tksigmask, sigsaved;
struct timespec64   ts;
int ret;
@@ -1993,8 +1994,13 @@ SYSCALL_DEFINE6(io_pgetevents,
if (timeout && unlikely(get_timespec64(, timeout)))
return -EFAULT;
 
-   if (sigmask) {
-   if (copy_from_user(, sigmask, sizeof(ksigmask)))
+   if (usig && copy_from_user(, usig, sizeof(ksig)))
+   return -EFAULT;
+
+   if (ksig.sigmask) {
+   if (ksig.sigsetsize != sizeof(sigset_t))
+   return -EINVAL;
+   if (copy_from_user(, ksig.sigmask, sizeof(ksigmask)))
return -EFAULT;
sigdelsetmask(, sigmask(SIGKILL) | sigmask(SIGSTOP));
sigprocmask(SIG_SETMASK, , );
@@ -2002,7 +2008,7 @@ SYSCALL_DEFINE6(io_pgetevents,
 
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ?  : NULL);
if (signal_pending(current)) {
-   if (sigmask) {
+   if (ksig.sigmask) {
current->saved_sigmask = sigsaved;
set_restore_sigmask();
}
@@ -2010,7 +2016,7 @@ SYSCALL_DEFINE6(io_pgetevents,
if (!ret)
ret = -ERESTARTNOHAND;
} else {
-   if (sigmask)
+   if (ksig.sigmask)
sigprocmask(SIG_SETMASK, , NULL);
}
 
@@ -2036,14 +2042,21 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, 
compat_aio_context_t, ctx_id,
return ret;
 }
 
+
+struct __compat_aio_sigset {
+   compat_sigset_t __user  *sigmask;
+   compat_size_t   sigsetsize;
+};
+
 COMPAT_SYSCALL_DEFINE6(io_pgetevents,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
struct io_event __user *, events,
struct compat_timespec __user *, timeout,
-   const compat_sigset_t __user *, sigmask)
+   const struct __compat_aio_sigset __user *, usig)
 {
+   struct __compat_aio_sigset ksig = { NULL, };
sigset_t ksigmask, sigsaved;
struct timespec64 t;
int ret;
@@ -2051,8 +2064,13 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
if (timeout && compat_get_timespec64(, timeout))
return -EFAULT;
 
-   if (sigmask) {
-   if (get_compat_sigset(, sigmask))
+   if (usig && copy_from_user(, usig, sizeof(ksig)))
+   return -EFAULT;
+
+   if (ksig.sigmask) {
+   if (ksig.sigsetsize != sizeof(compat_sigset_t))
+   return -EINVAL;
+   if (get_compat_sigset(, ksig.sigmask))
return -EFAULT;
sigdelsetmask(, sigmask(SIGKILL) | sigmask(SIGSTOP));
sigprocmask(SIG_SETMASK, , );
@@ -2060,14 +2078,14 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
 
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ?  : NULL);
if (signal_pending(current)) {
-   if (sigmask) {
+   if (ksig.sigmask) {
current->saved_sigmask = sigsaved;
set_restore_sigmask();
}
if (!ret)
ret = -ERESTARTNOHAND;
} else {
-   if (sigmask)
+   if (ksig.sigmask)
sigprocmask(SIG_SETMASK, , NULL);
}
 
diff --git a/include/linux/compat.h b/include/linux/compat.h
index a4cda98073f1..6c04450e961f 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -205,6 +205,7 @@ extern int put_compat_rusage(const struct rusage *,
 struct compat_rusage __user *);
 
 struct compat_siginfo;
+struct __compat_aio_sigset;
 
 extern asmlinkage long compat_sys_waitid(int, compat_pid_t,

Re: [PATCH 32/32] aio: implement io_pgetevents

2018-01-16 Thread Christoph Hellwig
On Tue, Jan 16, 2018 at 07:41:24PM -0500, Jeff Moyer wrote:
> I'd be willing to bet the issue is in your io_syscall6 implementation.
> You pass in arg5 where arg6 should be used.  Don't feel bad, it took me
> the better part of today to figure that out.  :)
> 
> Here's an incremental diff on top of what you've posted.  Feel free to
> fold it into your patch (and format however you like).  You can find the
> libaio changes in my 'aio-poll' branch:
>   https://pagure.io/libaio/commits/aio-poll
> 
> These changes were run through the libaio test harness, 64 bit and 32
> bit, so the compat system call was tested.

Oops, yes.  Although I prefer the copy_from_user version, this is what
I had:


diff --git a/fs/aio.c b/fs/aio.c
index 9fe0a5539596..6c1bbfa9b06a 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1984,8 +1984,9 @@ SYSCALL_DEFINE6(io_pgetevents,
long, nr,
struct io_event __user *, events,
struct timespec __user *, timeout,
-   const sigset_t __user *, sigmask)
+   const struct __aio_sigset __user *, usig)
 {
+   struct __aio_sigset ksig = { NULL, };
sigset_tksigmask, sigsaved;
struct timespec64   ts;
int ret;
@@ -1993,8 +1994,13 @@ SYSCALL_DEFINE6(io_pgetevents,
if (timeout && unlikely(get_timespec64(, timeout)))
return -EFAULT;
 
-   if (sigmask) {
-   if (copy_from_user(, sigmask, sizeof(ksigmask)))
+   if (usig && copy_from_user(, usig, sizeof(ksig)))
+   return -EFAULT;
+
+   if (ksig.sigmask) {
+   if (ksig.sigsetsize != sizeof(sigset_t))
+   return -EINVAL;
+   if (copy_from_user(, ksig.sigmask, sizeof(ksigmask)))
return -EFAULT;
sigdelsetmask(, sigmask(SIGKILL) | sigmask(SIGSTOP));
sigprocmask(SIG_SETMASK, , );
@@ -2002,7 +2008,7 @@ SYSCALL_DEFINE6(io_pgetevents,
 
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ?  : NULL);
if (signal_pending(current)) {
-   if (sigmask) {
+   if (ksig.sigmask) {
current->saved_sigmask = sigsaved;
set_restore_sigmask();
}
@@ -2010,7 +2016,7 @@ SYSCALL_DEFINE6(io_pgetevents,
if (!ret)
ret = -ERESTARTNOHAND;
} else {
-   if (sigmask)
+   if (ksig.sigmask)
sigprocmask(SIG_SETMASK, , NULL);
}
 
@@ -2036,14 +2042,21 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, 
compat_aio_context_t, ctx_id,
return ret;
 }
 
+
+struct __compat_aio_sigset {
+   compat_sigset_t __user  *sigmask;
+   compat_size_t   sigsetsize;
+};
+
 COMPAT_SYSCALL_DEFINE6(io_pgetevents,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
struct io_event __user *, events,
struct compat_timespec __user *, timeout,
-   const compat_sigset_t __user *, sigmask)
+   const struct __compat_aio_sigset __user *, usig)
 {
+   struct __compat_aio_sigset ksig = { NULL, };
sigset_t ksigmask, sigsaved;
struct timespec64 t;
int ret;
@@ -2051,8 +2064,13 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
if (timeout && compat_get_timespec64(, timeout))
return -EFAULT;
 
-   if (sigmask) {
-   if (get_compat_sigset(, sigmask))
+   if (usig && copy_from_user(, usig, sizeof(ksig)))
+   return -EFAULT;
+
+   if (ksig.sigmask) {
+   if (ksig.sigsetsize != sizeof(compat_sigset_t))
+   return -EINVAL;
+   if (get_compat_sigset(, ksig.sigmask))
return -EFAULT;
sigdelsetmask(, sigmask(SIGKILL) | sigmask(SIGSTOP));
sigprocmask(SIG_SETMASK, , );
@@ -2060,14 +2078,14 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
 
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ?  : NULL);
if (signal_pending(current)) {
-   if (sigmask) {
+   if (ksig.sigmask) {
current->saved_sigmask = sigsaved;
set_restore_sigmask();
}
if (!ret)
ret = -ERESTARTNOHAND;
} else {
-   if (sigmask)
+   if (ksig.sigmask)
sigprocmask(SIG_SETMASK, , NULL);
}
 
diff --git a/include/linux/compat.h b/include/linux/compat.h
index a4cda98073f1..6c04450e961f 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -205,6 +205,7 @@ extern int put_compat_rusage(const struct rusage *,
 struct compat_rusage __user *);
 
 struct compat_siginfo;
+struct __compat_aio_sigset;
 
 extern asmlinkage long compat_sys_waitid(int, compat_pid_t,

Re: [PATCH v5 1/2] printk: Add console owner and waiter logic to load balance console writes

2018-01-16 Thread Byungchul Park

On 1/17/2018 11:19 AM, Byungchul Park wrote:

On 1/10/2018 10:24 PM, Petr Mladek wrote:

From: Steven Rostedt 

From: Steven Rostedt (VMware) 

This patch implements what I discussed in Kernel Summit. I added
lockdep annotation (hopefully correctly), and it hasn't had any splats
(since I fixed some bugs in the first iterations). It did catch
problems when I had the owner covering too much. But now that the owner
is only set when actively calling the consoles, lockdep has stayed
quiet.

Here's the design again:

I added a "console_owner" which is set to a task that is actively
writing to the consoles. It is *not* the same as the owner of the
console_lock. It is only set when doing the calls to the console
functions. It is protected by a console_owner_lock which is a raw spin
lock.

There is a console_waiter. This is set when there is an active console
owner that is not current, and waiter is not set. This too is protected
by console_owner_lock.

In printk() when it tries to write to the consoles, we have:

if (console_trylock())
    console_unlock();

Now I added an else, which will check if there is an active owner, and
no current waiter. If that is the case, then console_waiter is set, and
the task goes into a spin until it is no longer set.

When the active console owner finishes writing the current message to
the consoles, it grabs the console_owner_lock and sees if there is a
waiter, and clears console_owner.

If there is a waiter, then it breaks out of the loop, clears the waiter
flag (because that will release the waiter from its spin), and exits.
Note, it does *not* release the console semaphore. Because it is a
semaphore, there is no owner. Another task may release it. This means
that the waiter is guaranteed to be the new console owner! Which it
becomes.

Then the waiter calls console_unlock() and continues to write to the
consoles.

If another task comes along and does a printk() it too can become the
new waiter, and we wash rinse and repeat!

By Petr Mladek about possible new deadlocks:

The thing is that we move console_sem only to printk() call
that normally calls console_unlock() as well. It means that
the transferred owner should not bring new type of dependencies.
As Steven said somewhere: "If there is a deadlock, it was
there even before."

We could look at it from this side. The possible deadlock would
look like:

CPU0    CPU1

console_unlock()

   console_owner = current;

    spin_lockA()
  printk()
    spin = true;
    while (...)

 call_console_drivers()
   spin_lockA()

This would be a deadlock. CPU0 would wait for the lock A.
While CPU1 would own the lockA and would wait for CPU0
to finish calling the console drivers and pass the console_sem
owner.

But if the above is true than the following scenario was
already possible before:

CPU0

spin_lockA()
   printk()
 console_unlock()
   call_console_drivers()
spin_lockA()

By other words, this deadlock was there even before. Such
deadlocks are prevented by using printk_deferred() in
the sections guarded by the lock A.


Hello,

I didn't see what you did, at the last version. You were
tring to transfer the semaphore owner and make it taken
over. I see.

But, what I mentioned last time is still valid. See below.


Signed-off-by: Steven Rostedt (VMware) 
[pmla...@suse.com: Commit message about possible deadlocks]
---
  kernel/printk/printk.c | 108 
-

  1 file changed, 107 insertions(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b9006617710f..7e6459abba43 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -86,8 +86,15 @@ EXPORT_SYMBOL_GPL(console_drivers);
  static struct lockdep_map console_lock_dep_map = {
  .name = "console_lock"
  };
+static struct lockdep_map console_owner_dep_map = {
+    .name = "console_owner"
+};
  #endif
+static DEFINE_RAW_SPINLOCK(console_owner_lock);
+static struct task_struct *console_owner;
+static bool console_waiter;
+
  enum devkmsg_log_bits {
  __DEVKMSG_LOG_BIT_ON = 0,
  __DEVKMSG_LOG_BIT_OFF,
@@ -1753,8 +1760,56 @@ asmlinkage int vprintk_emit(int facility, int 
level,

   * semaphore.  The release will print out buffers and wake up
   * /dev/kmsg and syslog() users.
   */
-    if (console_trylock())
+    if (console_trylock()) {
  console_unlock();
+    } else {
+    struct task_struct *owner = NULL;
+    bool waiter;
+    bool spin = false;
+
+    printk_safe_enter_irqsave(flags);
+
+    raw_spin_lock(_owner_lock);
+    owner = READ_ONCE(console_owner);
+    waiter = READ_ONCE(console_waiter);
+    if (!waiter && owner && owner != current) {
+    WRITE_ONCE(console_waiter, true);
+ 

Re: [PATCH v5 1/2] printk: Add console owner and waiter logic to load balance console writes

2018-01-16 Thread Byungchul Park

On 1/17/2018 11:19 AM, Byungchul Park wrote:

On 1/10/2018 10:24 PM, Petr Mladek wrote:

From: Steven Rostedt 

From: Steven Rostedt (VMware) 

This patch implements what I discussed in Kernel Summit. I added
lockdep annotation (hopefully correctly), and it hasn't had any splats
(since I fixed some bugs in the first iterations). It did catch
problems when I had the owner covering too much. But now that the owner
is only set when actively calling the consoles, lockdep has stayed
quiet.

Here's the design again:

I added a "console_owner" which is set to a task that is actively
writing to the consoles. It is *not* the same as the owner of the
console_lock. It is only set when doing the calls to the console
functions. It is protected by a console_owner_lock which is a raw spin
lock.

There is a console_waiter. This is set when there is an active console
owner that is not current, and waiter is not set. This too is protected
by console_owner_lock.

In printk() when it tries to write to the consoles, we have:

if (console_trylock())
    console_unlock();

Now I added an else, which will check if there is an active owner, and
no current waiter. If that is the case, then console_waiter is set, and
the task goes into a spin until it is no longer set.

When the active console owner finishes writing the current message to
the consoles, it grabs the console_owner_lock and sees if there is a
waiter, and clears console_owner.

If there is a waiter, then it breaks out of the loop, clears the waiter
flag (because that will release the waiter from its spin), and exits.
Note, it does *not* release the console semaphore. Because it is a
semaphore, there is no owner. Another task may release it. This means
that the waiter is guaranteed to be the new console owner! Which it
becomes.

Then the waiter calls console_unlock() and continues to write to the
consoles.

If another task comes along and does a printk() it too can become the
new waiter, and we wash rinse and repeat!

By Petr Mladek about possible new deadlocks:

The thing is that we move console_sem only to printk() call
that normally calls console_unlock() as well. It means that
the transferred owner should not bring new type of dependencies.
As Steven said somewhere: "If there is a deadlock, it was
there even before."

We could look at it from this side. The possible deadlock would
look like:

CPU0    CPU1

console_unlock()

   console_owner = current;

    spin_lockA()
  printk()
    spin = true;
    while (...)

 call_console_drivers()
   spin_lockA()

This would be a deadlock. CPU0 would wait for the lock A.
While CPU1 would own the lockA and would wait for CPU0
to finish calling the console drivers and pass the console_sem
owner.

But if the above is true than the following scenario was
already possible before:

CPU0

spin_lockA()
   printk()
 console_unlock()
   call_console_drivers()
spin_lockA()

By other words, this deadlock was there even before. Such
deadlocks are prevented by using printk_deferred() in
the sections guarded by the lock A.


Hello,

I didn't see what you did, at the last version. You were
tring to transfer the semaphore owner and make it taken
over. I see.

But, what I mentioned last time is still valid. See below.


Signed-off-by: Steven Rostedt (VMware) 
[pmla...@suse.com: Commit message about possible deadlocks]
---
  kernel/printk/printk.c | 108 
-

  1 file changed, 107 insertions(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b9006617710f..7e6459abba43 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -86,8 +86,15 @@ EXPORT_SYMBOL_GPL(console_drivers);
  static struct lockdep_map console_lock_dep_map = {
  .name = "console_lock"
  };
+static struct lockdep_map console_owner_dep_map = {
+    .name = "console_owner"
+};
  #endif
+static DEFINE_RAW_SPINLOCK(console_owner_lock);
+static struct task_struct *console_owner;
+static bool console_waiter;
+
  enum devkmsg_log_bits {
  __DEVKMSG_LOG_BIT_ON = 0,
  __DEVKMSG_LOG_BIT_OFF,
@@ -1753,8 +1760,56 @@ asmlinkage int vprintk_emit(int facility, int 
level,

   * semaphore.  The release will print out buffers and wake up
   * /dev/kmsg and syslog() users.
   */
-    if (console_trylock())
+    if (console_trylock()) {
  console_unlock();
+    } else {
+    struct task_struct *owner = NULL;
+    bool waiter;
+    bool spin = false;
+
+    printk_safe_enter_irqsave(flags);
+
+    raw_spin_lock(_owner_lock);
+    owner = READ_ONCE(console_owner);
+    waiter = READ_ONCE(console_waiter);
+    if (!waiter && owner && owner != current) {
+    WRITE_ONCE(console_waiter, true);
+    spin = true;
+    }
+    

Re: [BUG 4.15-rc7] IRQ matrix management errors

2018-01-16 Thread Thomas Gleixner
On Tue, 16 Jan 2018, Keith Busch wrote:
> On Tue, Jan 16, 2018 at 12:20:18PM +0100, Thomas Gleixner wrote:
> > 8<--
> > diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
> > index f8b03bb8e725..3cc471beb50b 100644
> > --- a/arch/x86/kernel/apic/vector.c
> > +++ b/arch/x86/kernel/apic/vector.c
> > @@ -542,14 +542,17 @@ static int x86_vector_alloc_irqs(struct irq_domain 
> > *domain, unsigned int virq,
> >  
> > err = assign_irq_vector_policy(irqd, info);
> > trace_vector_setup(virq + i, false, err);
> > -   if (err)
> > +   if (err) {
> > +   irqd->chip_data = NULL;
> > +   free_apic_chip_data(apicd);
> > goto error;
> > +   }
> > }
> >  
> > return 0;
> >  
> >  error:
> > -   x86_vector_free_irqs(domain, virq, i + 1);
> > +   x86_vector_free_irqs(domain, virq, i);
> > return err;
> >  }
> >  
> 
> The patch does indeed fix all the warnings and allows device binding to
> succeed, albeit in a degraded performance mode. Despite that, this is
> a good fix, and looks applicable to 4.4-stable, so:
> 
> Tested-by: Keith Busch 
> 
> I'm still concerned assign_irq_vector_policy is failing. That has
> interrupt allocation abandon MSI-x and fall back to legacy IRQ.

Can you trace the matrix allocations from the very beginning or tell me how
to reproduce. I'd like to figure out why this is happening.
 
> Your patch does address my main concern, though. Are you comfortable
> enough to queue this up for 4.15?

Yes, it's a pretty obvious bug and the fix is straight forward.

Thanks,

tglx


Re: [BUG 4.15-rc7] IRQ matrix management errors

2018-01-16 Thread Thomas Gleixner
On Tue, 16 Jan 2018, Keith Busch wrote:
> On Tue, Jan 16, 2018 at 12:20:18PM +0100, Thomas Gleixner wrote:
> > 8<--
> > diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
> > index f8b03bb8e725..3cc471beb50b 100644
> > --- a/arch/x86/kernel/apic/vector.c
> > +++ b/arch/x86/kernel/apic/vector.c
> > @@ -542,14 +542,17 @@ static int x86_vector_alloc_irqs(struct irq_domain 
> > *domain, unsigned int virq,
> >  
> > err = assign_irq_vector_policy(irqd, info);
> > trace_vector_setup(virq + i, false, err);
> > -   if (err)
> > +   if (err) {
> > +   irqd->chip_data = NULL;
> > +   free_apic_chip_data(apicd);
> > goto error;
> > +   }
> > }
> >  
> > return 0;
> >  
> >  error:
> > -   x86_vector_free_irqs(domain, virq, i + 1);
> > +   x86_vector_free_irqs(domain, virq, i);
> > return err;
> >  }
> >  
> 
> The patch does indeed fix all the warnings and allows device binding to
> succeed, albeit in a degraded performance mode. Despite that, this is
> a good fix, and looks applicable to 4.4-stable, so:
> 
> Tested-by: Keith Busch 
> 
> I'm still concerned assign_irq_vector_policy is failing. That has
> interrupt allocation abandon MSI-x and fall back to legacy IRQ.

Can you trace the matrix allocations from the very beginning or tell me how
to reproduce. I'd like to figure out why this is happening.
 
> Your patch does address my main concern, though. Are you comfortable
> enough to queue this up for 4.15?

Yes, it's a pretty obvious bug and the fix is straight forward.

Thanks,

tglx


Re: [PATCH v2 11/13] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:20 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> Thanks for your reply.
>
>
> On 01/17/2018 01:44 PM, Tomasz Figa wrote:
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> wrote:
>>>
>>> Converts the rockchip-iommu driver to use the OF_IOMMU infrastructure,
>>> which allows attaching master devices to their IOMMUs automatically
>>> according to DT properties.
>>>
>>> Signed-off-by: Jeffy Chen 
>>> ---
>>>
>>> Changes in v2: None
>>>
>>>   drivers/iommu/rockchip-iommu.c | 116
>>> +++--
>>>   1 file changed, 31 insertions(+), 85 deletions(-)
>>>
>>> diff --git a/drivers/iommu/rockchip-iommu.c
>>> b/drivers/iommu/rockchip-iommu.c
>>> index 51e4f982c4a6..c2d3ac82184e 100644
>>> --- a/drivers/iommu/rockchip-iommu.c
>>> +++ b/drivers/iommu/rockchip-iommu.c
>>
>> [snip]
>>>
>>> +static int rk_iommu_of_xlate(struct device *dev,
>>> +struct of_phandle_args *args)
>>> +{
>>> +   struct platform_device *iommu_dev;
>>> +
>>> +   iommu_dev = of_find_device_by_node(args->np);
>>> +   if (!iommu_dev) {
>>> +   dev_err(dev, "iommu %pOF not found\n", args->np);
>>> +   return -ENODEV;
>>> +   }
>>> +
>>> +   dev->archdata.iommu = platform_get_drvdata(iommu_dev);
>>
>>
>> This will work only if that iommu was already probed. Do we have any
>> guarantees that this callback is not called earlier?
>
> in of_iommu.c, the of_iommu_xlate would check for fwnode before calling
> this.

Right, looks like deferred probe is handled there.

>
> but it's possible the probe failed after calling iommu_device_set_fwnode, so
> i'll try to add some checks here, and maybe adjust probe() to prevent it
> too.

I think iommu_device_set_fwnode() is not enough for of_iommu_xlate()
to find the IOMMU. The IOMMU is actually added to the IOMMU list by
iommu_device_register(), which is last in the sequence, so I guess we
should be fine.

Best regards,
Tomasz


Re: [PATCH v2 11/13] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:20 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> Thanks for your reply.
>
>
> On 01/17/2018 01:44 PM, Tomasz Figa wrote:
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> wrote:
>>>
>>> Converts the rockchip-iommu driver to use the OF_IOMMU infrastructure,
>>> which allows attaching master devices to their IOMMUs automatically
>>> according to DT properties.
>>>
>>> Signed-off-by: Jeffy Chen 
>>> ---
>>>
>>> Changes in v2: None
>>>
>>>   drivers/iommu/rockchip-iommu.c | 116
>>> +++--
>>>   1 file changed, 31 insertions(+), 85 deletions(-)
>>>
>>> diff --git a/drivers/iommu/rockchip-iommu.c
>>> b/drivers/iommu/rockchip-iommu.c
>>> index 51e4f982c4a6..c2d3ac82184e 100644
>>> --- a/drivers/iommu/rockchip-iommu.c
>>> +++ b/drivers/iommu/rockchip-iommu.c
>>
>> [snip]
>>>
>>> +static int rk_iommu_of_xlate(struct device *dev,
>>> +struct of_phandle_args *args)
>>> +{
>>> +   struct platform_device *iommu_dev;
>>> +
>>> +   iommu_dev = of_find_device_by_node(args->np);
>>> +   if (!iommu_dev) {
>>> +   dev_err(dev, "iommu %pOF not found\n", args->np);
>>> +   return -ENODEV;
>>> +   }
>>> +
>>> +   dev->archdata.iommu = platform_get_drvdata(iommu_dev);
>>
>>
>> This will work only if that iommu was already probed. Do we have any
>> guarantees that this callback is not called earlier?
>
> in of_iommu.c, the of_iommu_xlate would check for fwnode before calling
> this.

Right, looks like deferred probe is handled there.

>
> but it's possible the probe failed after calling iommu_device_set_fwnode, so
> i'll try to add some checks here, and maybe adjust probe() to prevent it
> too.

I think iommu_device_set_fwnode() is not enough for of_iommu_xlate()
to find the IOMMU. The IOMMU is actually added to the IOMMU list by
iommu_device_register(), which is last in the sequence, so I guess we
should be fine.

Best regards,
Tomasz


kexec reboot fails with extra wbinvd introduced for AME SME

2018-01-16 Thread Dave Young
[Modify the subject since this is a new problem, original io vector
issue has been fixed with one commit from Thomas]

Add more cc according to below old discussion:
https://lkml.org/lkml/2017/7/27/574

Tom, I'm not sure why you finally did not dynamically run wbinvd?
On 01/04/18 at 11:15am, Dave Young wrote:
> On 12/14/17 at 05:24pm, Dave Young wrote:
> > On 12/13/17 at 11:57pm, Yu Chen wrote:
> > > On Wed, Dec 13, 2017 at 10:52:56AM +0800, Dave Young wrote:
> > > > Hi,
> > > > 
> > > > Kexec reboot and kdump has broken on my laptop for long time with
> > > > 4.15.0-rc1+ kernels. With the patch below an early panic been fixed:
> > > > https://patchwork.kernel.org/patch/10084289/
> > > > 
> > > > But still can not get a successful reboot, it looked like graphic
> > > > issue, but after bisecting the kernel, I got below:
> > > > 
> > > > [dyoung@dhcp-*-* linux]$ git bisect good
> > > > There are only 'skip'ped commits left to test.
> > > > The first bad commit could be any of:
> > > > 2db1f959d9dc16035f2eb44ed5fdb2789b754d6a
> > > > 4900be83602b6be07366d3e69f756c1959f4169a
> > > > We cannot bisect more!
> > > > 
> > > > These two commits can no be reverted because of code conflicts, thus
> > > > I reverted the whole series from Thomas (below commits), with those
> > > > x86/vector changes reverted, kexec reboot works fine.
> > > > 
> > > > Could you help to take a look, any thoughts?  I can do the test
> > > > if you have some debug patch to try.
> > > Is it possible that the "second" kernel runs on non-zero CPU? If yes,
> > > what if some irqs are only delivered to cpu0? (use cpumask_of(0)
> > > directly)
> > 
> > Thanks for the reply.
> > 
> > For kdump, yes, for kexec, I'm not sure.  
> > 
> > Here is some kexec kernel boot log:
> > http://people.redhat.com/~ruyang/misc/kexec-regression.txt
> > 
> > Copy the lockup call trace here:
> > [   23.779285] NMI watchdog: Watchdog detected hard LOCKUP on cpu 0 
> > 
> > [   23.779285] Modules linked in: arc4 rtsx_pci_sdmmc i915 iwlmvm kvm_intel 
> > mac8
> > 0211 kvm irqbypass btusb btrtl btbcm intel_gtt btintel drm_kms_helper 
> > snd_hda_in
> > tel syscopyarea bluetooth iwlwifi snd_hda_codec snd_hwdep snd_hda_core 
> > sysfillre
> > ct snd_seq sysimgblt input_leds fb_sys_fops e1000e ecdh_generic cfg80211 
> > snd_seq
> > _device drm snd_pcm serio_raw ptp pcspkr thinkpad_acpi i2c_i801 snd_timer 
> > rtsx_p
> > ci pps_core snd soundcore rfkill video  
> > 
> > [   23.779307] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.15.0-rc3+ #378   
> > 
> > [   23.779308] Hardware name: LENOVO 20ARS1BJ02/20ARS1BJ02, BIOS GJET92WW 
> > (2.42 
> > ) 03/03/2017
> > 
> > [   23.779312] RIP: 0010:poll_idle+0x2f/0x5f
> > 
> > [   23.779313] RSP: 0018:81c03e80 EFLAGS: 0246  
> > 
> > [   23.779314] RAX: 81c0f4c0 RBX: 81c6db80 RCX: 
> > 
> > [   23.779315] RDX:  RSI: 81c6db80 RDI: 
> > 88021f2201e8
> > [   23.779316] RBP: 88021f2201e8 R08: 00349a65b7dd R09: 
> > 88021f216db4
> > [   23.779317] R10: 81c03e68 R11:  R12: 
> > 
> > [   23.779318] R13: 81c6db98 R14:  R15: 
> > 000578a065b1
> > [   23.779319] FS:  () GS:88021f20() 
> > knlGS:0
> > 000 
> > 
> > [   23.779320] CS:  0010 DS:  ES:  CR0: 80050033
> > 
> > [   23.779321] CR2: 7ffed1d0ee60 CR3: 00021ec0a006 CR4: 
> > 001606b0
> > [   23.779322] Call Trace:  
> > 
> > [   23.779328]  cpuidle_enter_state+0x6a/0x2c0  
> > 
> > [   23.779333]  do_idle+0x17b/0x1d0 
> > 
> > [   23.779335]  cpu_startup_entry+0x6f/0x80 
> > 
> > [   23.779338]  start_kernel+0x431/0x451
> > 
> > [   23.779342]  secondary_startup_64+0xa5/0xb0  
> > 
> > [   23.779344] Code: 00 fb 66 0f 1f 44 00 00 65 48 8b 04 25 40 c4 00 00 f0 
> > 80 48
> >  02 20 48 8b 08 83 e1 08 74 0d eb 12 f3 90 65 48 8b 04 25 40 c4 00 00 <48> 
> > 8b 00
> >  a8 08 74 ee 65 48 8b 04 25 40 c4 00 00 f0 80 60 02 df
> > 
> 
> Followup this issue, seems another commit from Thomas partially fixed
> this, kexec/kdump boot up successfully for me, but kexec after kexec
> (2nd kexec reboot cycle) failed, kernel hung early

The above kexec reboot hang is another problem, so Thomas has fully
fixed previous report, thanks!

For the kexec reboot hang, if I remove the wbinvd in stop_this_cpu()
then kexec works fine. like this:
 
diff --git a/arch/x86/kernel/process.c 

kexec reboot fails with extra wbinvd introduced for AME SME

2018-01-16 Thread Dave Young
[Modify the subject since this is a new problem, original io vector
issue has been fixed with one commit from Thomas]

Add more cc according to below old discussion:
https://lkml.org/lkml/2017/7/27/574

Tom, I'm not sure why you finally did not dynamically run wbinvd?
On 01/04/18 at 11:15am, Dave Young wrote:
> On 12/14/17 at 05:24pm, Dave Young wrote:
> > On 12/13/17 at 11:57pm, Yu Chen wrote:
> > > On Wed, Dec 13, 2017 at 10:52:56AM +0800, Dave Young wrote:
> > > > Hi,
> > > > 
> > > > Kexec reboot and kdump has broken on my laptop for long time with
> > > > 4.15.0-rc1+ kernels. With the patch below an early panic been fixed:
> > > > https://patchwork.kernel.org/patch/10084289/
> > > > 
> > > > But still can not get a successful reboot, it looked like graphic
> > > > issue, but after bisecting the kernel, I got below:
> > > > 
> > > > [dyoung@dhcp-*-* linux]$ git bisect good
> > > > There are only 'skip'ped commits left to test.
> > > > The first bad commit could be any of:
> > > > 2db1f959d9dc16035f2eb44ed5fdb2789b754d6a
> > > > 4900be83602b6be07366d3e69f756c1959f4169a
> > > > We cannot bisect more!
> > > > 
> > > > These two commits can no be reverted because of code conflicts, thus
> > > > I reverted the whole series from Thomas (below commits), with those
> > > > x86/vector changes reverted, kexec reboot works fine.
> > > > 
> > > > Could you help to take a look, any thoughts?  I can do the test
> > > > if you have some debug patch to try.
> > > Is it possible that the "second" kernel runs on non-zero CPU? If yes,
> > > what if some irqs are only delivered to cpu0? (use cpumask_of(0)
> > > directly)
> > 
> > Thanks for the reply.
> > 
> > For kdump, yes, for kexec, I'm not sure.  
> > 
> > Here is some kexec kernel boot log:
> > http://people.redhat.com/~ruyang/misc/kexec-regression.txt
> > 
> > Copy the lockup call trace here:
> > [   23.779285] NMI watchdog: Watchdog detected hard LOCKUP on cpu 0 
> > 
> > [   23.779285] Modules linked in: arc4 rtsx_pci_sdmmc i915 iwlmvm kvm_intel 
> > mac8
> > 0211 kvm irqbypass btusb btrtl btbcm intel_gtt btintel drm_kms_helper 
> > snd_hda_in
> > tel syscopyarea bluetooth iwlwifi snd_hda_codec snd_hwdep snd_hda_core 
> > sysfillre
> > ct snd_seq sysimgblt input_leds fb_sys_fops e1000e ecdh_generic cfg80211 
> > snd_seq
> > _device drm snd_pcm serio_raw ptp pcspkr thinkpad_acpi i2c_i801 snd_timer 
> > rtsx_p
> > ci pps_core snd soundcore rfkill video  
> > 
> > [   23.779307] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.15.0-rc3+ #378   
> > 
> > [   23.779308] Hardware name: LENOVO 20ARS1BJ02/20ARS1BJ02, BIOS GJET92WW 
> > (2.42 
> > ) 03/03/2017
> > 
> > [   23.779312] RIP: 0010:poll_idle+0x2f/0x5f
> > 
> > [   23.779313] RSP: 0018:81c03e80 EFLAGS: 0246  
> > 
> > [   23.779314] RAX: 81c0f4c0 RBX: 81c6db80 RCX: 
> > 
> > [   23.779315] RDX:  RSI: 81c6db80 RDI: 
> > 88021f2201e8
> > [   23.779316] RBP: 88021f2201e8 R08: 00349a65b7dd R09: 
> > 88021f216db4
> > [   23.779317] R10: 81c03e68 R11:  R12: 
> > 
> > [   23.779318] R13: 81c6db98 R14:  R15: 
> > 000578a065b1
> > [   23.779319] FS:  () GS:88021f20() 
> > knlGS:0
> > 000 
> > 
> > [   23.779320] CS:  0010 DS:  ES:  CR0: 80050033
> > 
> > [   23.779321] CR2: 7ffed1d0ee60 CR3: 00021ec0a006 CR4: 
> > 001606b0
> > [   23.779322] Call Trace:  
> > 
> > [   23.779328]  cpuidle_enter_state+0x6a/0x2c0  
> > 
> > [   23.779333]  do_idle+0x17b/0x1d0 
> > 
> > [   23.779335]  cpu_startup_entry+0x6f/0x80 
> > 
> > [   23.779338]  start_kernel+0x431/0x451
> > 
> > [   23.779342]  secondary_startup_64+0xa5/0xb0  
> > 
> > [   23.779344] Code: 00 fb 66 0f 1f 44 00 00 65 48 8b 04 25 40 c4 00 00 f0 
> > 80 48
> >  02 20 48 8b 08 83 e1 08 74 0d eb 12 f3 90 65 48 8b 04 25 40 c4 00 00 <48> 
> > 8b 00
> >  a8 08 74 ee 65 48 8b 04 25 40 c4 00 00 f0 80 60 02 df
> > 
> 
> Followup this issue, seems another commit from Thomas partially fixed
> this, kexec/kdump boot up successfully for me, but kexec after kexec
> (2nd kexec reboot cycle) failed, kernel hung early

The above kexec reboot hang is another problem, so Thomas has fully
fixed previous report, thanks!

For the kexec reboot hang, if I remove the wbinvd in stop_this_cpu()
then kexec works fine. like this:
 
diff --git a/arch/x86/kernel/process.c 

Re: [PATCH v2 05/13] iommu/rockchip: Fix error handling in init

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:14 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> On 01/17/2018 01:26 PM, Tomasz Figa wrote:
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> wrote:
>>>
>>> It's hard to undo bus_set_iommu() in the error path, so move it to the
>>> end of rk_iommu_probe().
>>
>>
>> Does this work fine now? I remember we used to need this called in an
>> early initcall for all the ARM/ARM64 DMA stuff to work.
>>
> yes, i think it works now, i saw there are some other iommu drivers also do
> this(arm-smmu-v3, mtk_iommu) :)

Okay, if so:

Reviewed-by: Tomasz Figa 

Best regards,
Tomasz

P.S. Looks like your email client is set to HTML messages. Your
messages might end up dropped from the mailing list.


Re: [PATCH v2 05/13] iommu/rockchip: Fix error handling in init

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:14 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> On 01/17/2018 01:26 PM, Tomasz Figa wrote:
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> wrote:
>>>
>>> It's hard to undo bus_set_iommu() in the error path, so move it to the
>>> end of rk_iommu_probe().
>>
>>
>> Does this work fine now? I remember we used to need this called in an
>> early initcall for all the ARM/ARM64 DMA stuff to work.
>>
> yes, i think it works now, i saw there are some other iommu drivers also do
> this(arm-smmu-v3, mtk_iommu) :)

Okay, if so:

Reviewed-by: Tomasz Figa 

Best regards,
Tomasz

P.S. Looks like your email client is set to HTML messages. Your
messages might end up dropped from the mailing list.


Re: [PATCH v2 01/13] iommu/rockchip: Request irqs in rk_iommu_probe()

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:08 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> Thanks for your reply.
>
> On 01/17/2018 12:21 PM, Tomasz Figa wrote:
>>
>> Hi Jeffy,
>>
>> Thanks for the patch. Please see my comments inline.
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> wrote:
>>
>> Please add patch description.
>
>
> ok, will do.
>>
>>
>>> Suggested-by: Robin Murphy 
>>> Signed-off-by: Jeffy Chen 
>>> ---
>>
>> [snip]
>>>
>>> -   for (i = 0; i < iommu->num_irq; i++) {
>>> -   iommu->irq[i] = platform_get_irq(pdev, i);
>>> -   if (iommu->irq[i] < 0) {
>>> -   dev_err(dev, "Failed to get IRQ, %d\n",
>>> iommu->irq[i]);
>>> +   num_irq = of_irq_count(dev->of_node);
>>> +   for (i = 0; i < num_irq; i++) {
>>> +   irq = platform_get_irq(pdev, i);
>>
>>
>> This lacks consistency. of_irq_count() is used for counting, but
>> platform_get_irq() is used for getting. Either platform_ or of_ API
>> should be used for both and I'd lean for platform_, since it's more
>> general.
>
> hmmm, right, i was thinking of removing num_irq, and do something like:
> while (nr++) {
>   err = platform_get_irq(dev, nr);
>   if (err == -EPROBE_DEFER)
>  break;
>   if (err < 0)
>  return err;
>   
> }
>
> but forgot to do that..

Was there anything wrong with platform_irq_count() used by existing code?

>
>>
>>> +   if (irq < 0) {
>>> +   dev_err(dev, "Failed to get IRQ, %d\n", irq);
>>>  return -ENXIO;
>>>  }
>>> +   err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
>>> +  IRQF_SHARED, dev_name(dev),
>>> iommu);
>>> +   if (err)
>>> +   return err;
>>>  }
>>
>>
>> Looks like there is some more initialization below. Is the driver okay
>> with the IRQ being potentially fired right here? (Shared IRQ handlers
>> might be run at request_irq() time for testing.)
>>
> right, forget about that. maybe we can check iommu->domain not NULL in
> rk_iommu_irq()

Maybe we could just move IRQ requesting to the end of probe?

Best regards,
Tomasz


Re: [PATCH v2 01/13] iommu/rockchip: Request irqs in rk_iommu_probe()

2018-01-16 Thread Tomasz Figa
On Wed, Jan 17, 2018 at 4:08 PM, JeffyChen  wrote:
> Hi Tomasz,
>
> Thanks for your reply.
>
> On 01/17/2018 12:21 PM, Tomasz Figa wrote:
>>
>> Hi Jeffy,
>>
>> Thanks for the patch. Please see my comments inline.
>>
>> On Tue, Jan 16, 2018 at 10:25 PM, Jeffy Chen 
>> wrote:
>>
>> Please add patch description.
>
>
> ok, will do.
>>
>>
>>> Suggested-by: Robin Murphy 
>>> Signed-off-by: Jeffy Chen 
>>> ---
>>
>> [snip]
>>>
>>> -   for (i = 0; i < iommu->num_irq; i++) {
>>> -   iommu->irq[i] = platform_get_irq(pdev, i);
>>> -   if (iommu->irq[i] < 0) {
>>> -   dev_err(dev, "Failed to get IRQ, %d\n",
>>> iommu->irq[i]);
>>> +   num_irq = of_irq_count(dev->of_node);
>>> +   for (i = 0; i < num_irq; i++) {
>>> +   irq = platform_get_irq(pdev, i);
>>
>>
>> This lacks consistency. of_irq_count() is used for counting, but
>> platform_get_irq() is used for getting. Either platform_ or of_ API
>> should be used for both and I'd lean for platform_, since it's more
>> general.
>
> hmmm, right, i was thinking of removing num_irq, and do something like:
> while (nr++) {
>   err = platform_get_irq(dev, nr);
>   if (err == -EPROBE_DEFER)
>  break;
>   if (err < 0)
>  return err;
>   
> }
>
> but forgot to do that..

Was there anything wrong with platform_irq_count() used by existing code?

>
>>
>>> +   if (irq < 0) {
>>> +   dev_err(dev, "Failed to get IRQ, %d\n", irq);
>>>  return -ENXIO;
>>>  }
>>> +   err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
>>> +  IRQF_SHARED, dev_name(dev),
>>> iommu);
>>> +   if (err)
>>> +   return err;
>>>  }
>>
>>
>> Looks like there is some more initialization below. Is the driver okay
>> with the IRQ being potentially fired right here? (Shared IRQ handlers
>> might be run at request_irq() time for testing.)
>>
> right, forget about that. maybe we can check iommu->domain not NULL in
> rk_iommu_irq()

Maybe we could just move IRQ requesting to the end of probe?

Best regards,
Tomasz


Re: WARNING in can_rcv

2018-01-16 Thread Eric Biggers
On Wed, Jan 17, 2018 at 07:39:24AM +0100, Oliver Hartkopp wrote:
> 
> 
> On 01/16/2018 07:11 PM, Dmitry Vyukov wrote:
> > On Tue, Jan 16, 2018 at 7:07 PM, Marc Kleine-Budde  
> > wrote:
> > > On 01/16/2018 06:58 PM, syzbot wrote:
> > > > Hello,
> > > > 
> > > > syzkaller hit the following crash on
> > > > a8750ddca918032d6349adbf9a4b6555e7db20da
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
> > > > compiler: gcc (GCC) 7.1.1 20170620
> > > > .config is attached
> > > > Raw console output is attached.
> > > > C reproducer is attached
> > > > syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> > > > for information about syzkaller reproducers
> > > > 
> > > > 
> > > > IMPORTANT: if you fix the bug, please add the following tag to the 
> > > > commit:
> > > > Reported-by: syzbot+4386709c0c1284dca...@syzkaller.appspotmail.com
> > > > It will help syzbot understand when the bug is fixed. See footer for
> > > > details.
> > > > If you forward the report, please keep this part and the footer.
> > > > 
> > > > device eql entered promiscuous mode
> > > > [ cut here ]
> > > > PF_CAN: dropped non conform CAN skbuf: dev type 65534, len 42, datalen 0
> > > > WARNING: CPU: 0 PID: 3650 at net/can/af_can.c:729 can_rcv+0x1c5/0x200
> > > > net/can/af_can.c:724
> > > > Kernel panic - not syncing: panic_on_warn set ...
> > > 
> > > Invalid packages generate a warning (WARN_ONCE()), and you have
> > > panic_on_warn active. Should we better silently drop these CAN packages?
> > 
> > Hi,
> > 
> > pr_warn_once() will be more appropriate. It prints a single line.
> > 
> 
> The idea behind this WARN() is to detect really bad things that might have
> happen on network driver level:
> 
> The CAN subsystem registers with dev_add_pack() for ETH_P_CAN and
> ETH_P_CANFD only. These ETH_P_ types are only allowed to be created by CAN
> network devices (like vcan, vxcan, and real CAN drivers).
> 
> I don't have any strong opinion on using WARN() or pr_warn_once().
> Is this detected violation worth using WARN(), as something already must
> have gone really wrong to trigger this issue?
> 

WARN() indicates a kernel bug.  If it's instead "userspace did something
stupid", or "someone sent some unexpected network packet", it needs to be
pr_warn_once(), pr_warn_ratelimited(), or removed entirely.

Eric


Re: WARNING in can_rcv

2018-01-16 Thread Eric Biggers
On Wed, Jan 17, 2018 at 07:39:24AM +0100, Oliver Hartkopp wrote:
> 
> 
> On 01/16/2018 07:11 PM, Dmitry Vyukov wrote:
> > On Tue, Jan 16, 2018 at 7:07 PM, Marc Kleine-Budde  
> > wrote:
> > > On 01/16/2018 06:58 PM, syzbot wrote:
> > > > Hello,
> > > > 
> > > > syzkaller hit the following crash on
> > > > a8750ddca918032d6349adbf9a4b6555e7db20da
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
> > > > compiler: gcc (GCC) 7.1.1 20170620
> > > > .config is attached
> > > > Raw console output is attached.
> > > > C reproducer is attached
> > > > syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> > > > for information about syzkaller reproducers
> > > > 
> > > > 
> > > > IMPORTANT: if you fix the bug, please add the following tag to the 
> > > > commit:
> > > > Reported-by: syzbot+4386709c0c1284dca...@syzkaller.appspotmail.com
> > > > It will help syzbot understand when the bug is fixed. See footer for
> > > > details.
> > > > If you forward the report, please keep this part and the footer.
> > > > 
> > > > device eql entered promiscuous mode
> > > > [ cut here ]
> > > > PF_CAN: dropped non conform CAN skbuf: dev type 65534, len 42, datalen 0
> > > > WARNING: CPU: 0 PID: 3650 at net/can/af_can.c:729 can_rcv+0x1c5/0x200
> > > > net/can/af_can.c:724
> > > > Kernel panic - not syncing: panic_on_warn set ...
> > > 
> > > Invalid packages generate a warning (WARN_ONCE()), and you have
> > > panic_on_warn active. Should we better silently drop these CAN packages?
> > 
> > Hi,
> > 
> > pr_warn_once() will be more appropriate. It prints a single line.
> > 
> 
> The idea behind this WARN() is to detect really bad things that might have
> happen on network driver level:
> 
> The CAN subsystem registers with dev_add_pack() for ETH_P_CAN and
> ETH_P_CANFD only. These ETH_P_ types are only allowed to be created by CAN
> network devices (like vcan, vxcan, and real CAN drivers).
> 
> I don't have any strong opinion on using WARN() or pr_warn_once().
> Is this detected violation worth using WARN(), as something already must
> have gone really wrong to trigger this issue?
> 

WARN() indicates a kernel bug.  If it's instead "userspace did something
stupid", or "someone sent some unexpected network packet", it needs to be
pr_warn_once(), pr_warn_ratelimited(), or removed entirely.

Eric


Re: [PATCH 32/32] aio: implement io_pgetevents

2018-01-16 Thread Christoph Hellwig
On Wed, Jan 17, 2018 at 04:27:21AM +, Al Viro wrote:
> On Tue, Jan 16, 2018 at 07:41:24PM -0500, Jeff Moyer wrote:
> > if (sigmask) {
> > -   if (copy_from_user(, sigmask, sizeof(ksigmask)))
> > +   if (!access_ok(VERIFY_READ, sigmask,
> > +  sizeof(void *) + sizeof(size_t)) ||
> > +   __get_user(up, (sigset_t __user * __user *)sigmask) ||
> > +   __get_user(sigsetsize,
> > +  (size_t __user *)(sigmask + sizeof(void *
> > return -EFAULT;
> 
> How about copy_from_user() on a struct?  Making eyes bleed is fun, but
> people tend to get annoyed when you do it to them...

Above is the copy & paste version from pselect.  I've got both copy_from_user
and that horrible version in my tree, and if we really need this awfull
calling convention copy_from_user certainly is much better.  pselect
also should be switched to explicit struct + copy_from_user while
we're at it.  In fact glibc defines a struct for the userland version
to start with.


Re: [PATCH 32/32] aio: implement io_pgetevents

2018-01-16 Thread Christoph Hellwig
On Wed, Jan 17, 2018 at 04:27:21AM +, Al Viro wrote:
> On Tue, Jan 16, 2018 at 07:41:24PM -0500, Jeff Moyer wrote:
> > if (sigmask) {
> > -   if (copy_from_user(, sigmask, sizeof(ksigmask)))
> > +   if (!access_ok(VERIFY_READ, sigmask,
> > +  sizeof(void *) + sizeof(size_t)) ||
> > +   __get_user(up, (sigset_t __user * __user *)sigmask) ||
> > +   __get_user(sigsetsize,
> > +  (size_t __user *)(sigmask + sizeof(void *
> > return -EFAULT;
> 
> How about copy_from_user() on a struct?  Making eyes bleed is fun, but
> people tend to get annoyed when you do it to them...

Above is the copy & paste version from pselect.  I've got both copy_from_user
and that horrible version in my tree, and if we really need this awfull
calling convention copy_from_user certainly is much better.  pselect
also should be switched to explicit struct + copy_from_user while
we're at it.  In fact glibc defines a struct for the userland version
to start with.


Re: [PATCH net-next] net: stmmac: Fix reception of Broadcom switches tags

2018-01-16 Thread Giuseppe CAVALLARO

Hi Florian

for gmac4.x and gmac3.x series the ACS bit is the Automatic Pad or CRC 
Stripping, so the
core strips the Pad or FCS on frames if the value of the length field is 
< 1536 bytes.
For MAC10-100 there is the Bit 8 (ASTP) of the reg0 that does the same 
if len is < 46bytes.
In your patch I can just suggest to add a new field to strip the PAD/FCS 
w/o passing the whole
netdev struct to the core_init. In the main driver, we could manage the 
pad-strip feature (also
by using dt) or disable it in case of netdev_uses_dsa; then propagating 
this setting to the core_init

or calling a new callback. What do you think?

Regards
Peppe

On 1/17/2018 12:25 AM, Florian Fainelli wrote:

Broadcom tags inserted by Broadcom switches put a 4 byte header after
the MAC SA and before the EtherType, which may look like some sort of 0
length LLC/SNAP packet (tcpdump and wireshark do think that way). With
ACS enabled in stmmac the packets were truncated to 8 bytes on
reception, whereas clearing this bit allowed normal reception to occur.

In order to make that possible, we need to pass a net_device argument to
the different core_init() functions and we are dependent on the Broadcom
tagger padding packets correctly (which it now does). To be as little
invasive as possible, this is only done for gmac1000 when the network
device is DSA-enabled (netdev_uses_dsa() returns true).

Signed-off-by: Florian Fainelli 
---
  drivers/net/ethernet/stmicro/stmmac/common.h |  2 +-
  drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c|  3 ++-
  drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 12 +++-
  drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c  |  3 ++-
  drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c| 11 ++-
  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c|  2 +-
  6 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h 
b/drivers/net/ethernet/stmicro/stmmac/common.h
index ce2ea2d491ac..2ffe76c0ff74 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -474,7 +474,7 @@ struct mac_device_info;
  /* Helpers to program the MAC core */
  struct stmmac_ops {
/* MAC core initialization */
-   void (*core_init)(struct mac_device_info *hw, int mtu);
+   void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
/* Enable the MAC RX/TX */
void (*set_mac)(void __iomem *ioaddr, bool enable);
/* Enable and verify that the IPC module is supported */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 9eb7f65d8000..a3fa65b1ca8e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -483,7 +483,8 @@ static int sun8i_dwmac_init(struct platform_device *pdev, 
void *priv)
return 0;
  }
  
-static void sun8i_dwmac_core_init(struct mac_device_info *hw, int mtu)

+static void sun8i_dwmac_core_init(struct mac_device_info *hw,
+ struct net_device *dev)
  {
void __iomem *ioaddr = hw->pcsr;
u32 v;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 8a86340ff2d3..540d21786a43 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -25,18 +25,28 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include "stmmac_pcs.h"
  #include "dwmac1000.h"
  
-static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)

+static void dwmac1000_core_init(struct mac_device_info *hw,
+   struct net_device *dev)
  {
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONTROL);
+   int mtu = dev->mtu;
  
  	/* Configure GMAC core */

value |= GMAC_CORE_INIT;
  
+	/* Clear ACS bit because Ethernet switch tagging formats such as

+* Broadcom tags can look like invalid LLC/SNAP packets and cause the
+* hardware to truncate packets on reception.
+*/
+   if (netdev_uses_dsa(dev))
+   value &= ~GMAC_CONTROL_ACS;
+
if (mtu > 1500)
value |= GMAC_CONTROL_2K;
if (mtu > 2000)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 8ef517356313..c1ee427c42cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -28,7 +28,8 @@
  #include 
  #include "dwmac100.h"
  
-static void dwmac100_core_init(struct mac_device_info *hw, int mtu)

+static void dwmac100_core_init(struct mac_device_info *hw,
+  struct net_device *dev)
  {
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr 

Re: [PATCH net-next] net: stmmac: Fix reception of Broadcom switches tags

2018-01-16 Thread Giuseppe CAVALLARO

Hi Florian

for gmac4.x and gmac3.x series the ACS bit is the Automatic Pad or CRC 
Stripping, so the
core strips the Pad or FCS on frames if the value of the length field is 
< 1536 bytes.
For MAC10-100 there is the Bit 8 (ASTP) of the reg0 that does the same 
if len is < 46bytes.
In your patch I can just suggest to add a new field to strip the PAD/FCS 
w/o passing the whole
netdev struct to the core_init. In the main driver, we could manage the 
pad-strip feature (also
by using dt) or disable it in case of netdev_uses_dsa; then propagating 
this setting to the core_init

or calling a new callback. What do you think?

Regards
Peppe

On 1/17/2018 12:25 AM, Florian Fainelli wrote:

Broadcom tags inserted by Broadcom switches put a 4 byte header after
the MAC SA and before the EtherType, which may look like some sort of 0
length LLC/SNAP packet (tcpdump and wireshark do think that way). With
ACS enabled in stmmac the packets were truncated to 8 bytes on
reception, whereas clearing this bit allowed normal reception to occur.

In order to make that possible, we need to pass a net_device argument to
the different core_init() functions and we are dependent on the Broadcom
tagger padding packets correctly (which it now does). To be as little
invasive as possible, this is only done for gmac1000 when the network
device is DSA-enabled (netdev_uses_dsa() returns true).

Signed-off-by: Florian Fainelli 
---
  drivers/net/ethernet/stmicro/stmmac/common.h |  2 +-
  drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c|  3 ++-
  drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 12 +++-
  drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c  |  3 ++-
  drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c| 11 ++-
  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c|  2 +-
  6 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h 
b/drivers/net/ethernet/stmicro/stmmac/common.h
index ce2ea2d491ac..2ffe76c0ff74 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -474,7 +474,7 @@ struct mac_device_info;
  /* Helpers to program the MAC core */
  struct stmmac_ops {
/* MAC core initialization */
-   void (*core_init)(struct mac_device_info *hw, int mtu);
+   void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
/* Enable the MAC RX/TX */
void (*set_mac)(void __iomem *ioaddr, bool enable);
/* Enable and verify that the IPC module is supported */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 9eb7f65d8000..a3fa65b1ca8e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -483,7 +483,8 @@ static int sun8i_dwmac_init(struct platform_device *pdev, 
void *priv)
return 0;
  }
  
-static void sun8i_dwmac_core_init(struct mac_device_info *hw, int mtu)

+static void sun8i_dwmac_core_init(struct mac_device_info *hw,
+ struct net_device *dev)
  {
void __iomem *ioaddr = hw->pcsr;
u32 v;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 8a86340ff2d3..540d21786a43 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -25,18 +25,28 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include "stmmac_pcs.h"
  #include "dwmac1000.h"
  
-static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)

+static void dwmac1000_core_init(struct mac_device_info *hw,
+   struct net_device *dev)
  {
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONTROL);
+   int mtu = dev->mtu;
  
  	/* Configure GMAC core */

value |= GMAC_CORE_INIT;
  
+	/* Clear ACS bit because Ethernet switch tagging formats such as

+* Broadcom tags can look like invalid LLC/SNAP packets and cause the
+* hardware to truncate packets on reception.
+*/
+   if (netdev_uses_dsa(dev))
+   value &= ~GMAC_CONTROL_ACS;
+
if (mtu > 1500)
value |= GMAC_CONTROL_2K;
if (mtu > 2000)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 8ef517356313..c1ee427c42cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -28,7 +28,8 @@
  #include 
  #include "dwmac100.h"
  
-static void dwmac100_core_init(struct mac_device_info *hw, int mtu)

+static void dwmac100_core_init(struct mac_device_info *hw,
+  struct net_device *dev)
  {
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + MAC_CONTROL);
diff 

[PATCH v5 01/17] ASoC: fsl_ssi: Redefine RX and TX macros

2018-01-16 Thread Nicolin Chen
The RX and TX macros were defined implicitly and there was
a potential risk if someone changes their values.

Since they were defined to index the array ssi->regvals[2],
this patch moves these two macros to fsl_ssi.c, closer to
its owner ssi->regvals. And it also puts some comments here
to limit their value within [0, 1].

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 4 
 sound/soc/fsl/fsl_ssi.h | 3 ---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index aecd00f..001e453 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -56,6 +56,10 @@
 #include "fsl_ssi.h"
 #include "imx-pcm.h"
 
+/* Define RX and TX to index ssi->regvals array; Can be 0 or 1 only */
+#define RX 0
+#define TX 1
+
 /**
  * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
  *
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index de2fdc5..18f8dd5 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -12,9 +12,6 @@
 #ifndef _MPC8610_I2S_H
 #define _MPC8610_I2S_H
 
-#define RX 0
-#define TX 1
-
 /* -- SSI Register Map -- */
 
 /* SSI Transmit Data Register 0 */
-- 
2.7.4



[PATCH v5 01/17] ASoC: fsl_ssi: Redefine RX and TX macros

2018-01-16 Thread Nicolin Chen
The RX and TX macros were defined implicitly and there was
a potential risk if someone changes their values.

Since they were defined to index the array ssi->regvals[2],
this patch moves these two macros to fsl_ssi.c, closer to
its owner ssi->regvals. And it also puts some comments here
to limit their value within [0, 1].

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 4 
 sound/soc/fsl/fsl_ssi.h | 3 ---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index aecd00f..001e453 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -56,6 +56,10 @@
 #include "fsl_ssi.h"
 #include "imx-pcm.h"
 
+/* Define RX and TX to index ssi->regvals array; Can be 0 or 1 only */
+#define RX 0
+#define TX 1
+
 /**
  * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
  *
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index de2fdc5..18f8dd5 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -12,9 +12,6 @@
 #ifndef _MPC8610_I2S_H
 #define _MPC8610_I2S_H
 
-#define RX 0
-#define TX 1
-
 /* -- SSI Register Map -- */
 
 /* SSI Transmit Data Register 0 */
-- 
2.7.4



[PATCH v5 04/17] ASoC: fsl_ssi: Maintain a mask of active streams

2018-01-16 Thread Nicolin Chen
Checking TE and RE bits in SCR register doesn't work for AC97 mode
which enables SSIEN, TE and RE in the fsl_ssi_setup_ac97() that's
called during probe().

So when running into the trigger(), it will always get the result
of both TE and RE being enabled already, even if actually there is
no active stream.

This patch fixes this issue by adding a variable to log the active
streams manually.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Replaced "bool dir" with "int dir"
v2
 * Replaced bool tx with bool dir

 sound/soc/fsl/fsl_ssi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 8984ee2..51e7405 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -205,6 +205,7 @@ struct fsl_ssi_soc_data {
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
+ * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
@@ -249,6 +250,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
+   u8 streams;
u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
@@ -444,15 +446,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   int dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
int nr_active_streams;
-   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, );
-
-   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
+   nr_active_streams = !!(ssi->streams & BIT(TX)) +
+   !!(ssi->streams & BIT(RX));
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -474,6 +475,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
  keep_active);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
+
+   /* Log the disabled stream to the mask */
+   ssi->streams &= ~BIT(dir);
}
 
/*
@@ -549,6 +553,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
}
/* Enable all remaining bits */
regmap_update_bits(regs, REG_SSI_SCR, vals->scr, vals->scr);
+
+   /* Log the enabled stream to the mask */
+   ssi->streams |= BIT(dir);
}
 }
 
-- 
2.7.4



[PATCH v5 04/17] ASoC: fsl_ssi: Maintain a mask of active streams

2018-01-16 Thread Nicolin Chen
Checking TE and RE bits in SCR register doesn't work for AC97 mode
which enables SSIEN, TE and RE in the fsl_ssi_setup_ac97() that's
called during probe().

So when running into the trigger(), it will always get the result
of both TE and RE being enabled already, even if actually there is
no active stream.

This patch fixes this issue by adding a variable to log the active
streams manually.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Replaced "bool dir" with "int dir"
v2
 * Replaced bool tx with bool dir

 sound/soc/fsl/fsl_ssi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 8984ee2..51e7405 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -205,6 +205,7 @@ struct fsl_ssi_soc_data {
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
+ * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
@@ -249,6 +250,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
+   u8 streams;
u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
@@ -444,15 +446,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   int dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
int nr_active_streams;
-   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, );
-
-   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
+   nr_active_streams = !!(ssi->streams & BIT(TX)) +
+   !!(ssi->streams & BIT(RX));
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -474,6 +475,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
  keep_active);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
+
+   /* Log the disabled stream to the mask */
+   ssi->streams &= ~BIT(dir);
}
 
/*
@@ -549,6 +553,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
}
/* Enable all remaining bits */
regmap_update_bits(regs, REG_SSI_SCR, vals->scr, vals->scr);
+
+   /* Log the enabled stream to the mask */
+   ssi->streams |= BIT(dir);
}
 }
 
-- 
2.7.4



[PATCH v5 05/17] ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro

2018-01-16 Thread Nicolin Chen
The define of fsl_ssi_disable_val is not so clear as it mixes two
steps of calculations together. And those parameter names are also
a bit long to read.

Since it just tries to exclude the shared bits from the regvals of
current stream while the opposite stream is active, it's better to
use something like ssi_excl_shared_bits.

This patch also bisects fsl_ssi_disable_val into two macros of two
corresponding steps and then shortens its parameter names. It also
updates callers in the fsl_ssi_config() accordingly.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Replaced !dir with int adir

 sound/soc/fsl/fsl_ssi.c | 55 +
 1 file changed, 23 insertions(+), 32 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 51e7405..bbeef71 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -421,24 +421,24 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 }
 
 /**
- * Calculate the bits that have to be disabled for the current stream that is
- * getting disabled. This keeps the bits enabled that are necessary for the
- * second stream to work if 'stream_active' is true.
+ * Exclude bits that are used by the opposite stream
  *
- * Detailed calculation:
- * These are the values that need to be active after disabling. For non-active
- * second stream, this is 0:
- * vals_stream * !!stream_active
+ * When both streams are active, disabling some bits for the current stream
+ * might break the other stream if these bits are used by it.
  *
- * The following computes the overall differences between the setup for the
- * to-disable stream and the active stream, a simple XOR:
- * vals_disable ^ (vals_stream * !!(stream_active))
+ * @vals : regvals of the current stream
+ * @avals: regvals of the opposite stream
+ * @aactive: active state of the opposite stream
  *
- * The full expression adds a mask on all values we care about
+ *  1) XOR vals and avals to get the differences if the other stream is active;
+ * Otherwise, return current vals if the other stream is not active
+ *  2) AND the result of 1) with the current vals
  */
-#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
-   ((vals_disable) & \
-((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active
+#define _ssi_xor_shared_bits(vals, avals, aactive) \
+   ((vals) ^ ((avals) * (aactive)))
+
+#define ssi_excl_shared_bits(vals, avals, aactive) \
+   ((vals) & _ssi_xor_shared_bits(vals, avals, aactive))
 
 /**
  * Enable or disable SSI configuration.
@@ -446,19 +446,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   int adir = (>regvals[TX] == vals) ? RX : TX;
int dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
-   int nr_active_streams;
-   int keep_active;
-
-   nr_active_streams = !!(ssi->streams & BIT(TX)) +
-   !!(ssi->streams & BIT(RX));
+   bool aactive;
 
-   if (nr_active_streams - 1 > 0)
-   keep_active = 1;
-   else
-   keep_active = 0;
+   /* Check if the opposite stream is active */
+   aactive = ssi->streams & BIT(adir);
 
/* Get the opposite direction to keep its values untouched */
if (>regvals[RX] == vals)
@@ -471,8 +466,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
- keep_active);
+   u32 scr = ssi_excl_shared_bits(vals->scr, avals->scr, aactive);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
 
@@ -487,7 +481,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * 2) Disable all remaining bits of both streams when last stream ends
 */
if (ssi->soc->offline_config) {
-   if ((enable && !nr_active_streams) || (!enable && !keep_active))
+   if ((enable && !ssi->streams) || (!enable && !aactive))
fsl_ssi_rxtx_config(ssi, enable);
 
goto config_done;
@@ -509,12 +503,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   sier = fsl_ssi_disable_val(vals->sier, avals->sier,
- 

[PATCH v5 03/17] ASoC: fsl_ssi: Clean up set_dai_tdm_slot()

2018-01-16 Thread Nicolin Chen
This patch replaces the register read with ssi->i2s_net for
simplification. It also removes masking SSIEN from scr value
since it's handled later by regmap_update_bits() to set this
scr value back.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 9847a1d..8984ee2 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1055,9 +1055,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
}
 
/* The slot number should be >= 2 if using Network mode or I2S mode */
-   regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET;
-   if (val && slots < 2) {
+   if (ssi->i2s_net && slots < 2) {
dev_err(dai->dev, "slot number should be >= 2 in I2S or NET\n");
return -EINVAL;
}
@@ -1067,9 +1065,8 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
regmap_update_bits(regs, REG_SSI_SRCCR,
   SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
 
-   /* Save SSIEN bit of the SCR register */
+   /* Save the SCR register value */
regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_SSIEN;
/* Temporarily enable SSI to allow SxMSKs to be configurable */
regmap_update_bits(regs, REG_SSI_SCR, SSI_SCR_SSIEN, SSI_SCR_SSIEN);
 
-- 
2.7.4



[PATCH v5 05/17] ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro

2018-01-16 Thread Nicolin Chen
The define of fsl_ssi_disable_val is not so clear as it mixes two
steps of calculations together. And those parameter names are also
a bit long to read.

Since it just tries to exclude the shared bits from the regvals of
current stream while the opposite stream is active, it's better to
use something like ssi_excl_shared_bits.

This patch also bisects fsl_ssi_disable_val into two macros of two
corresponding steps and then shortens its parameter names. It also
updates callers in the fsl_ssi_config() accordingly.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Replaced !dir with int adir

 sound/soc/fsl/fsl_ssi.c | 55 +
 1 file changed, 23 insertions(+), 32 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 51e7405..bbeef71 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -421,24 +421,24 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 }
 
 /**
- * Calculate the bits that have to be disabled for the current stream that is
- * getting disabled. This keeps the bits enabled that are necessary for the
- * second stream to work if 'stream_active' is true.
+ * Exclude bits that are used by the opposite stream
  *
- * Detailed calculation:
- * These are the values that need to be active after disabling. For non-active
- * second stream, this is 0:
- * vals_stream * !!stream_active
+ * When both streams are active, disabling some bits for the current stream
+ * might break the other stream if these bits are used by it.
  *
- * The following computes the overall differences between the setup for the
- * to-disable stream and the active stream, a simple XOR:
- * vals_disable ^ (vals_stream * !!(stream_active))
+ * @vals : regvals of the current stream
+ * @avals: regvals of the opposite stream
+ * @aactive: active state of the opposite stream
  *
- * The full expression adds a mask on all values we care about
+ *  1) XOR vals and avals to get the differences if the other stream is active;
+ * Otherwise, return current vals if the other stream is not active
+ *  2) AND the result of 1) with the current vals
  */
-#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
-   ((vals_disable) & \
-((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active
+#define _ssi_xor_shared_bits(vals, avals, aactive) \
+   ((vals) ^ ((avals) * (aactive)))
+
+#define ssi_excl_shared_bits(vals, avals, aactive) \
+   ((vals) & _ssi_xor_shared_bits(vals, avals, aactive))
 
 /**
  * Enable or disable SSI configuration.
@@ -446,19 +446,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   int adir = (>regvals[TX] == vals) ? RX : TX;
int dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
-   int nr_active_streams;
-   int keep_active;
-
-   nr_active_streams = !!(ssi->streams & BIT(TX)) +
-   !!(ssi->streams & BIT(RX));
+   bool aactive;
 
-   if (nr_active_streams - 1 > 0)
-   keep_active = 1;
-   else
-   keep_active = 0;
+   /* Check if the opposite stream is active */
+   aactive = ssi->streams & BIT(adir);
 
/* Get the opposite direction to keep its values untouched */
if (>regvals[RX] == vals)
@@ -471,8 +466,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
- keep_active);
+   u32 scr = ssi_excl_shared_bits(vals->scr, avals->scr, aactive);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
 
@@ -487,7 +481,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * 2) Disable all remaining bits of both streams when last stream ends
 */
if (ssi->soc->offline_config) {
-   if ((enable && !nr_active_streams) || (!enable && !keep_active))
+   if ((enable && !ssi->streams) || (!enable && !aactive))
fsl_ssi_rxtx_config(ssi, enable);
 
goto config_done;
@@ -509,12 +503,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   sier = fsl_ssi_disable_val(vals->sier, avals->sier,
-  keep_active);
-   srcr = 

[PATCH v5 03/17] ASoC: fsl_ssi: Clean up set_dai_tdm_slot()

2018-01-16 Thread Nicolin Chen
This patch replaces the register read with ssi->i2s_net for
simplification. It also removes masking SSIEN from scr value
since it's handled later by regmap_update_bits() to set this
scr value back.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 9847a1d..8984ee2 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1055,9 +1055,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
}
 
/* The slot number should be >= 2 if using Network mode or I2S mode */
-   regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET;
-   if (val && slots < 2) {
+   if (ssi->i2s_net && slots < 2) {
dev_err(dai->dev, "slot number should be >= 2 in I2S or NET\n");
return -EINVAL;
}
@@ -1067,9 +1065,8 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
regmap_update_bits(regs, REG_SSI_SRCCR,
   SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
 
-   /* Save SSIEN bit of the SCR register */
+   /* Save the SCR register value */
regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_SSIEN;
/* Temporarily enable SSI to allow SxMSKs to be configurable */
regmap_update_bits(regs, REG_SSI_SCR, SSI_SCR_SSIEN, SSI_SCR_SSIEN);
 
-- 
2.7.4



[PATCH v5 06/17] ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()

2018-01-16 Thread Nicolin Chen
The FIFO clear helper function is just one line of code now.
So it could be cleaned up by removing it and calling regmap
directly.

Meanwhile, FIFO clear could be applied to all use cases, not
confined to AC97. So this patch also moves FIFO clear in the
trigger() to fsl_ssi_config() and removes the AC97 check.

Note that SOR register is safe from offline_config HW limit.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Replaced "bool dir" with "int dir" and "int adir"
v2
 * Replaced bool tx with bool dir

 sound/soc/fsl/fsl_ssi.c | 33 ++---
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index bbeef71..a2ac92f 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -410,17 +410,6 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 }
 
 /**
- * Clear remaining data in the FIFO to avoid dirty data or channel slipping
- */
-static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
-{
-   bool tx = !is_rx;
-
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
-}
-
-/**
  * Exclude bits that are used by the opposite stream
  *
  * When both streams are active, disabling some bits for the current stream
@@ -446,10 +435,11 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
-   int adir = (>regvals[TX] == vals) ? RX : TX;
-   int dir = (>regvals[TX] == vals) ? TX : RX;
+   bool tx = >regvals[TX] == vals;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
+   int adir = tx ? RX : TX;
+   int dir = tx ? TX : RX;
bool aactive;
 
/* Check if the opposite stream is active */
@@ -489,7 +479,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
/* Online configure single direction while SSI is running */
if (enable) {
-   fsl_ssi_fifo_clear(ssi, vals->scr & SSI_SCR_RE);
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 
regmap_update_bits(regs, REG_SSI_SRCR, vals->srcr, vals->srcr);
regmap_update_bits(regs, REG_SSI_STCR, vals->stcr, vals->stcr);
@@ -511,6 +503,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
regmap_update_bits(regs, REG_SSI_SRCR, srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR, stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER, sier, 0);
+
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
}
 
 config_done:
@@ -1091,7 +1087,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-   struct regmap *regs = ssi->regs;
 
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -1116,14 +,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
return -EINVAL;
}
 
-   /* Clear corresponding FIFO */
-   if (fsl_ssi_is_ac97(ssi)) {
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_TX_CLR);
-   else
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_RX_CLR);
-   }
-
return 0;
 }
 
-- 
2.7.4



[PATCH v5 06/17] ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()

2018-01-16 Thread Nicolin Chen
The FIFO clear helper function is just one line of code now.
So it could be cleaned up by removing it and calling regmap
directly.

Meanwhile, FIFO clear could be applied to all use cases, not
confined to AC97. So this patch also moves FIFO clear in the
trigger() to fsl_ssi_config() and removes the AC97 check.

Note that SOR register is safe from offline_config HW limit.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Replaced "bool dir" with "int dir" and "int adir"
v2
 * Replaced bool tx with bool dir

 sound/soc/fsl/fsl_ssi.c | 33 ++---
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index bbeef71..a2ac92f 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -410,17 +410,6 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 }
 
 /**
- * Clear remaining data in the FIFO to avoid dirty data or channel slipping
- */
-static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
-{
-   bool tx = !is_rx;
-
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
-}
-
-/**
  * Exclude bits that are used by the opposite stream
  *
  * When both streams are active, disabling some bits for the current stream
@@ -446,10 +435,11 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
-   int adir = (>regvals[TX] == vals) ? RX : TX;
-   int dir = (>regvals[TX] == vals) ? TX : RX;
+   bool tx = >regvals[TX] == vals;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
+   int adir = tx ? RX : TX;
+   int dir = tx ? TX : RX;
bool aactive;
 
/* Check if the opposite stream is active */
@@ -489,7 +479,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
/* Online configure single direction while SSI is running */
if (enable) {
-   fsl_ssi_fifo_clear(ssi, vals->scr & SSI_SCR_RE);
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 
regmap_update_bits(regs, REG_SSI_SRCR, vals->srcr, vals->srcr);
regmap_update_bits(regs, REG_SSI_STCR, vals->stcr, vals->stcr);
@@ -511,6 +503,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
regmap_update_bits(regs, REG_SSI_SRCR, srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR, stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER, sier, 0);
+
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
}
 
 config_done:
@@ -1091,7 +1087,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-   struct regmap *regs = ssi->regs;
 
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -1116,14 +,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
return -EINVAL;
}
 
-   /* Clear corresponding FIFO */
-   if (fsl_ssi_is_ac97(ssi)) {
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_TX_CLR);
-   else
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_RX_CLR);
-   }
-
return 0;
 }
 
-- 
2.7.4



[PATCH v5 08/17] ASoC: fsl_ssi: Add DAIFMT define for AC97

2018-01-16 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() bypasses an undefined format for AC97
mode. However, it's not really necessary if AC97 has its complete
format defined.

So this patch adds a DAIFMT macro of complete format including a
clock direction and polarity.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7a6a32b..b76a517 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -90,6 +90,16 @@
 SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
+/*
+ * In AC97 mode, TXDIR bit is forced to 0 and TFDIR bit is forced to 1:
+ *  - SSI inputs external bit clock and outputs frame sync clock -- CBM_CFS
+ *  - Also have NB_NF to mark these two clocks will not be inverted
+ */
+#define FSLSSI_AC97_DAIFMT \
+   (SND_SOC_DAIFMT_AC97 | \
+SND_SOC_DAIFMT_CBM_CFS | \
+SND_SOC_DAIFMT_NB_NF)
+
 #define FSLSSI_SIER_DBG_RX_FLAGS \
(SSI_SIER_RFF0_EN | \
 SSI_SIER_RLS_EN | \
@@ -964,8 +974,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
scr &= ~SSI_SCR_SYS_CLK_EN;
break;
default:
-   if (!fsl_ssi_is_ac97(ssi))
-   return -EINVAL;
+   return -EINVAL;
}
 
stcr |= strcr;
@@ -1372,7 +1381,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = SND_SOC_DAIFMT_AC97;
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
}
 
/* Select DMA or FIQ */
-- 
2.7.4



[PATCH v5 08/17] ASoC: fsl_ssi: Add DAIFMT define for AC97

2018-01-16 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() bypasses an undefined format for AC97
mode. However, it's not really necessary if AC97 has its complete
format defined.

So this patch adds a DAIFMT macro of complete format including a
clock direction and polarity.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7a6a32b..b76a517 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -90,6 +90,16 @@
 SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
+/*
+ * In AC97 mode, TXDIR bit is forced to 0 and TFDIR bit is forced to 1:
+ *  - SSI inputs external bit clock and outputs frame sync clock -- CBM_CFS
+ *  - Also have NB_NF to mark these two clocks will not be inverted
+ */
+#define FSLSSI_AC97_DAIFMT \
+   (SND_SOC_DAIFMT_AC97 | \
+SND_SOC_DAIFMT_CBM_CFS | \
+SND_SOC_DAIFMT_NB_NF)
+
 #define FSLSSI_SIER_DBG_RX_FLAGS \
(SSI_SIER_RFF0_EN | \
 SSI_SIER_RLS_EN | \
@@ -964,8 +974,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
scr &= ~SSI_SCR_SYS_CLK_EN;
break;
default:
-   if (!fsl_ssi_is_ac97(ssi))
-   return -EINVAL;
+   return -EINVAL;
}
 
stcr |= strcr;
@@ -1372,7 +1381,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = SND_SOC_DAIFMT_AC97;
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
}
 
/* Select DMA or FIQ */
-- 
2.7.4



[PATCH v5 02/17] ASoC: fsl_ssi: Keep ssi->i2s_net updated

2018-01-16 Thread Nicolin Chen
The hw_params() overwrites i2s_net settings for special cases like
mono-channel support, however, it doesn't update ssi->i2s_net as
set_dai_fmt() does.

This patch removes the local i2s_net variable and directly updates
ssi->i2s_net in the hw_params() so that the driver can simply look
up the ssi->i2s_net instead of reading the register.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 001e453..9847a1d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -838,16 +838,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   u8 i2s_net;
/* Normal + Network mode to send 16-bit data in 32-bit frames */
if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16)
-   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
-   else
-   i2s_net = ssi->i2s_net;
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+
+   /* Use Normal mode to send mono data at 1st slot of 2 slots */
+   if (channels == 1)
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_I2S_NET_MASK,
-  channels == 1 ? 0 : i2s_net);
+  SSI_SCR_I2S_NET_MASK, ssi->i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-- 
2.7.4



[PATCH v5 02/17] ASoC: fsl_ssi: Keep ssi->i2s_net updated

2018-01-16 Thread Nicolin Chen
The hw_params() overwrites i2s_net settings for special cases like
mono-channel support, however, it doesn't update ssi->i2s_net as
set_dai_fmt() does.

This patch removes the local i2s_net variable and directly updates
ssi->i2s_net in the hw_params() so that the driver can simply look
up the ssi->i2s_net instead of reading the register.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 001e453..9847a1d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -838,16 +838,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   u8 i2s_net;
/* Normal + Network mode to send 16-bit data in 32-bit frames */
if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16)
-   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
-   else
-   i2s_net = ssi->i2s_net;
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+
+   /* Use Normal mode to send mono data at 1st slot of 2 slots */
+   if (channels == 1)
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_I2S_NET_MASK,
-  channels == 1 ? 0 : i2s_net);
+  SSI_SCR_I2S_NET_MASK, ssi->i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-- 
2.7.4



[PATCH v5 10/17] ASoC: fsl_ssi: Set xFEN0 and xFEN1 together

2018-01-16 Thread Nicolin Chen
It'd be safer to enable both FIFOs for TX or RX at the same time.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e5efee2..ba06e94 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -591,6 +591,11 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
if (fsl_ssi_is_ac97(ssi))
vals[RX].scr = vals[TX].scr = 0;
 
+   if (ssi->use_dual_fifo) {
+   vals[RX].srcr |= SSI_SRCR_RFEN1;
+   vals[TX].stcr |= SSI_STCR_TFEN1;
+   }
+
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
vals[TX].sier |= SSI_SIER_TDMAE;
@@ -991,14 +996,9 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
 SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
 
-   if (ssi->use_dual_fifo) {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  SSI_SRCR_RFEN1, SSI_SRCR_RFEN1);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  SSI_STCR_TFEN1, SSI_STCR_TFEN1);
+   if (ssi->use_dual_fifo)
regmap_update_bits(regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-   }
 
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
-- 
2.7.4



[PATCH v5 10/17] ASoC: fsl_ssi: Set xFEN0 and xFEN1 together

2018-01-16 Thread Nicolin Chen
It'd be safer to enable both FIFOs for TX or RX at the same time.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e5efee2..ba06e94 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -591,6 +591,11 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
if (fsl_ssi_is_ac97(ssi))
vals[RX].scr = vals[TX].scr = 0;
 
+   if (ssi->use_dual_fifo) {
+   vals[RX].srcr |= SSI_SRCR_RFEN1;
+   vals[TX].stcr |= SSI_STCR_TFEN1;
+   }
+
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
vals[TX].sier |= SSI_SIER_TDMAE;
@@ -991,14 +996,9 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
 SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
 
-   if (ssi->use_dual_fifo) {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  SSI_SRCR_RFEN1, SSI_SRCR_RFEN1);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  SSI_STCR_TFEN1, SSI_STCR_TFEN1);
+   if (ssi->use_dual_fifo)
regmap_update_bits(regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-   }
 
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
-- 
2.7.4



[PATCH v5 09/17] ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()

2018-01-16 Thread Nicolin Chen
This patch cleans fsl_ssi_setup_regvals() by following changes:
1) Moving DBG bits to the first lines.
2) Setting SSIE, RE/TE as default and cleaning it for AC97

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b76a517..e5efee2 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -580,18 +580,16 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
 {
struct fsl_ssi_regvals *vals = ssi->regvals;
 
-   vals[RX].sier = SSI_SIER_RFF0_EN;
+   vals[RX].sier = SSI_SIER_RFF0_EN | FSLSSI_SIER_DBG_RX_FLAGS;
vals[RX].srcr = SSI_SRCR_RFEN0;
-   vals[RX].scr = 0;
-   vals[TX].sier = SSI_SIER_TFE0_EN;
+   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
+   vals[TX].sier = SSI_SIER_TFE0_EN | FSLSSI_SIER_DBG_TX_FLAGS;
vals[TX].stcr = SSI_STCR_TFEN0;
-   vals[TX].scr = 0;
+   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
 
/* AC97 has already enabled SSIEN, RE and TE, so ignore them */
-   if (!fsl_ssi_is_ac97(ssi)) {
-   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
-   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
-   }
+   if (fsl_ssi_is_ac97(ssi))
+   vals[RX].scr = vals[TX].scr = 0;
 
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
@@ -600,9 +598,6 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
vals[RX].sier |= SSI_SIER_RIE;
vals[TX].sier |= SSI_SIER_TIE;
}
-
-   vals[RX].sier |= FSLSSI_SIER_DBG_RX_FLAGS;
-   vals[TX].sier |= FSLSSI_SIER_DBG_TX_FLAGS;
 }
 
 static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi)
-- 
2.7.4



[PATCH v5 09/17] ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()

2018-01-16 Thread Nicolin Chen
This patch cleans fsl_ssi_setup_regvals() by following changes:
1) Moving DBG bits to the first lines.
2) Setting SSIE, RE/TE as default and cleaning it for AC97

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b76a517..e5efee2 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -580,18 +580,16 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
 {
struct fsl_ssi_regvals *vals = ssi->regvals;
 
-   vals[RX].sier = SSI_SIER_RFF0_EN;
+   vals[RX].sier = SSI_SIER_RFF0_EN | FSLSSI_SIER_DBG_RX_FLAGS;
vals[RX].srcr = SSI_SRCR_RFEN0;
-   vals[RX].scr = 0;
-   vals[TX].sier = SSI_SIER_TFE0_EN;
+   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
+   vals[TX].sier = SSI_SIER_TFE0_EN | FSLSSI_SIER_DBG_TX_FLAGS;
vals[TX].stcr = SSI_STCR_TFEN0;
-   vals[TX].scr = 0;
+   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
 
/* AC97 has already enabled SSIEN, RE and TE, so ignore them */
-   if (!fsl_ssi_is_ac97(ssi)) {
-   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
-   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
-   }
+   if (fsl_ssi_is_ac97(ssi))
+   vals[RX].scr = vals[TX].scr = 0;
 
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
@@ -600,9 +598,6 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
vals[RX].sier |= SSI_SIER_RIE;
vals[TX].sier |= SSI_SIER_TIE;
}
-
-   vals[RX].sier |= FSLSSI_SIER_DBG_RX_FLAGS;
-   vals[TX].sier |= FSLSSI_SIER_DBG_TX_FLAGS;
 }
 
 static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi)
-- 
2.7.4



[PATCH v5 12/17] ASoC: fsl_ssi: Move one-time configurations to probe()

2018-01-16 Thread Nicolin Chen
The probe() could handle some one-time configurations since
they will not be changed once being configured.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v2
 * Moved all to fsl_ssi_hw_init() in platform probe()

 sound/soc/fsl/fsl_ssi.c | 39 ++-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e1fe511..50648f5 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -865,7 +865,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 {
struct regmap *regs = ssi->regs;
u32 strcr = 0, stcr, srcr, scr, mask;
-   u8 wm;
 
ssi->dai_fmt = fmt;
 
@@ -874,8 +873,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
-   fsl_ssi_setup_regvals(ssi);
-
regmap_read(regs, REG_SSI_SCR, );
scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
@@ -990,16 +987,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   wm = ssi->fifo_watermark;
-
-   regmap_write(regs, REG_SSI_SFCSR,
-SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
-SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
-
-   if (ssi->use_dual_fifo)
-   regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
 
@@ -1249,6 +1236,29 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
 };
 
 /**
+ * Initialize SSI registers
+ */
+static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
+{
+   u32 wm = ssi->fifo_watermark;
+
+   /* Initialize regvals */
+   fsl_ssi_setup_regvals(ssi);
+
+   /* Set watermarks */
+   regmap_write(ssi->regs, REG_SSI_SFCSR,
+SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
+SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
+
+   /* Enable Dual FIFO mode */
+   if (ssi->use_dual_fifo)
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
+
+   return 0;
+}
+
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1533,6 +1543,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (ssi->dai_fmt)
_fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
 
+   /* Initially configures SSI registers */
+   fsl_ssi_hw_init(ssi);
+
if (fsl_ssi_is_ac97(ssi)) {
u32 ssi_idx;
 
-- 
2.7.4



[PATCH v5 07/17] ASoC: fsl_ssi: Clean up helper functions of trigger()

2018-01-16 Thread Nicolin Chen
The trigger() calls fsl_ssi_tx_config() and fsl_ssi_rx_config(),
and both of them jump to fsl_ssi_config(). And fsl_ssi_config()
later calls another fsl_ssi_rxtx_config().

However, the whole routine, especially fsl_ssi_config() function,
is too complicated because of the folowing reasons:
1) It has to handle the concern of the opposite stream.
2) It has to handle cases of offline configurations support.
3) It has to handle enable and disable operations while they're
   mostly different.

Since the enable and disable routines have more differences than
TX and RX rountines, this patch simplifies these helper functions
with the following changes:
- Changing to two helper functions of enable and disable instead
  of TX and RX.
- Removing fsl_ssi_rxtx_config() by separately integrating it to
  two newly introduced enable & disable functions.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 256 +++-
 1 file changed, 122 insertions(+), 134 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index a2ac92f..7a6a32b 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -382,31 +382,83 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 }
 
 /**
- * Enable or disable all rx/tx config flags at once
+ * Set SCR, SIER, STCR and SRCR registers with cached values in regvals
+ *
+ * Notes:
+ * 1) For offline_config SoCs, enable all necessary bits of both streams
+ *when 1st stream starts, even if the opposite stream will not start
+ * 2) It also clears FIFO before setting regvals; SOR is safe to set online
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
+static void fsl_ssi_config_enable(struct fsl_ssi *ssi, bool tx)
 {
-   struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *vals = ssi->regvals;
+   int dir = tx ? TX : RX;
+   u32 sier, srcr, stcr;
 
-   if (enable) {
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier,
-  vals[RX].sier | vals[TX].sier);
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr,
-  vals[RX].srcr | vals[TX].srcr);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr,
-  vals[RX].stcr | vals[TX].stcr);
+   /* Clear dirty data in the FIFO; It also prevents channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
+
+   /*
+* On offline_config SoCs, SxCR and SIER are already configured when
+* the previous stream started. So skip all SxCR and SIER settings
+* to prevent online reconfigurations, then jump to set SCR directly
+*/
+   if (ssi->soc->offline_config && ssi->streams)
+   goto enable_scr;
+
+   if (ssi->soc->offline_config) {
+   /*
+* Online reconfiguration not supported, so enable all bits for
+* both streams at once to avoid necessity of reconfigurations
+*/
+   srcr = vals[RX].srcr | vals[TX].srcr;
+   stcr = vals[RX].stcr | vals[TX].stcr;
+   sier = vals[RX].sier | vals[TX].sier;
} else {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr, 0);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr, 0);
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier, 0);
+   /* Otherwise, only set bits for the current stream */
+   srcr = vals[dir].srcr;
+   stcr = vals[dir].stcr;
+   sier = vals[dir].sier;
}
+
+   /* Configure SRCR, STCR and SIER at once */
+   regmap_update_bits(ssi->regs, REG_SSI_SRCR, srcr, srcr);
+   regmap_update_bits(ssi->regs, REG_SSI_STCR, stcr, stcr);
+   regmap_update_bits(ssi->regs, REG_SSI_SIER, sier, sier);
+
+enable_scr:
+   /*
+* Start DMA before setting TE to avoid FIFO underrun
+* which may cause a channel slip or a channel swap
+*
+* TODO: FIQ cases might also need this upon testing
+*/
+   if (ssi->use_dma && tx) {
+   int try = 100;
+   u32 sfcsr;
+
+   /* Enable SSI first to send TX DMA request */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_SSIEN, SSI_SCR_SSIEN);
+
+   /* Busy wait until TX FIFO not empty -- DMA working */
+   do {
+   

[PATCH v5 12/17] ASoC: fsl_ssi: Move one-time configurations to probe()

2018-01-16 Thread Nicolin Chen
The probe() could handle some one-time configurations since
they will not be changed once being configured.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v2
 * Moved all to fsl_ssi_hw_init() in platform probe()

 sound/soc/fsl/fsl_ssi.c | 39 ++-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e1fe511..50648f5 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -865,7 +865,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 {
struct regmap *regs = ssi->regs;
u32 strcr = 0, stcr, srcr, scr, mask;
-   u8 wm;
 
ssi->dai_fmt = fmt;
 
@@ -874,8 +873,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
-   fsl_ssi_setup_regvals(ssi);
-
regmap_read(regs, REG_SSI_SCR, );
scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
@@ -990,16 +987,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   wm = ssi->fifo_watermark;
-
-   regmap_write(regs, REG_SSI_SFCSR,
-SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
-SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
-
-   if (ssi->use_dual_fifo)
-   regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
 
@@ -1249,6 +1236,29 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
 };
 
 /**
+ * Initialize SSI registers
+ */
+static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
+{
+   u32 wm = ssi->fifo_watermark;
+
+   /* Initialize regvals */
+   fsl_ssi_setup_regvals(ssi);
+
+   /* Set watermarks */
+   regmap_write(ssi->regs, REG_SSI_SFCSR,
+SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
+SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
+
+   /* Enable Dual FIFO mode */
+   if (ssi->use_dual_fifo)
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
+
+   return 0;
+}
+
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1533,6 +1543,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (ssi->dai_fmt)
_fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
 
+   /* Initially configures SSI registers */
+   fsl_ssi_hw_init(ssi);
+
if (fsl_ssi_is_ac97(ssi)) {
u32 ssi_idx;
 
-- 
2.7.4



[PATCH v5 07/17] ASoC: fsl_ssi: Clean up helper functions of trigger()

2018-01-16 Thread Nicolin Chen
The trigger() calls fsl_ssi_tx_config() and fsl_ssi_rx_config(),
and both of them jump to fsl_ssi_config(). And fsl_ssi_config()
later calls another fsl_ssi_rxtx_config().

However, the whole routine, especially fsl_ssi_config() function,
is too complicated because of the folowing reasons:
1) It has to handle the concern of the opposite stream.
2) It has to handle cases of offline configurations support.
3) It has to handle enable and disable operations while they're
   mostly different.

Since the enable and disable routines have more differences than
TX and RX rountines, this patch simplifies these helper functions
with the following changes:
- Changing to two helper functions of enable and disable instead
  of TX and RX.
- Removing fsl_ssi_rxtx_config() by separately integrating it to
  two newly introduced enable & disable functions.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 256 +++-
 1 file changed, 122 insertions(+), 134 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index a2ac92f..7a6a32b 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -382,31 +382,83 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 }
 
 /**
- * Enable or disable all rx/tx config flags at once
+ * Set SCR, SIER, STCR and SRCR registers with cached values in regvals
+ *
+ * Notes:
+ * 1) For offline_config SoCs, enable all necessary bits of both streams
+ *when 1st stream starts, even if the opposite stream will not start
+ * 2) It also clears FIFO before setting regvals; SOR is safe to set online
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
+static void fsl_ssi_config_enable(struct fsl_ssi *ssi, bool tx)
 {
-   struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *vals = ssi->regvals;
+   int dir = tx ? TX : RX;
+   u32 sier, srcr, stcr;
 
-   if (enable) {
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier,
-  vals[RX].sier | vals[TX].sier);
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr,
-  vals[RX].srcr | vals[TX].srcr);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr,
-  vals[RX].stcr | vals[TX].stcr);
+   /* Clear dirty data in the FIFO; It also prevents channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
+
+   /*
+* On offline_config SoCs, SxCR and SIER are already configured when
+* the previous stream started. So skip all SxCR and SIER settings
+* to prevent online reconfigurations, then jump to set SCR directly
+*/
+   if (ssi->soc->offline_config && ssi->streams)
+   goto enable_scr;
+
+   if (ssi->soc->offline_config) {
+   /*
+* Online reconfiguration not supported, so enable all bits for
+* both streams at once to avoid necessity of reconfigurations
+*/
+   srcr = vals[RX].srcr | vals[TX].srcr;
+   stcr = vals[RX].stcr | vals[TX].stcr;
+   sier = vals[RX].sier | vals[TX].sier;
} else {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr, 0);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr, 0);
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier, 0);
+   /* Otherwise, only set bits for the current stream */
+   srcr = vals[dir].srcr;
+   stcr = vals[dir].stcr;
+   sier = vals[dir].sier;
}
+
+   /* Configure SRCR, STCR and SIER at once */
+   regmap_update_bits(ssi->regs, REG_SSI_SRCR, srcr, srcr);
+   regmap_update_bits(ssi->regs, REG_SSI_STCR, stcr, stcr);
+   regmap_update_bits(ssi->regs, REG_SSI_SIER, sier, sier);
+
+enable_scr:
+   /*
+* Start DMA before setting TE to avoid FIFO underrun
+* which may cause a channel slip or a channel swap
+*
+* TODO: FIQ cases might also need this upon testing
+*/
+   if (ssi->use_dma && tx) {
+   int try = 100;
+   u32 sfcsr;
+
+   /* Enable SSI first to send TX DMA request */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_SSIEN, SSI_SCR_SSIEN);
+
+   /* Busy wait until TX FIFO not empty -- DMA working */
+   do {
+   regmap_read(ssi->regs, REG_SSI_SFCSR, );
+ 

[PATCH v5 13/17] ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()

2018-01-16 Thread Nicolin Chen
AC97 configures most of registers earlier to start a communication
with CODECs in order to successfully initialize CODEC. Currently,
_fsl_ssi_set_dai_fmt() and fsl_ssi_setup_ac97() are called to get
all SSI registers properly set.

Since now the driver has a fsl_ssi_hw_init() to handle all register
initial settings, this patch moves those register settings of AC97
to the fsl_ssi_hw_init() as well.

Meanwhile it applies _fsl_ssi_set_dai_fmt() call to AC97 only since
other formats would be configured via normal set_dai_fmt() directly.

This patch also adds fsl_ssi_hw_clean() to cleanup control bits for
AC97 in the platform remote() function.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v5
 * Moved fsl_ssi_hw_clean() after unregister CODEC platform dev
 * For cleanup sequence, disabled TE and RE first while SSIEN at last
v2
 * Moved all to fsl_ssi_hw_init() in platform probe()
 * Added fsl_ssi_hw_clean() instead of dai remove()

 sound/soc/fsl/fsl_ssi.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 50648f5..d577f3d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -987,9 +987,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
-   fsl_ssi_setup_ac97(ssi);
-
return 0;
 }
 
@@ -1255,10 +1252,34 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
regmap_update_bits(ssi->regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
 
+   /* AC97 should start earlier to communicate with CODECs */
+   if (fsl_ssi_is_ac97(ssi)) {
+   _fsl_ssi_set_dai_fmt(ssi->dev, ssi, ssi->dai_fmt);
+   fsl_ssi_setup_ac97(ssi);
+   }
+
return 0;
 }
 
 /**
+ * Clear SSI registers
+ */
+static void fsl_ssi_hw_clean(struct fsl_ssi *ssi)
+{
+   /* Disable registers for AC97 */
+   if (fsl_ssi_is_ac97(ssi)) {
+   /* Disable TE and RE bits first */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TE | SSI_SCR_RE, 0);
+   /* Disable AC97 mode */
+   regmap_write(ssi->regs, REG_SSI_SACNT, 0);
+   /* Unset WAIT bits */
+   regmap_write(ssi->regs, REG_SSI_SOR, 0);
+   /* Disable SSI -- software reset */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR, SSI_SCR_SSIEN, 0);
+   }
+}
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1540,9 +1561,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
}
 
 done:
-   if (ssi->dai_fmt)
-   _fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
-
/* Initially configures SSI registers */
fsl_ssi_hw_init(ssi);
 
@@ -1592,6 +1610,9 @@ static int fsl_ssi_remove(struct platform_device *pdev)
if (ssi->pdev)
platform_device_unregister(ssi->pdev);
 
+   /* Clean up SSI registers */
+   fsl_ssi_hw_clean(ssi);
+
if (ssi->soc->imx)
fsl_ssi_imx_clean(pdev, ssi);
 
-- 
2.7.4



[PATCH v5 13/17] ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()

2018-01-16 Thread Nicolin Chen
AC97 configures most of registers earlier to start a communication
with CODECs in order to successfully initialize CODEC. Currently,
_fsl_ssi_set_dai_fmt() and fsl_ssi_setup_ac97() are called to get
all SSI registers properly set.

Since now the driver has a fsl_ssi_hw_init() to handle all register
initial settings, this patch moves those register settings of AC97
to the fsl_ssi_hw_init() as well.

Meanwhile it applies _fsl_ssi_set_dai_fmt() call to AC97 only since
other formats would be configured via normal set_dai_fmt() directly.

This patch also adds fsl_ssi_hw_clean() to cleanup control bits for
AC97 in the platform remote() function.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v5
 * Moved fsl_ssi_hw_clean() after unregister CODEC platform dev
 * For cleanup sequence, disabled TE and RE first while SSIEN at last
v2
 * Moved all to fsl_ssi_hw_init() in platform probe()
 * Added fsl_ssi_hw_clean() instead of dai remove()

 sound/soc/fsl/fsl_ssi.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 50648f5..d577f3d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -987,9 +987,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
-   fsl_ssi_setup_ac97(ssi);
-
return 0;
 }
 
@@ -1255,10 +1252,34 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
regmap_update_bits(ssi->regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
 
+   /* AC97 should start earlier to communicate with CODECs */
+   if (fsl_ssi_is_ac97(ssi)) {
+   _fsl_ssi_set_dai_fmt(ssi->dev, ssi, ssi->dai_fmt);
+   fsl_ssi_setup_ac97(ssi);
+   }
+
return 0;
 }
 
 /**
+ * Clear SSI registers
+ */
+static void fsl_ssi_hw_clean(struct fsl_ssi *ssi)
+{
+   /* Disable registers for AC97 */
+   if (fsl_ssi_is_ac97(ssi)) {
+   /* Disable TE and RE bits first */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TE | SSI_SCR_RE, 0);
+   /* Disable AC97 mode */
+   regmap_write(ssi->regs, REG_SSI_SACNT, 0);
+   /* Unset WAIT bits */
+   regmap_write(ssi->regs, REG_SSI_SOR, 0);
+   /* Disable SSI -- software reset */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR, SSI_SCR_SSIEN, 0);
+   }
+}
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1540,9 +1561,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
}
 
 done:
-   if (ssi->dai_fmt)
-   _fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
-
/* Initially configures SSI registers */
fsl_ssi_hw_init(ssi);
 
@@ -1592,6 +1610,9 @@ static int fsl_ssi_remove(struct platform_device *pdev)
if (ssi->pdev)
platform_device_unregister(ssi->pdev);
 
+   /* Clean up SSI registers */
+   fsl_ssi_hw_clean(ssi);
+
if (ssi->soc->imx)
fsl_ssi_imx_clean(pdev, ssi);
 
-- 
2.7.4



[PATCH v5 17/17] ASoC: fsl_ssi: Use ssi->streams instead of reading register

2018-01-16 Thread Nicolin Chen
Since ssi->streams is being updated along with SCR register and
its SSIEN bit, it's simpler to use it instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index a8a040d..c6c1b07 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -803,11 +803,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
unsigned int sample_size = params_width(hw_params);
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
-   u32 scr;
-   int enabled;
-
-   regmap_read(regs, REG_SSI_SCR, );
-   enabled = scr & SSI_SCR_SSIEN;
 
/*
 * SSI is properly configured if it is enabled and running in
@@ -815,7 +810,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->synchronous)
+   if (ssi->streams && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-- 
2.7.4



[PATCH v5 17/17] ASoC: fsl_ssi: Use ssi->streams instead of reading register

2018-01-16 Thread Nicolin Chen
Since ssi->streams is being updated along with SCR register and
its SSIEN bit, it's simpler to use it instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index a8a040d..c6c1b07 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -803,11 +803,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
unsigned int sample_size = params_width(hw_params);
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
-   u32 scr;
-   int enabled;
-
-   regmap_read(regs, REG_SSI_SCR, );
-   enabled = scr & SSI_SCR_SSIEN;
 
/*
 * SSI is properly configured if it is enabled and running in
@@ -815,7 +810,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->synchronous)
+   if (ssi->streams && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-- 
2.7.4



[PATCH v5 14/17] ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()

2018-01-16 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() is a helper function being called from
fsl_ssi_set_dai_fmt() as an ASoC operation and fsl_ssi_hw_init()
mainly for AC97 format initialization.

This patch cleans the _fsl_ssi_set_dai_fmt() in following ways:
* Removing *dev pointer in the parameters as it's included in the
  *ssi pointer of struct fsl_ssi.
* Using regmap_update_bits() instead of regmap_read() with masking
  the value manually.
* Moving baudclk check to the switch-case routine to skip the I2S
  master check. And moving SxCCR.DC settings after baudclk check.
* Adding format settings for SND_SOC_DAIFMT_AC97 like others.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v4
 * Added TXBIT0 bit back to play safe
v3
 * Put CBM_CFS behind the baudclk check to keep the same program
   flow as before

 sound/soc/fsl/fsl_ssi.c | 74 +++--
 1 file changed, 35 insertions(+), 39 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index d577f3d..f29f3b0 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -860,42 +860,31 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream 
*substream,
return 0;
 }
 
-static int _fsl_ssi_set_dai_fmt(struct device *dev,
-   struct fsl_ssi *ssi, unsigned int fmt)
+static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
 {
-   struct regmap *regs = ssi->regs;
-   u32 strcr = 0, stcr, srcr, scr, mask;
+   u32 strcr = 0, scr = 0, stcr, srcr, mask;
 
ssi->dai_fmt = fmt;
 
-   if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "missing baudclk for master mode\n");
-   return -EINVAL;
-   }
-
-   regmap_read(regs, REG_SSI_SCR, );
-   scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
scr |= SSI_SCR_SYNC_TX_FS;
 
-   mask = SSI_STCR_TXBIT0 | SSI_STCR_TFDIR | SSI_STCR_TXDIR |
-  SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TFSL | SSI_STCR_TEFS;
-   regmap_read(regs, REG_SSI_STCR, );
-   regmap_read(regs, REG_SSI_SRCR, );
-   stcr &= ~mask;
-   srcr &= ~mask;
+   /* Set to default shifting settings: LSB_ALIGNED */
+   strcr |= SSI_STCR_TXBIT0;
 
/* Use Network mode as default */
ssi->i2s_net = SSI_SCR_NET;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
-   regmap_update_bits(regs, REG_SSI_STCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
-   regmap_update_bits(regs, REG_SSI_SRCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-   case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
+   if (IS_ERR(ssi->baudclk)) {
+   dev_err(ssi->dev,
+   "missing baudclk for master mode\n");
+   return -EINVAL;
+   }
+   /* fall through */
+   case SND_SOC_DAIFMT_CBM_CFS:
ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -905,30 +894,34 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
+   regmap_update_bits(ssi->regs, REG_SSI_STCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+   regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+
/* Data on rising edge of bclk, frame low, 1clk before data */
-   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_LEFT_J:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP;
+   strcr |= SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_DSP_A:
/* Data on rising edge of bclk, frame high, 1clk before data */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_DSP_B:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TXBIT0;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of 

[PATCH v5 16/17] ASoC: fsl_ssi: Move DT related code to a separate probe()

2018-01-16 Thread Nicolin Chen
This patch cleans up probe() function by moving all Device Tree
related code into a separate function. It allows the probe() to
be Device Tree independent. This will be very useful for future
integration of imx-ssi driver which has similar functionalities
while exists only because it supports non-DT cases.

This patch also moves symmetric_channels of AC97 from the probe
to the structure snd_soc_dai_driver for simplification.

Additionally, since PowerPC and AC97 use the same pdev pointer
to register a platform device, this patch also unifies related
code.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v5
 * Uses NULL as the parent device as CODEC platform device with
   comments for the reason
 * Updated comments of three pointers for the platform_device
v4
 * Made bool synchronous exclusive with AC97 mode in PATCH-16

 sound/soc/fsl/fsl_ssi.c | 219 +++-
 1 file changed, 124 insertions(+), 95 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7ce055c..a8a040d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -239,8 +239,12 @@ struct fsl_ssi_soc_data {
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
- *TODO: Should be replaced with simple-sound-card
+ * @card_pdev: Platform_device pointer to register a sound card for PowerPC or
+ * to register a CODEC platform device for AC97
+ * @card_name: Platform_device name to register a sound card for PowerPC or
+ * to register a CODEC platform device for AC97
+ * @card_idx: The index of SSI to register a sound card for PowerPC or
+ *to register a CODEC platform device for AC97
  *
  * @dbg_stats: Debugging statistics
  *
@@ -285,7 +289,9 @@ struct fsl_ssi {
 
struct imx_pcm_fiq_params fiq_params;
 
-   struct platform_device *pdev;
+   struct platform_device *card_pdev;
+   char card_name[32];
+   u32 card_idx;
 
struct fsl_ssi_dbg dbg_stats;
 
@@ -1134,6 +1140,7 @@ static const struct snd_soc_component_driver 
fsl_ssi_component = {
 
 static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
.bus_control = true,
+   .symmetric_channels = 1,
.probe = fsl_ssi_dai_probe,
.playback = {
.stream_name = "AC97 Playback",
@@ -1291,9 +1298,7 @@ static void make_lowercase(char *s)
 static int fsl_ssi_imx_probe(struct platform_device *pdev,
 struct fsl_ssi *ssi, void __iomem *iomem)
 {
-   struct device_node *np = pdev->dev.of_node;
struct device *dev = >dev;
-   u32 dmas[4];
int ret;
 
/* Backward compatible for a DT without ipg clock name assigned */
@@ -1327,14 +1332,8 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0;
 
-   /* Set to dual FIFO mode according to the SDMA sciprt */
-   ret = of_property_read_u32_array(np, "dmas", dmas, 4);
-   if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
-   ssi->use_dual_fifo = true;
-   /*
-* Use even numbers to avoid channel swap due to SDMA
-* script design
-*/
+   /* Use even numbers to avoid channel swap due to SDMA script design */
+   if (ssi->use_dual_fifo) {
ssi->dma_params_tx.maxburst &= ~0x1;
ssi->dma_params_rx.maxburst &= ~0x1;
}
@@ -1375,41 +1374,109 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
clk_disable_unprepare(ssi->clk);
 }
 
-static int fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
 {
-   struct fsl_ssi *ssi;
-   int ret = 0;
-   struct device_node *np = pdev->dev.of_node;
-   struct device *dev = >dev;
+   struct device *dev = ssi->dev;
+   struct device_node *np = dev->of_node;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
-   struct resource *res;
-   void __iomem *iomem;
-   char name[64];
-   struct regmap_config regconfig = fsl_ssi_regconfig;
+   u32 dmas[4];
+   int ret;
 
of_id = of_match_device(fsl_ssi_ids, dev);
if (!of_id || !of_id->data)
return -EINVAL;
 
-   ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
-   if (!ssi)
-   return -ENOMEM;
-
ssi->soc = of_id->data;
-   ssi->dev = dev;
+
+   ret = of_property_match_string(np, "clock-names", "ipg");
+   /* Get error code if not found */
+   ssi->has_ipg_clk_name = ret >= 0;
 
/* Check if being used in AC97 mode */
sprop = of_get_property(np, "fsl,mode", NULL);
-  

[PATCH v5 16/17] ASoC: fsl_ssi: Move DT related code to a separate probe()

2018-01-16 Thread Nicolin Chen
This patch cleans up probe() function by moving all Device Tree
related code into a separate function. It allows the probe() to
be Device Tree independent. This will be very useful for future
integration of imx-ssi driver which has similar functionalities
while exists only because it supports non-DT cases.

This patch also moves symmetric_channels of AC97 from the probe
to the structure snd_soc_dai_driver for simplification.

Additionally, since PowerPC and AC97 use the same pdev pointer
to register a platform device, this patch also unifies related
code.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v5
 * Uses NULL as the parent device as CODEC platform device with
   comments for the reason
 * Updated comments of three pointers for the platform_device
v4
 * Made bool synchronous exclusive with AC97 mode in PATCH-16

 sound/soc/fsl/fsl_ssi.c | 219 +++-
 1 file changed, 124 insertions(+), 95 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 7ce055c..a8a040d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -239,8 +239,12 @@ struct fsl_ssi_soc_data {
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
- *TODO: Should be replaced with simple-sound-card
+ * @card_pdev: Platform_device pointer to register a sound card for PowerPC or
+ * to register a CODEC platform device for AC97
+ * @card_name: Platform_device name to register a sound card for PowerPC or
+ * to register a CODEC platform device for AC97
+ * @card_idx: The index of SSI to register a sound card for PowerPC or
+ *to register a CODEC platform device for AC97
  *
  * @dbg_stats: Debugging statistics
  *
@@ -285,7 +289,9 @@ struct fsl_ssi {
 
struct imx_pcm_fiq_params fiq_params;
 
-   struct platform_device *pdev;
+   struct platform_device *card_pdev;
+   char card_name[32];
+   u32 card_idx;
 
struct fsl_ssi_dbg dbg_stats;
 
@@ -1134,6 +1140,7 @@ static const struct snd_soc_component_driver 
fsl_ssi_component = {
 
 static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
.bus_control = true,
+   .symmetric_channels = 1,
.probe = fsl_ssi_dai_probe,
.playback = {
.stream_name = "AC97 Playback",
@@ -1291,9 +1298,7 @@ static void make_lowercase(char *s)
 static int fsl_ssi_imx_probe(struct platform_device *pdev,
 struct fsl_ssi *ssi, void __iomem *iomem)
 {
-   struct device_node *np = pdev->dev.of_node;
struct device *dev = >dev;
-   u32 dmas[4];
int ret;
 
/* Backward compatible for a DT without ipg clock name assigned */
@@ -1327,14 +1332,8 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0;
 
-   /* Set to dual FIFO mode according to the SDMA sciprt */
-   ret = of_property_read_u32_array(np, "dmas", dmas, 4);
-   if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
-   ssi->use_dual_fifo = true;
-   /*
-* Use even numbers to avoid channel swap due to SDMA
-* script design
-*/
+   /* Use even numbers to avoid channel swap due to SDMA script design */
+   if (ssi->use_dual_fifo) {
ssi->dma_params_tx.maxburst &= ~0x1;
ssi->dma_params_rx.maxburst &= ~0x1;
}
@@ -1375,41 +1374,109 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
clk_disable_unprepare(ssi->clk);
 }
 
-static int fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
 {
-   struct fsl_ssi *ssi;
-   int ret = 0;
-   struct device_node *np = pdev->dev.of_node;
-   struct device *dev = >dev;
+   struct device *dev = ssi->dev;
+   struct device_node *np = dev->of_node;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
-   struct resource *res;
-   void __iomem *iomem;
-   char name[64];
-   struct regmap_config regconfig = fsl_ssi_regconfig;
+   u32 dmas[4];
+   int ret;
 
of_id = of_match_device(fsl_ssi_ids, dev);
if (!of_id || !of_id->data)
return -EINVAL;
 
-   ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
-   if (!ssi)
-   return -ENOMEM;
-
ssi->soc = of_id->data;
-   ssi->dev = dev;
+
+   ret = of_property_match_string(np, "clock-names", "ipg");
+   /* Get error code if not found */
+   ssi->has_ipg_clk_name = ret >= 0;
 
/* Check if being used in AC97 mode */
sprop = of_get_property(np, "fsl,mode", NULL);
-   if (sprop) {
-   if 

[PATCH v5 14/17] ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()

2018-01-16 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() is a helper function being called from
fsl_ssi_set_dai_fmt() as an ASoC operation and fsl_ssi_hw_init()
mainly for AC97 format initialization.

This patch cleans the _fsl_ssi_set_dai_fmt() in following ways:
* Removing *dev pointer in the parameters as it's included in the
  *ssi pointer of struct fsl_ssi.
* Using regmap_update_bits() instead of regmap_read() with masking
  the value manually.
* Moving baudclk check to the switch-case routine to skip the I2S
  master check. And moving SxCCR.DC settings after baudclk check.
* Adding format settings for SND_SOC_DAIFMT_AC97 like others.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v4
 * Added TXBIT0 bit back to play safe
v3
 * Put CBM_CFS behind the baudclk check to keep the same program
   flow as before

 sound/soc/fsl/fsl_ssi.c | 74 +++--
 1 file changed, 35 insertions(+), 39 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index d577f3d..f29f3b0 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -860,42 +860,31 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream 
*substream,
return 0;
 }
 
-static int _fsl_ssi_set_dai_fmt(struct device *dev,
-   struct fsl_ssi *ssi, unsigned int fmt)
+static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
 {
-   struct regmap *regs = ssi->regs;
-   u32 strcr = 0, stcr, srcr, scr, mask;
+   u32 strcr = 0, scr = 0, stcr, srcr, mask;
 
ssi->dai_fmt = fmt;
 
-   if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "missing baudclk for master mode\n");
-   return -EINVAL;
-   }
-
-   regmap_read(regs, REG_SSI_SCR, );
-   scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
scr |= SSI_SCR_SYNC_TX_FS;
 
-   mask = SSI_STCR_TXBIT0 | SSI_STCR_TFDIR | SSI_STCR_TXDIR |
-  SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TFSL | SSI_STCR_TEFS;
-   regmap_read(regs, REG_SSI_STCR, );
-   regmap_read(regs, REG_SSI_SRCR, );
-   stcr &= ~mask;
-   srcr &= ~mask;
+   /* Set to default shifting settings: LSB_ALIGNED */
+   strcr |= SSI_STCR_TXBIT0;
 
/* Use Network mode as default */
ssi->i2s_net = SSI_SCR_NET;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
-   regmap_update_bits(regs, REG_SSI_STCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
-   regmap_update_bits(regs, REG_SSI_SRCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-   case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
+   if (IS_ERR(ssi->baudclk)) {
+   dev_err(ssi->dev,
+   "missing baudclk for master mode\n");
+   return -EINVAL;
+   }
+   /* fall through */
+   case SND_SOC_DAIFMT_CBM_CFS:
ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -905,30 +894,34 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
+   regmap_update_bits(ssi->regs, REG_SSI_STCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+   regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+
/* Data on rising edge of bclk, frame low, 1clk before data */
-   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_LEFT_J:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP;
+   strcr |= SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_DSP_A:
/* Data on rising edge of bclk, frame high, 1clk before data */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_DSP_B:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TXBIT0;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of bclk, frame high, 1clk before data */
-   

[PATCH v5 11/17] ASoC: fsl_ssi: Use snd_soc_init_dma_data instead

2018-01-16 Thread Nicolin Chen
Since there is a helper function, use it to help readability.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index ba06e94..e1fe511 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1110,10 +1110,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
-   if (ssi->soc->imx && ssi->use_dma) {
-   dai->playback_dma_data = >dma_params_tx;
-   dai->capture_dma_data = >dma_params_rx;
-   }
+   if (ssi->soc->imx && ssi->use_dma)
+   snd_soc_dai_init_dma_data(dai, >dma_params_tx,
+ >dma_params_rx);
 
return 0;
 }
-- 
2.7.4



[PATCH v5 11/17] ASoC: fsl_ssi: Use snd_soc_init_dma_data instead

2018-01-16 Thread Nicolin Chen
Since there is a helper function, use it to help readability.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index ba06e94..e1fe511 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1110,10 +1110,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
-   if (ssi->soc->imx && ssi->use_dma) {
-   dai->playback_dma_data = >dma_params_tx;
-   dai->capture_dma_data = >dma_params_rx;
-   }
+   if (ssi->soc->imx && ssi->use_dma)
+   snd_soc_dai_init_dma_data(dai, >dma_params_tx,
+ >dma_params_rx);
 
return 0;
 }
-- 
2.7.4



[PATCH v5 15/17] ASoC: fsl_ssi: Add bool synchronous to mark synchronous mode

2018-01-16 Thread Nicolin Chen
Using symmetric_rates in the cpu_dai_drv is a bit implicit,
so this patch adds a bool synchronous instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Removed all cpu_dai_drv changes

 sound/soc/fsl/fsl_ssi.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index f29f3b0..7ce055c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -217,6 +217,7 @@ struct fsl_ssi_soc_data {
  * @dai_fmt: DAI configuration this device is currently used with
  * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
+ * @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
  * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
@@ -262,6 +263,7 @@ struct fsl_ssi {
unsigned int dai_fmt;
u8 streams;
u8 i2s_net;
+   bool synchronous;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -673,7 +675,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
-   int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
unsigned int slots = params_channels(hw_params);
@@ -681,6 +682,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
u64 sub, savesub = 10;
unsigned int freq;
bool baudclk_is_used;
+   int ret;
 
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
@@ -759,7 +761,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
/* STCCR is used for RX in synchronous mode */
-   tx2 = tx || synchronous;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
@@ -807,7 +809,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->cpu_dai_drv.symmetric_rates)
+   if (enabled && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
@@ -839,7 +841,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
@@ -968,7 +970,7 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, 
unsigned int fmt)
srcr = strcr;
 
/* Set SYN mode and clear RXDIR bit when using SYN or AC97 mode */
-   if (ssi->cpu_dai_drv.symmetric_rates || fsl_ssi_is_ac97(ssi)) {
+   if (ssi->synchronous || fsl_ssi_is_ac97(ssi)) {
srcr &= ~SSI_SRCR_RXDIR;
scr |= SSI_SCR_SYN;
}
@@ -1456,6 +1458,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (!fsl_ssi_is_ac97(ssi)) {
ssi->cpu_dai_drv.symmetric_rates = 1;
ssi->cpu_dai_drv.symmetric_samplebits = 1;
+   ssi->synchronous = true;
}
 
ssi->cpu_dai_drv.symmetric_channels = 1;
-- 
2.7.4



[PATCH v5 15/17] ASoC: fsl_ssi: Add bool synchronous to mark synchronous mode

2018-01-16 Thread Nicolin Chen
Using symmetric_rates in the cpu_dai_drv is a bit implicit,
so this patch adds a bool synchronous instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
Changelog
v3
 * Removed all cpu_dai_drv changes

 sound/soc/fsl/fsl_ssi.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index f29f3b0..7ce055c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -217,6 +217,7 @@ struct fsl_ssi_soc_data {
  * @dai_fmt: DAI configuration this device is currently used with
  * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
+ * @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
  * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
@@ -262,6 +263,7 @@ struct fsl_ssi {
unsigned int dai_fmt;
u8 streams;
u8 i2s_net;
+   bool synchronous;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -673,7 +675,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
-   int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
unsigned int slots = params_channels(hw_params);
@@ -681,6 +682,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
u64 sub, savesub = 10;
unsigned int freq;
bool baudclk_is_used;
+   int ret;
 
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
@@ -759,7 +761,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
/* STCCR is used for RX in synchronous mode */
-   tx2 = tx || synchronous;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
@@ -807,7 +809,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->cpu_dai_drv.symmetric_rates)
+   if (enabled && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
@@ -839,7 +841,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
@@ -968,7 +970,7 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, 
unsigned int fmt)
srcr = strcr;
 
/* Set SYN mode and clear RXDIR bit when using SYN or AC97 mode */
-   if (ssi->cpu_dai_drv.symmetric_rates || fsl_ssi_is_ac97(ssi)) {
+   if (ssi->synchronous || fsl_ssi_is_ac97(ssi)) {
srcr &= ~SSI_SRCR_RXDIR;
scr |= SSI_SCR_SYN;
}
@@ -1456,6 +1458,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (!fsl_ssi_is_ac97(ssi)) {
ssi->cpu_dai_drv.symmetric_rates = 1;
ssi->cpu_dai_drv.symmetric_samplebits = 1;
+   ssi->synchronous = true;
}
 
ssi->cpu_dai_drv.symmetric_channels = 1;
-- 
2.7.4



[PATCH v5 00/17] ASoC: fsl_ssi: Clean up - program flow level

2018-01-16 Thread Nicolin Chen
[ Maciej, could you please send your Tested-by/Reviewed-by for AC97
  once you confirm this series?
  
  And Caleb, this version does not need a test for non-AC97 cases.

  Thanks both! ]

==Change log==
v5
 * Reworked the series by taking suggestions from Maciej for AC97
  + Fixed SSI lockup issue by changing cleanup sequence in PATCH-13
  + Moved fsl_ssi_hw_clean() after unregistering the CODEC device
in PATCH-13
  + Set NULL as the parent of CODEC platform device to fix a NULL
pointer dereference bug in PATCH-16
 * Updated comments of three variables/pointers in struct fsl_ssi
   to describe them more accurately in PATCH-16
v4
 * Reworked the series by taking suggestions from Maciej
  + Added TXBIT0 bit back to play safe in PATCH-14
  + Made bool synchronous exclusive with AC97 mode in PATCH-16
v3
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to make RX and TX more clearly defined
  + Replaced "bool dir" with "int dir" in PATCH-04
  + Replaced "!dir" with "int adir" in PATCH-05
  + Put CBM_CFS behind the baudclk check to keep the same
program flow in PATCH-14
  + Removed all cpu_dai_drv changes in PATCH-15
v2
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to keep all ssi->i2s_net updated
  + Replaced bool tx with bool dir in PATCH-03 and PATCH-06
  + Moved all initial register configurations from dai probe() to
platform probe() so as to let AC97 CODEC successfully probe.
 * Added Tested-by from Caleb for TDM test cases.

==Background==
The fsl_ssi driver was designed for PPC originally and then it has
been updated to support different modes for i.MX Series, including
SDMA, I2S Master mode, AC97 and older i.MXs with FIQ, by different
contributors for different use cases in different coding styles.

Additionally, in order to fix/work-around hardware bugs and design
flaws, the driver made a lot of compromise so now its program flow
looks very complicated and it's getting hard to maintain or update.

So I am going to clean up the driver on both coding style level and
program flow level.

==Introduction==
This series of patches is the second set to clean up fsl_ssi driver
in the program flow level. Any patch here may impact a fundamental
test case like playback or record.

==Verification==
This series of patches require fully tested. I have done such tests
on i.MX6SoloX with WM8962 using imx_v6_v7_defconfig as:
 - Playback via I2S Master and Slave mode
 - Record via I2S Master and Slave mode
 - Simultaneous playback and record via I2S Master and Slave mode
 - Background playback with foreground record (starting at different
   time) via I2S Master and Slave mode
 - Background record with foreground playback (starting at different
   time) via I2S Master and Slave mode
 * All tests above by hacking offline_config to true in imx51.

Caleb has tested v1-v4 with TDM lookback tests on i.MX6.

Example of uncovered tests: AC97, PowerPC and FIQ.

Nicolin Chen (17):
  ASoC: fsl_ssi: Redefine RX and TX macros
  ASoC: fsl_ssi: Keep ssi->i2s_net updated
  ASoC: fsl_ssi: Clean up set_dai_tdm_slot()
  ASoC: fsl_ssi: Maintain a mask of active streams
  ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro
  ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()
  ASoC: fsl_ssi: Clean up helper functions of trigger()
  ASoC: fsl_ssi: Add DAIFMT define for AC97
  ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()
  ASoC: fsl_ssi: Set xFEN0 and xFEN1 together
  ASoC: fsl_ssi: Use snd_soc_init_dma_data instead
  ASoC: fsl_ssi: Move one-time configurations to probe()
  ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()
  ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()
  ASoC: fsl_ssi: Add bool synchronous to mark synchronous mode
  ASoC: fsl_ssi: Move DT related code to a separate probe()
  ASoC: fsl_ssi: Use ssi->streams instead of reading register

 sound/soc/fsl/fsl_ssi.c | 756 +---
 sound/soc/fsl/fsl_ssi.h |   3 -
 2 files changed, 395 insertions(+), 364 deletions(-)

-- 
2.7.4



[PATCH v5 00/17] ASoC: fsl_ssi: Clean up - program flow level

2018-01-16 Thread Nicolin Chen
[ Maciej, could you please send your Tested-by/Reviewed-by for AC97
  once you confirm this series?
  
  And Caleb, this version does not need a test for non-AC97 cases.

  Thanks both! ]

==Change log==
v5
 * Reworked the series by taking suggestions from Maciej for AC97
  + Fixed SSI lockup issue by changing cleanup sequence in PATCH-13
  + Moved fsl_ssi_hw_clean() after unregistering the CODEC device
in PATCH-13
  + Set NULL as the parent of CODEC platform device to fix a NULL
pointer dereference bug in PATCH-16
 * Updated comments of three variables/pointers in struct fsl_ssi
   to describe them more accurately in PATCH-16
v4
 * Reworked the series by taking suggestions from Maciej
  + Added TXBIT0 bit back to play safe in PATCH-14
  + Made bool synchronous exclusive with AC97 mode in PATCH-16
v3
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to make RX and TX more clearly defined
  + Replaced "bool dir" with "int dir" in PATCH-04
  + Replaced "!dir" with "int adir" in PATCH-05
  + Put CBM_CFS behind the baudclk check to keep the same
program flow in PATCH-14
  + Removed all cpu_dai_drv changes in PATCH-15
v2
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to keep all ssi->i2s_net updated
  + Replaced bool tx with bool dir in PATCH-03 and PATCH-06
  + Moved all initial register configurations from dai probe() to
platform probe() so as to let AC97 CODEC successfully probe.
 * Added Tested-by from Caleb for TDM test cases.

==Background==
The fsl_ssi driver was designed for PPC originally and then it has
been updated to support different modes for i.MX Series, including
SDMA, I2S Master mode, AC97 and older i.MXs with FIQ, by different
contributors for different use cases in different coding styles.

Additionally, in order to fix/work-around hardware bugs and design
flaws, the driver made a lot of compromise so now its program flow
looks very complicated and it's getting hard to maintain or update.

So I am going to clean up the driver on both coding style level and
program flow level.

==Introduction==
This series of patches is the second set to clean up fsl_ssi driver
in the program flow level. Any patch here may impact a fundamental
test case like playback or record.

==Verification==
This series of patches require fully tested. I have done such tests
on i.MX6SoloX with WM8962 using imx_v6_v7_defconfig as:
 - Playback via I2S Master and Slave mode
 - Record via I2S Master and Slave mode
 - Simultaneous playback and record via I2S Master and Slave mode
 - Background playback with foreground record (starting at different
   time) via I2S Master and Slave mode
 - Background record with foreground playback (starting at different
   time) via I2S Master and Slave mode
 * All tests above by hacking offline_config to true in imx51.

Caleb has tested v1-v4 with TDM lookback tests on i.MX6.

Example of uncovered tests: AC97, PowerPC and FIQ.

Nicolin Chen (17):
  ASoC: fsl_ssi: Redefine RX and TX macros
  ASoC: fsl_ssi: Keep ssi->i2s_net updated
  ASoC: fsl_ssi: Clean up set_dai_tdm_slot()
  ASoC: fsl_ssi: Maintain a mask of active streams
  ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro
  ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()
  ASoC: fsl_ssi: Clean up helper functions of trigger()
  ASoC: fsl_ssi: Add DAIFMT define for AC97
  ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()
  ASoC: fsl_ssi: Set xFEN0 and xFEN1 together
  ASoC: fsl_ssi: Use snd_soc_init_dma_data instead
  ASoC: fsl_ssi: Move one-time configurations to probe()
  ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()
  ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()
  ASoC: fsl_ssi: Add bool synchronous to mark synchronous mode
  ASoC: fsl_ssi: Move DT related code to a separate probe()
  ASoC: fsl_ssi: Use ssi->streams instead of reading register

 sound/soc/fsl/fsl_ssi.c | 756 +---
 sound/soc/fsl/fsl_ssi.h |   3 -
 2 files changed, 395 insertions(+), 364 deletions(-)

-- 
2.7.4



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

2018-01-16 Thread 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 
Cc: Palmer Dabbelt 
Cc: Ralf Baechle 
Cc: linux-m...@linux-mips.org
Cc: linux-kernel@vger.kernel.org
---
 arch/mips/Kconfig   |  5 +
 arch/mips/lib/Makefile  |  2 +-
 arch/mips/lib/ashldi3.c | 30 --
 arch/mips/lib/ashrdi3.c | 32 
 arch/mips/lib/cmpdi2.c  | 28 
 arch/mips/lib/lshrdi3.c | 30 --
 arch/mips/lib/ucmpdi2.c | 22 --
 7 files changed, 6 insertions(+), 143 deletions(-)
 delete mode 100644 arch/mips/lib/ashldi3.c
 delete mode 100644 arch/mips/lib/ashrdi3.c
 delete mode 100644 arch/mips/lib/cmpdi2.c
 delete mode 100644 arch/mips/lib/lshrdi3.c
 delete mode 100644 arch/mips/lib/ucmpdi2.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 350a990fc719..9cd49ee848c6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -73,6 +73,11 @@ config MIPS
select RTC_LIB if !MACH_LOONGSON64
select SYSCTL_EXCEPTION_TRACE
select VIRT_TO_BUS
+   select GENERIC_ASHLDI3
+   select GENERIC_ASHRDI3
+   select GENERIC_LSHRDI3
+   select GENERIC_CMPDI2
+   select GENERIC_UCMPDI2
 
 menu "Machine selection"
 
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 78c2affeabf8..195ab4cb0840 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -16,4 +16,4 @@ obj-$(CONFIG_CPU_R3000)   += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)   += r3k_dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += bswapsi.o bswapdi.o
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
deleted file mode 100644
index 24cd6903e797..
--- a/arch/mips/lib/ashldi3.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-long long notrace __ashldi3(long long u, word_type b)
-{
-   DWunion uu, w;
-   word_type bm;
-
-   if (b == 0)
-   return u;
-
-   uu.ll = u;
-   bm = 32 - b;
-
-   if (bm <= 0) {
-   w.s.low = 0;
-   w.s.high = (unsigned int) uu.s.low << -bm;
-   } else {
-   const unsigned int carries = (unsigned int) uu.s.low >> bm;
-
-   w.s.low = (unsigned int) uu.s.low << b;
-   w.s.high = ((unsigned int) uu.s.high << b) | carries;
-   }
-
-   return w.ll;
-}
-
-EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
deleted file mode 100644
index 23f5295af51e..
--- a/arch/mips/lib/ashrdi3.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-long long notrace __ashrdi3(long long u, word_type b)
-{
-   DWunion uu, w;
-   word_type bm;
-
-   if (b == 0)
-   return u;
-
-   uu.ll = u;
-   bm = 32 - b;
-
-   if (bm <= 0) {
-   /* w.s.high = 1..1 or 0..0 */
-   w.s.high =
-   uu.s.high >> 31;
-   w.s.low = uu.s.high >> -bm;
-   } else {
-   const unsigned int carries = (unsigned int) uu.s.high << bm;
-
-   w.s.high = uu.s.high >> b;
-   w.s.low = ((unsigned int) uu.s.low >> b) | carries;
-   }
-
-   return w.ll;
-}
-
-EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/mips/lib/cmpdi2.c b/arch/mips/lib/cmpdi2.c
deleted file mode 100644
index 93cfc785927d..
--- a/arch/mips/lib/cmpdi2.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-word_type notrace __cmpdi2(long long a, long long b)
-{
-   const DWunion au = {
-   .ll = a
-   };
-   const DWunion bu = {
-   .ll = b
-   };
-
-   if (au.s.high < bu.s.high)
-   return 0;
-   else if (au.s.high > bu.s.high)
-   return 2;
-
-   if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
-   return 0;
-   else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
-   return 2;
-
-   return 1;
-}
-
-EXPORT_SYMBOL(__cmpdi2);
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
deleted file mode 100644
index 914b971aca3b..
--- a/arch/mips/lib/lshrdi3.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-long long notrace __lshrdi3(long long u, word_type b)
-{
-   DWunion uu, w;
-   word_type bm;
-
-   if (b == 0)
-   return u;
-
-   uu.ll = u;
-

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

2018-01-16 Thread 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 
Cc: Palmer Dabbelt 
Cc: Ralf Baechle 
Cc: linux-m...@linux-mips.org
Cc: linux-kernel@vger.kernel.org
---
 arch/mips/Kconfig   |  5 +
 arch/mips/lib/Makefile  |  2 +-
 arch/mips/lib/ashldi3.c | 30 --
 arch/mips/lib/ashrdi3.c | 32 
 arch/mips/lib/cmpdi2.c  | 28 
 arch/mips/lib/lshrdi3.c | 30 --
 arch/mips/lib/ucmpdi2.c | 22 --
 7 files changed, 6 insertions(+), 143 deletions(-)
 delete mode 100644 arch/mips/lib/ashldi3.c
 delete mode 100644 arch/mips/lib/ashrdi3.c
 delete mode 100644 arch/mips/lib/cmpdi2.c
 delete mode 100644 arch/mips/lib/lshrdi3.c
 delete mode 100644 arch/mips/lib/ucmpdi2.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 350a990fc719..9cd49ee848c6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -73,6 +73,11 @@ config MIPS
select RTC_LIB if !MACH_LOONGSON64
select SYSCTL_EXCEPTION_TRACE
select VIRT_TO_BUS
+   select GENERIC_ASHLDI3
+   select GENERIC_ASHRDI3
+   select GENERIC_LSHRDI3
+   select GENERIC_CMPDI2
+   select GENERIC_UCMPDI2
 
 menu "Machine selection"
 
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 78c2affeabf8..195ab4cb0840 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -16,4 +16,4 @@ obj-$(CONFIG_CPU_R3000)   += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)   += r3k_dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += bswapsi.o bswapdi.o
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
deleted file mode 100644
index 24cd6903e797..
--- a/arch/mips/lib/ashldi3.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-long long notrace __ashldi3(long long u, word_type b)
-{
-   DWunion uu, w;
-   word_type bm;
-
-   if (b == 0)
-   return u;
-
-   uu.ll = u;
-   bm = 32 - b;
-
-   if (bm <= 0) {
-   w.s.low = 0;
-   w.s.high = (unsigned int) uu.s.low << -bm;
-   } else {
-   const unsigned int carries = (unsigned int) uu.s.low >> bm;
-
-   w.s.low = (unsigned int) uu.s.low << b;
-   w.s.high = ((unsigned int) uu.s.high << b) | carries;
-   }
-
-   return w.ll;
-}
-
-EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
deleted file mode 100644
index 23f5295af51e..
--- a/arch/mips/lib/ashrdi3.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-long long notrace __ashrdi3(long long u, word_type b)
-{
-   DWunion uu, w;
-   word_type bm;
-
-   if (b == 0)
-   return u;
-
-   uu.ll = u;
-   bm = 32 - b;
-
-   if (bm <= 0) {
-   /* w.s.high = 1..1 or 0..0 */
-   w.s.high =
-   uu.s.high >> 31;
-   w.s.low = uu.s.high >> -bm;
-   } else {
-   const unsigned int carries = (unsigned int) uu.s.high << bm;
-
-   w.s.high = uu.s.high >> b;
-   w.s.low = ((unsigned int) uu.s.low >> b) | carries;
-   }
-
-   return w.ll;
-}
-
-EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/mips/lib/cmpdi2.c b/arch/mips/lib/cmpdi2.c
deleted file mode 100644
index 93cfc785927d..
--- a/arch/mips/lib/cmpdi2.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-word_type notrace __cmpdi2(long long a, long long b)
-{
-   const DWunion au = {
-   .ll = a
-   };
-   const DWunion bu = {
-   .ll = b
-   };
-
-   if (au.s.high < bu.s.high)
-   return 0;
-   else if (au.s.high > bu.s.high)
-   return 2;
-
-   if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
-   return 0;
-   else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
-   return 2;
-
-   return 1;
-}
-
-EXPORT_SYMBOL(__cmpdi2);
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
deleted file mode 100644
index 914b971aca3b..
--- a/arch/mips/lib/lshrdi3.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-
-#include "libgcc.h"
-
-long long notrace __lshrdi3(long long u, word_type b)
-{
-   DWunion uu, w;
-   word_type bm;
-
-   if (b == 0)
-   return u;
-
-   uu.ll = u;
-   bm = 32 - b;
-
-   if (bm <= 0) {
-   

Re: [PATCH v3 8/9] x86: use __uaccess_begin_nospec and ASM_IFENCE in get_user paths

2018-01-16 Thread Dan Williams
On Tue, Jan 16, 2018 at 10:28 PM, Al Viro  wrote:
> On Tue, Jan 16, 2018 at 08:30:17PM -0800, Dan Williams wrote:
>> On Tue, Jan 16, 2018 at 2:23 PM, Dan Williams  
>> wrote:
>> > On Sat, Jan 13, 2018 at 11:33 AM, Linus Torvalds
>> [..]
>> > I'll respin this set along those lines, and drop the ifence bits.
>>
>> So now I'm not so sure. Yes, get_user_{1,2,4,8} can mask the pointer
>> with the address limit result, but this doesn't work for the
>> access_ok() + __get_user() case. We can either change the access_ok()
>> calling convention to return a properly masked pointer to be used in
>> subsequent calls to __get_user(), or go with lfence on every
>> __get_user call. There seem to be several drivers that open code
>> copy_from_user() with __get_user loops, so the 'fence every
>> __get_user' approach might have noticeable overhead. On the other hand
>> the access_ok conversion, while it could be scripted with coccinelle,
>> is ~300 sites (VERIFY_READ), if you're concerned about having
>> something small to merge for 4.15.
>>
>> I think the access_ok() conversion to return a speculation sanitized
>> pointer or NULL is the way to go unless I'm missing something simpler.
>> Other ideas?
>
> What masked pointer?

The pointer value that is masked under speculation.

   diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
   index c97d935a29e8..4c378b485399 100644
   --- a/arch/x86/lib/getuser.S
   +++ b/arch/x86/lib/getuser.S
   @@ -40,6 +40,8 @@ ENTRY(__get_user_1)
   mov PER_CPU_VAR(current_task), %_ASM_DX
   cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
   jae bad_get_user
   +   sbb %_ASM_DX,%_ASM_DX
   +   and %_ASM_DX,%_ASM_AX
   ASM_STAC
1: movzbl (%_ASM_AX),%edx
   xor %eax,%eax

...i.e %_ASM_AX is guaranteed to be zero if userspace tries to cause
speculation with an address above the limit. The proposal is make
access_ok do that same masking so we never speculate on pointers from
userspace aimed at kernel memory.

> access_ok() exists for other architectures as well,

I'd modify those as well...

> and the fewer callers remain outside of arch/*, the better.
>
> Anything that open-codes copy_from_user() that way is *ALREADY* fucked if
> it cares about the overhead - recent x86 boxen will have slowdown from
> hell on stac()/clac() pairs.  Anything like that on a hot path is already
> deep in trouble and needs to be found and fixed.  What drivers would those
> be?

So I took a closer look and the pattern is not copy_from_user it's
more like __get_user + write-to-hardware loops. If the performance is
already expected to be bad for those then perhaps an lfence each loop
iteration won't be much worse. It's still a waste because the lfence
is only needed once after the access_ok.

> We don't have that many __get_user() users left outside of arch/*
> anymore...


Re: [PATCH v3 8/9] x86: use __uaccess_begin_nospec and ASM_IFENCE in get_user paths

2018-01-16 Thread Dan Williams
On Tue, Jan 16, 2018 at 10:28 PM, Al Viro  wrote:
> On Tue, Jan 16, 2018 at 08:30:17PM -0800, Dan Williams wrote:
>> On Tue, Jan 16, 2018 at 2:23 PM, Dan Williams  
>> wrote:
>> > On Sat, Jan 13, 2018 at 11:33 AM, Linus Torvalds
>> [..]
>> > I'll respin this set along those lines, and drop the ifence bits.
>>
>> So now I'm not so sure. Yes, get_user_{1,2,4,8} can mask the pointer
>> with the address limit result, but this doesn't work for the
>> access_ok() + __get_user() case. We can either change the access_ok()
>> calling convention to return a properly masked pointer to be used in
>> subsequent calls to __get_user(), or go with lfence on every
>> __get_user call. There seem to be several drivers that open code
>> copy_from_user() with __get_user loops, so the 'fence every
>> __get_user' approach might have noticeable overhead. On the other hand
>> the access_ok conversion, while it could be scripted with coccinelle,
>> is ~300 sites (VERIFY_READ), if you're concerned about having
>> something small to merge for 4.15.
>>
>> I think the access_ok() conversion to return a speculation sanitized
>> pointer or NULL is the way to go unless I'm missing something simpler.
>> Other ideas?
>
> What masked pointer?

The pointer value that is masked under speculation.

   diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
   index c97d935a29e8..4c378b485399 100644
   --- a/arch/x86/lib/getuser.S
   +++ b/arch/x86/lib/getuser.S
   @@ -40,6 +40,8 @@ ENTRY(__get_user_1)
   mov PER_CPU_VAR(current_task), %_ASM_DX
   cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
   jae bad_get_user
   +   sbb %_ASM_DX,%_ASM_DX
   +   and %_ASM_DX,%_ASM_AX
   ASM_STAC
1: movzbl (%_ASM_AX),%edx
   xor %eax,%eax

...i.e %_ASM_AX is guaranteed to be zero if userspace tries to cause
speculation with an address above the limit. The proposal is make
access_ok do that same masking so we never speculate on pointers from
userspace aimed at kernel memory.

> access_ok() exists for other architectures as well,

I'd modify those as well...

> and the fewer callers remain outside of arch/*, the better.
>
> Anything that open-codes copy_from_user() that way is *ALREADY* fucked if
> it cares about the overhead - recent x86 boxen will have slowdown from
> hell on stac()/clac() pairs.  Anything like that on a hot path is already
> deep in trouble and needs to be found and fixed.  What drivers would those
> be?

So I took a closer look and the pattern is not copy_from_user it's
more like __get_user + write-to-hardware loops. If the performance is
already expected to be bad for those then perhaps an lfence each loop
iteration won't be much worse. It's still a waste because the lfence
is only needed once after the access_ok.

> We don't have that many __get_user() users left outside of arch/*
> anymore...


[tip:x86/pti] x86/cpufeature: Move processor tracing out of scattered features

2018-01-16 Thread tip-bot for Paolo Bonzini
Commit-ID:  4fdec2034b7540dda461c6ba33325dfcff345c64
Gitweb: https://git.kernel.org/tip/4fdec2034b7540dda461c6ba33325dfcff345c64
Author: Paolo Bonzini 
AuthorDate: Tue, 16 Jan 2018 16:42:25 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 17 Jan 2018 07:38:39 +0100

x86/cpufeature: Move processor tracing out of scattered features

Processor tracing is already enumerated in word 9 (CPUID[7,0].EBX),
so do not duplicate it in the scattered features word.

Besides being more tidy, this will be useful for KVM when it presents
processor tracing to the guests.  KVM selects host features that are
supported by both the host kernel (depending on command line options,
CPU errata, or whatever) and KVM.  Whenever a full feature word exists,
KVM's code is written in the expectation that the CPUID bit number
matches the X86_FEATURE_* bit number, but this is not the case for
X86_FEATURE_INTEL_PT.

Signed-off-by: Paolo Bonzini 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Luwei Kang 
Cc: Peter Zijlstra 
Cc: Radim Krčmář 
Cc: Thomas Gleixner 
Cc: k...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1516117345-34561-1-git-send-email-pbonz...@redhat.com
Signed-off-by: Ingo Molnar 
---
 arch/x86/include/asm/cpufeatures.h | 2 +-
 arch/x86/kernel/cpu/scattered.c| 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/cpufeatures.h 
b/arch/x86/include/asm/cpufeatures.h
index aa09559..25b9375 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -206,7 +206,6 @@
 #define X86_FEATURE_RETPOLINE  ( 7*32+12) /* Generic Retpoline 
mitigation for Spectre variant 2 */
 #define X86_FEATURE_RETPOLINE_AMD  ( 7*32+13) /* AMD Retpoline mitigation 
for Spectre variant 2 */
 #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory 
Number */
-#define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512_4VNNIW  ( 7*32+16) /* AVX-512 Neural Network 
Instructions */
 #define X86_FEATURE_AVX512_4FMAPS  ( 7*32+17) /* AVX-512 Multiply 
Accumulation Single precision */
 
@@ -246,6 +245,7 @@
 #define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused 
Multiply-Add instructions */
 #define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
 #define X86_FEATURE_CLWB   ( 9*32+24) /* CLWB instruction */
+#define X86_FEATURE_INTEL_PT   ( 9*32+25) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512PF   ( 9*32+26) /* AVX-512 Prefetch */
 #define X86_FEATURE_AVX512ER   ( 9*32+27) /* AVX-512 Exponential and 
Reciprocal */
 #define X86_FEATURE_AVX512CD   ( 9*32+28) /* AVX-512 Conflict 
Detection */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 05459ad..d0e6976 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -21,7 +21,6 @@ struct cpuid_bit {
 static const struct cpuid_bit cpuid_bits[] = {
{ X86_FEATURE_APERFMPERF,   CPUID_ECX,  0, 0x0006, 0 },
{ X86_FEATURE_EPB,  CPUID_ECX,  3, 0x0006, 0 },
-   { X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x0007, 0 },
{ X86_FEATURE_AVX512_4VNNIW,CPUID_EDX,  2, 0x0007, 0 },
{ X86_FEATURE_AVX512_4FMAPS,CPUID_EDX,  3, 0x0007, 0 },
{ X86_FEATURE_CAT_L3,   CPUID_EBX,  1, 0x0010, 0 },


[tip:x86/pti] x86/cpufeature: Move processor tracing out of scattered features

2018-01-16 Thread tip-bot for Paolo Bonzini
Commit-ID:  4fdec2034b7540dda461c6ba33325dfcff345c64
Gitweb: https://git.kernel.org/tip/4fdec2034b7540dda461c6ba33325dfcff345c64
Author: Paolo Bonzini 
AuthorDate: Tue, 16 Jan 2018 16:42:25 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 17 Jan 2018 07:38:39 +0100

x86/cpufeature: Move processor tracing out of scattered features

Processor tracing is already enumerated in word 9 (CPUID[7,0].EBX),
so do not duplicate it in the scattered features word.

Besides being more tidy, this will be useful for KVM when it presents
processor tracing to the guests.  KVM selects host features that are
supported by both the host kernel (depending on command line options,
CPU errata, or whatever) and KVM.  Whenever a full feature word exists,
KVM's code is written in the expectation that the CPUID bit number
matches the X86_FEATURE_* bit number, but this is not the case for
X86_FEATURE_INTEL_PT.

Signed-off-by: Paolo Bonzini 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Luwei Kang 
Cc: Peter Zijlstra 
Cc: Radim Krčmář 
Cc: Thomas Gleixner 
Cc: k...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1516117345-34561-1-git-send-email-pbonz...@redhat.com
Signed-off-by: Ingo Molnar 
---
 arch/x86/include/asm/cpufeatures.h | 2 +-
 arch/x86/kernel/cpu/scattered.c| 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/cpufeatures.h 
b/arch/x86/include/asm/cpufeatures.h
index aa09559..25b9375 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -206,7 +206,6 @@
 #define X86_FEATURE_RETPOLINE  ( 7*32+12) /* Generic Retpoline 
mitigation for Spectre variant 2 */
 #define X86_FEATURE_RETPOLINE_AMD  ( 7*32+13) /* AMD Retpoline mitigation 
for Spectre variant 2 */
 #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory 
Number */
-#define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512_4VNNIW  ( 7*32+16) /* AVX-512 Neural Network 
Instructions */
 #define X86_FEATURE_AVX512_4FMAPS  ( 7*32+17) /* AVX-512 Multiply 
Accumulation Single precision */
 
@@ -246,6 +245,7 @@
 #define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused 
Multiply-Add instructions */
 #define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
 #define X86_FEATURE_CLWB   ( 9*32+24) /* CLWB instruction */
+#define X86_FEATURE_INTEL_PT   ( 9*32+25) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512PF   ( 9*32+26) /* AVX-512 Prefetch */
 #define X86_FEATURE_AVX512ER   ( 9*32+27) /* AVX-512 Exponential and 
Reciprocal */
 #define X86_FEATURE_AVX512CD   ( 9*32+28) /* AVX-512 Conflict 
Detection */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 05459ad..d0e6976 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -21,7 +21,6 @@ struct cpuid_bit {
 static const struct cpuid_bit cpuid_bits[] = {
{ X86_FEATURE_APERFMPERF,   CPUID_ECX,  0, 0x0006, 0 },
{ X86_FEATURE_EPB,  CPUID_ECX,  3, 0x0006, 0 },
-   { X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x0007, 0 },
{ X86_FEATURE_AVX512_4VNNIW,CPUID_EDX,  2, 0x0007, 0 },
{ X86_FEATURE_AVX512_4FMAPS,CPUID_EDX,  3, 0x0007, 0 },
{ X86_FEATURE_CAT_L3,   CPUID_EBX,  1, 0x0010, 0 },


Re: [PATCH 1/2] powerpc: export thread-tidr interfaces

2018-01-16 Thread Frederic Barrat

Hi,



diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2010e4c..f20c1ad 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1560,6 +1560,7 @@ void clear_thread_tidr(struct task_struct *t)
free_thread_tidr(t->thread.tidr);
t->thread.tidr = 0;
  }
+EXPORT_SYMBOL_GPL(clear_thread_tidr);


Isn't it dangerous to export clear_thread_tidr()? Other modules may also 
have assigned the TIDR by calling set_thread_tidr(), so clearing it 
could potentially break those other modules. My understanding is that 
once the TIDR is assigned, there's no safe way to reclaim it other than 
the thread exiting. Or we would need some kind of reference counter.




  void arch_release_task_struct(struct task_struct *t)
  {
@@ -1592,6 +1593,7 @@ int set_thread_tidr(struct task_struct *t)

return 0;
  }
+EXPORT_SYMBOL_GPL(set_thread_tidr);



FYI, there's a capi patch we hope to merge soon which is also doing this:
http://patchwork.ozlabs.org/patch/858935/

  Fred



Re: [PATCH 1/2] powerpc: export thread-tidr interfaces

2018-01-16 Thread Frederic Barrat

Hi,



diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2010e4c..f20c1ad 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1560,6 +1560,7 @@ void clear_thread_tidr(struct task_struct *t)
free_thread_tidr(t->thread.tidr);
t->thread.tidr = 0;
  }
+EXPORT_SYMBOL_GPL(clear_thread_tidr);


Isn't it dangerous to export clear_thread_tidr()? Other modules may also 
have assigned the TIDR by calling set_thread_tidr(), so clearing it 
could potentially break those other modules. My understanding is that 
once the TIDR is assigned, there's no safe way to reclaim it other than 
the thread exiting. Or we would need some kind of reference counter.




  void arch_release_task_struct(struct task_struct *t)
  {
@@ -1592,6 +1593,7 @@ int set_thread_tidr(struct task_struct *t)

return 0;
  }
+EXPORT_SYMBOL_GPL(set_thread_tidr);



FYI, there's a capi patch we hope to merge soon which is also doing this:
http://patchwork.ozlabs.org/patch/858935/

  Fred



Re: WARNING in can_rcv

2018-01-16 Thread Oliver Hartkopp



On 01/16/2018 07:11 PM, Dmitry Vyukov wrote:

On Tue, Jan 16, 2018 at 7:07 PM, Marc Kleine-Budde  wrote:

On 01/16/2018 06:58 PM, syzbot wrote:

Hello,

syzkaller hit the following crash on
a8750ddca918032d6349adbf9a4b6555e7db20da
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
compiler: gcc (GCC) 7.1.1 20170620
.config is attached
Raw console output is attached.
C reproducer is attached
syzkaller reproducer is attached. See https://goo.gl/kgGztJ
for information about syzkaller reproducers


IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+4386709c0c1284dca...@syzkaller.appspotmail.com
It will help syzbot understand when the bug is fixed. See footer for
details.
If you forward the report, please keep this part and the footer.

device eql entered promiscuous mode
[ cut here ]
PF_CAN: dropped non conform CAN skbuf: dev type 65534, len 42, datalen 0
WARNING: CPU: 0 PID: 3650 at net/can/af_can.c:729 can_rcv+0x1c5/0x200
net/can/af_can.c:724
Kernel panic - not syncing: panic_on_warn set ...


Invalid packages generate a warning (WARN_ONCE()), and you have
panic_on_warn active. Should we better silently drop these CAN packages?


Hi,

pr_warn_once() will be more appropriate. It prints a single line.



The idea behind this WARN() is to detect really bad things that might 
have happen on network driver level:


The CAN subsystem registers with dev_add_pack() for ETH_P_CAN and 
ETH_P_CANFD only. These ETH_P_ types are only allowed to be created by 
CAN network devices (like vcan, vxcan, and real CAN drivers).


I don't have any strong opinion on using WARN() or pr_warn_once().
Is this detected violation worth using WARN(), as something already must 
have gone really wrong to trigger this issue?


Best regards,
Oliver


Re: WARNING in can_rcv

2018-01-16 Thread Oliver Hartkopp



On 01/16/2018 07:11 PM, Dmitry Vyukov wrote:

On Tue, Jan 16, 2018 at 7:07 PM, Marc Kleine-Budde  wrote:

On 01/16/2018 06:58 PM, syzbot wrote:

Hello,

syzkaller hit the following crash on
a8750ddca918032d6349adbf9a4b6555e7db20da
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master
compiler: gcc (GCC) 7.1.1 20170620
.config is attached
Raw console output is attached.
C reproducer is attached
syzkaller reproducer is attached. See https://goo.gl/kgGztJ
for information about syzkaller reproducers


IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+4386709c0c1284dca...@syzkaller.appspotmail.com
It will help syzbot understand when the bug is fixed. See footer for
details.
If you forward the report, please keep this part and the footer.

device eql entered promiscuous mode
[ cut here ]
PF_CAN: dropped non conform CAN skbuf: dev type 65534, len 42, datalen 0
WARNING: CPU: 0 PID: 3650 at net/can/af_can.c:729 can_rcv+0x1c5/0x200
net/can/af_can.c:724
Kernel panic - not syncing: panic_on_warn set ...


Invalid packages generate a warning (WARN_ONCE()), and you have
panic_on_warn active. Should we better silently drop these CAN packages?


Hi,

pr_warn_once() will be more appropriate. It prints a single line.



The idea behind this WARN() is to detect really bad things that might 
have happen on network driver level:


The CAN subsystem registers with dev_add_pack() for ETH_P_CAN and 
ETH_P_CANFD only. These ETH_P_ types are only allowed to be created by 
CAN network devices (like vcan, vxcan, and real CAN drivers).


I don't have any strong opinion on using WARN() or pr_warn_once().
Is this detected violation worth using WARN(), as something already must 
have gone really wrong to trigger this issue?


Best regards,
Oliver


Re: general protection fault in __crypto_alg_lookup

2018-01-16 Thread Eric Biggers
On Tue, Dec 19, 2017 at 11:49:02PM -0800, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on
> 6084b576dca2e898f5c101baef151f7bfdbb606d
> git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> 
> Unfortunately, I don't have any reproducer for this bug yet.
> 
> 
> SELinux: unrecognized netlink message: protocol=0 nlmsg_type=256
> sclass=netlink_route_socket pig=17315 comm=syz-executor6
> SELinux: unrecognized netlink message: protocol=0 nlmsg_type=256
> sclass=netlink_route_socket pig=17326 comm=syz-executor6
> general protection fault:  [#1] SMP
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Modules linked in:
> CPU: 1 PID: 17336 Comm: syz-executor7 Not tainted 4.15.0-rc3-next-20171214+
> #67
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> RIP: 0010:__crypto_alg_lookup+0x43/0x190 crypto/api.c:63
> RSP: 0018:c9d7fcb8 EFLAGS: 00010216
> RAX: 0001 RBX: 623e2d6261746826 RCX: 816741f3
> RDX: 00d9 RSI: c90001a01000 RDI: 8801f9d11891
> RBP: c9d7fd00 R08: 0001 R09: 0001
> R10: c9d7fc80 R11:  R12: 
> R13: 72612f66 R14: 240e R15: 040f
> FS:  7ff6c7ec5700() GS:88021fd0() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 20f35000 CR3: 0001fce0e004 CR4: 001606e0
> Call Trace:
>  crypto_alg_lookup+0x31/0x50 crypto/api.c:201
>  crypto_larval_lookup.part.8+0x34/0x1c0 crypto/api.c:218
>  crypto_larval_lookup crypto/api.c:212 [inline]
>  crypto_alg_mod_lookup+0x77/0x120 crypto/api.c:271
>  crypto_find_alg crypto/api.c:501 [inline]
>  crypto_alloc_tfm+0x67/0x180 crypto/api.c:534
>  crypto_alloc_ahash+0x2c/0x40 crypto/ahash.c:540
>  hash_bind+0x51/0x90 crypto/algif_hash.c:422
>  alg_bind+0x94/0x180 crypto/af_alg.c:179
>  SYSC_bind+0xa8/0x130 net/socket.c:1454
>  SyS_bind+0x24/0x30 net/socket.c:1440
>  entry_SYSCALL_64_fastpath+0x1f/0x96
> RIP: 0033:0x452a09
> RSP: 002b:7ff6c7ec4c58 EFLAGS: 0212 ORIG_RAX: 0031
> RAX: ffda RBX: 0071bea0 RCX: 00452a09
> RDX: 0058 RSI: 20f35000 RDI: 0013
> RBP: 0554 R08:  R09: 
> R10:  R11: 0212 R12: 006f5080
> R13:  R14: 7ff6c7ec56d4 R15: 
> Code: 89 7d d0 e8 70 61 c4 ff 48 8b 1d 89 df a6 01 48 81 fb 60 21 0e 83 0f
> 84 4c 01 00 00 c7 45 c4 fe ff ff ff 45 31 e4 e8 4d 61 c4 ff <44> 8b 6b 20 41
> f6 c5 60 0f 85 03 01 00 00 e8 3a 61 c4 ff 44 89
> RIP: __crypto_alg_lookup+0x43/0x190 crypto/api.c:63 RSP: c9d7fcb8
> ---[ end trace 17ac9655be6571e5 ]---
> Kernel panic - not syncing: Fatal exception
> netlink: 5 bytes leftover after parsing attributes in process
> `syz-executor6'.
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..
> 

Invalidating this bug now that a similar one has been fixed; we'll see if it
happens again...

#syz invalid


Re: general protection fault in __crypto_alg_lookup

2018-01-16 Thread Eric Biggers
On Tue, Dec 19, 2017 at 11:49:02PM -0800, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on
> 6084b576dca2e898f5c101baef151f7bfdbb606d
> git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> 
> Unfortunately, I don't have any reproducer for this bug yet.
> 
> 
> SELinux: unrecognized netlink message: protocol=0 nlmsg_type=256
> sclass=netlink_route_socket pig=17315 comm=syz-executor6
> SELinux: unrecognized netlink message: protocol=0 nlmsg_type=256
> sclass=netlink_route_socket pig=17326 comm=syz-executor6
> general protection fault:  [#1] SMP
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Modules linked in:
> CPU: 1 PID: 17336 Comm: syz-executor7 Not tainted 4.15.0-rc3-next-20171214+
> #67
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> RIP: 0010:__crypto_alg_lookup+0x43/0x190 crypto/api.c:63
> RSP: 0018:c9d7fcb8 EFLAGS: 00010216
> RAX: 0001 RBX: 623e2d6261746826 RCX: 816741f3
> RDX: 00d9 RSI: c90001a01000 RDI: 8801f9d11891
> RBP: c9d7fd00 R08: 0001 R09: 0001
> R10: c9d7fc80 R11:  R12: 
> R13: 72612f66 R14: 240e R15: 040f
> FS:  7ff6c7ec5700() GS:88021fd0() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 20f35000 CR3: 0001fce0e004 CR4: 001606e0
> Call Trace:
>  crypto_alg_lookup+0x31/0x50 crypto/api.c:201
>  crypto_larval_lookup.part.8+0x34/0x1c0 crypto/api.c:218
>  crypto_larval_lookup crypto/api.c:212 [inline]
>  crypto_alg_mod_lookup+0x77/0x120 crypto/api.c:271
>  crypto_find_alg crypto/api.c:501 [inline]
>  crypto_alloc_tfm+0x67/0x180 crypto/api.c:534
>  crypto_alloc_ahash+0x2c/0x40 crypto/ahash.c:540
>  hash_bind+0x51/0x90 crypto/algif_hash.c:422
>  alg_bind+0x94/0x180 crypto/af_alg.c:179
>  SYSC_bind+0xa8/0x130 net/socket.c:1454
>  SyS_bind+0x24/0x30 net/socket.c:1440
>  entry_SYSCALL_64_fastpath+0x1f/0x96
> RIP: 0033:0x452a09
> RSP: 002b:7ff6c7ec4c58 EFLAGS: 0212 ORIG_RAX: 0031
> RAX: ffda RBX: 0071bea0 RCX: 00452a09
> RDX: 0058 RSI: 20f35000 RDI: 0013
> RBP: 0554 R08:  R09: 
> R10:  R11: 0212 R12: 006f5080
> R13:  R14: 7ff6c7ec56d4 R15: 
> Code: 89 7d d0 e8 70 61 c4 ff 48 8b 1d 89 df a6 01 48 81 fb 60 21 0e 83 0f
> 84 4c 01 00 00 c7 45 c4 fe ff ff ff 45 31 e4 e8 4d 61 c4 ff <44> 8b 6b 20 41
> f6 c5 60 0f 85 03 01 00 00 e8 3a 61 c4 ff 44 89
> RIP: __crypto_alg_lookup+0x43/0x190 crypto/api.c:63 RSP: c9d7fcb8
> ---[ end trace 17ac9655be6571e5 ]---
> Kernel panic - not syncing: Fatal exception
> netlink: 5 bytes leftover after parsing attributes in process
> `syz-executor6'.
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..
> 

Invalidating this bug now that a similar one has been fixed; we'll see if it
happens again...

#syz invalid


Re: BUG: unable to handle kernel NULL pointer dereference in crypto_alg_tested

2018-01-16 Thread Eric Biggers
On Fri, Dec 22, 2017 at 11:33:02PM -0800, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on
> 6084b576dca2e898f5c101baef151f7bfdbb606d
> git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> 
> Unfortunately, I don't have any reproducer for this bug yet.
> 
> 
> encrypted_key: master key parameter '� 
> ���"j�f@��� 0UY@*��q� -� {�o�' is invalid
> could not allocate digest TFM handle cryptd(sha224)
> BUG: unable to handle kernel NULL pointer dereference at 0020
> binder: BINDER_SET_CONTEXT_MGR already set
> binder: 5108:5114 ioctl 40046207 0 returned -16
> encrypted_key: master key parameter '� 
> ���"j�f@��� 0UY@*��q� -� {�o�' is invalid
> IP: crypto_alg_tested+0xe9/0x260 crypto/algapi.c:275
> PGD 0 P4D 0
> Oops:  [#1] SMP
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Modules linked in:
> CPU: 0 PID: 5153 Comm: cryptomgr_test Not tainted 4.15.0-rc3-next-20171214+
> #67
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> RIP: 0010:crypto_alg_tested+0xe9/0x260 crypto/algapi.c:275
> RSP: 0018:c9eafe98 EFLAGS: 00010293
> RAX: 8801fc9d66c0 RBX: 8801fcb35400 RCX: 81677729
> RDX:  RSI: 880215732481 RDI: 8801fd654081
> RBP: c9eafee8 R08: 0001 R09: 0004
> R10: c9eafe08 R11: 0004 R12: 
> R13: 8801fd654048 R14: 0c8f R15: c9eafeb0
> FS:  () GS:88021fc0() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 0020 CR3: 0301e002 CR4: 001606f0
> DR0: 20001000 DR1: 20001008 DR2: 20001000
> DR3: 20001008 DR6: fffe0ff0 DR7: 0600
> Call Trace:
>  cryptomgr_test+0x17/0x30 crypto/algboss.c:226
>  kthread+0x149/0x170 kernel/kthread.c:238
>  ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:524
> Code: c5 0f 84 a5 00 00 00 e8 36 2c c4 ff 41 81 4d 20 00 04 00 00 49 8d 45
> 38 48 89 45 c0 e8 21 2c c4 ff 4d 39 e5 74 70 e8 17 2c c4 ff <45> 8b 74 24 20
> 41 f6 c6 60 75 60 e8 07 2c c4 ff 49 8d 44 24 38
> RIP: crypto_alg_tested+0xe9/0x260 crypto/algapi.c:275 RSP: c9eafe98
> CR2: 0020
> ---[ end trace bf93c4f60f101736 ]---
> Kernel panic - not syncing: Fatal exception
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..

Invalidating this bug now that a similar one has been fixed; we'll see if it
happens again...

#syz invalid


Re: BUG: unable to handle kernel NULL pointer dereference in crypto_alg_tested

2018-01-16 Thread Eric Biggers
On Fri, Dec 22, 2017 at 11:33:02PM -0800, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on
> 6084b576dca2e898f5c101baef151f7bfdbb606d
> git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> 
> Unfortunately, I don't have any reproducer for this bug yet.
> 
> 
> encrypted_key: master key parameter '� 
> ���"j�f@��� 0UY@*��q� -� {�o�' is invalid
> could not allocate digest TFM handle cryptd(sha224)
> BUG: unable to handle kernel NULL pointer dereference at 0020
> binder: BINDER_SET_CONTEXT_MGR already set
> binder: 5108:5114 ioctl 40046207 0 returned -16
> encrypted_key: master key parameter '� 
> ���"j�f@��� 0UY@*��q� -� {�o�' is invalid
> IP: crypto_alg_tested+0xe9/0x260 crypto/algapi.c:275
> PGD 0 P4D 0
> Oops:  [#1] SMP
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Modules linked in:
> CPU: 0 PID: 5153 Comm: cryptomgr_test Not tainted 4.15.0-rc3-next-20171214+
> #67
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> RIP: 0010:crypto_alg_tested+0xe9/0x260 crypto/algapi.c:275
> RSP: 0018:c9eafe98 EFLAGS: 00010293
> RAX: 8801fc9d66c0 RBX: 8801fcb35400 RCX: 81677729
> RDX:  RSI: 880215732481 RDI: 8801fd654081
> RBP: c9eafee8 R08: 0001 R09: 0004
> R10: c9eafe08 R11: 0004 R12: 
> R13: 8801fd654048 R14: 0c8f R15: c9eafeb0
> FS:  () GS:88021fc0() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 0020 CR3: 0301e002 CR4: 001606f0
> DR0: 20001000 DR1: 20001008 DR2: 20001000
> DR3: 20001008 DR6: fffe0ff0 DR7: 0600
> Call Trace:
>  cryptomgr_test+0x17/0x30 crypto/algboss.c:226
>  kthread+0x149/0x170 kernel/kthread.c:238
>  ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:524
> Code: c5 0f 84 a5 00 00 00 e8 36 2c c4 ff 41 81 4d 20 00 04 00 00 49 8d 45
> 38 48 89 45 c0 e8 21 2c c4 ff 4d 39 e5 74 70 e8 17 2c c4 ff <45> 8b 74 24 20
> 41 f6 c6 60 75 60 e8 07 2c c4 ff 49 8d 44 24 38
> RIP: crypto_alg_tested+0xe9/0x260 crypto/algapi.c:275 RSP: c9eafe98
> CR2: 0020
> ---[ end trace bf93c4f60f101736 ]---
> Kernel panic - not syncing: Fatal exception
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..

Invalidating this bug now that a similar one has been fixed; we'll see if it
happens again...

#syz invalid


Re: general protection fault in crypto_remove_spawns

2018-01-16 Thread Eric Biggers
On Mon, Nov 27, 2017 at 10:56:46AM -0800, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on
> 1ea8d039f9edcfefb20d8ddfe136930f6e551529
> git://git.cmpxchg.org/linux-mmots.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> C reproducer is attached
> syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> for information about syzkaller reproducers
> 
> 
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Modules linked in:
> CPU: 0 PID: 25985 Comm: cryptomgr_test Not tainted 4.14.0-mm1+ #25
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> task: 8801c4562180 task.stack: 8801d5b7
> RIP: 0010:crypto_remove_spawns+0x58c/0x1260 crypto/algapi.c:159
> RSP: 0018:8801d5b779e8 EFLAGS: 00010206
> RAX: 0003 RBX: dc00 RCX: 82258aab
> RDX:  RSI: 11003ab6efa6 RDI: 0018
> RBP: 8801d5b77dd8 R08: 8801d5b77d70 R09: 0004
> R10:  R11: 8747dda0 R12: 
> R13: 8801c505bb60 R14: ed003ab6ef4e R15: 8801d5b77db0
> FS:  () GS:8801db40() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7fff1d3ffcac CR3: 0001cf825000 CR4: 001406f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> Call Trace:
>  crypto_alg_tested+0x514/0x6f0 crypto/algapi.c:311
>  cryptomgr_test+0x17/0x30 crypto/algboss.c:226
>  kthread+0x37a/0x440 kernel/kthread.c:238
>  ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:437
> Code: 84 e3 01 00 00 e8 35 94 4a ff 4c 89 e8 48 c1 e8 03 80 3c 18 00 0f 85
> d8 09 00 00 4d 8b 65 00 49 8d 7c 24 18 48 89 f8 48 c1 e8 03 <80> 3c 18 00 0f
> 85 b4 09 00 00 4d 8b 6c 24 18 4c 3b ad 50 fc ff
> RIP: crypto_remove_spawns+0x58c/0x1260 crypto/algapi.c:159 RSP:
> 8801d5b779e8
> ---[ end trace 14ce8f86fe2873b1 ]---
> Kernel panic - not syncing: Fatal exception
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..

Fix for the actual crash now is in Linus' tree:

#syz fix: crypto: algapi - fix NULL dereference in crypto_remove_spawns()


Re: general protection fault in crypto_remove_spawns

2018-01-16 Thread Eric Biggers
On Mon, Nov 27, 2017 at 10:56:46AM -0800, syzbot wrote:
> Hello,
> 
> syzkaller hit the following crash on
> 1ea8d039f9edcfefb20d8ddfe136930f6e551529
> git://git.cmpxchg.org/linux-mmots.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> C reproducer is attached
> syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> for information about syzkaller reproducers
> 
> 
> kasan: CONFIG_KASAN_INLINE enabled
> kasan: GPF could be caused by NULL-ptr deref or user memory access
> general protection fault:  [#1] SMP KASAN
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Modules linked in:
> CPU: 0 PID: 25985 Comm: cryptomgr_test Not tainted 4.14.0-mm1+ #25
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> task: 8801c4562180 task.stack: 8801d5b7
> RIP: 0010:crypto_remove_spawns+0x58c/0x1260 crypto/algapi.c:159
> RSP: 0018:8801d5b779e8 EFLAGS: 00010206
> RAX: 0003 RBX: dc00 RCX: 82258aab
> RDX:  RSI: 11003ab6efa6 RDI: 0018
> RBP: 8801d5b77dd8 R08: 8801d5b77d70 R09: 0004
> R10:  R11: 8747dda0 R12: 
> R13: 8801c505bb60 R14: ed003ab6ef4e R15: 8801d5b77db0
> FS:  () GS:8801db40() knlGS:
> CS:  0010 DS:  ES:  CR0: 80050033
> CR2: 7fff1d3ffcac CR3: 0001cf825000 CR4: 001406f0
> DR0:  DR1:  DR2: 
> DR3:  DR6: fffe0ff0 DR7: 0400
> Call Trace:
>  crypto_alg_tested+0x514/0x6f0 crypto/algapi.c:311
>  cryptomgr_test+0x17/0x30 crypto/algboss.c:226
>  kthread+0x37a/0x440 kernel/kthread.c:238
>  ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:437
> Code: 84 e3 01 00 00 e8 35 94 4a ff 4c 89 e8 48 c1 e8 03 80 3c 18 00 0f 85
> d8 09 00 00 4d 8b 65 00 49 8d 7c 24 18 48 89 f8 48 c1 e8 03 <80> 3c 18 00 0f
> 85 b4 09 00 00 4d 8b 6c 24 18 4c 3b ad 50 fc ff
> RIP: crypto_remove_spawns+0x58c/0x1260 crypto/algapi.c:159 RSP:
> 8801d5b779e8
> ---[ end trace 14ce8f86fe2873b1 ]---
> Kernel panic - not syncing: Fatal exception
> Dumping ftrace buffer:
>(ftrace buffer empty)
> Kernel Offset: disabled
> Rebooting in 86400 seconds..

Fix for the actual crash now is in Linus' tree:

#syz fix: crypto: algapi - fix NULL dereference in crypto_remove_spawns()


  1   2   3   4   5   6   7   8   9   10   >