All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: New option for wall to limit message by group?
From: Jim Patterson @ 2016-11-14 17:59 UTC (permalink / raw)
  To: kerolasa; +Cc: util-linux
In-Reply-To: <CAG27Bk3hONs8GZ_4GvwJYHu-kMntNzvmVn-qzSO7p6EBDS8xog@mail.gmail.com>

Hi Sami,

I think can handle the code without difficulty, but I'm open to help
from anyone we wants to help, and of course code review and feedback
is always welcome.

Thanks for heads up about the maintainer, sounds like a great holiday.

Jim P


On Mon, Nov 14, 2016 at 12:18 PM, Sami Kerola <kerolasa@iki.fi> wrote:
> On 14 November 2016 at 16:31, Jim Patterson <jimp@wegrok.net> wrote:
>> The company that I work for has an old terminal application that is
>> still in use today.  This app used to run on AIX boxes but has been
>> moved to modern Linux based systems.  The users on this application
>> are in groups and under AIX we used the "-g" switch on wall to be able
>> to send a message to a single group at a time.  The wall on Linux does
>> not offer this option.  I will either be adding this option to wall or
>> writing a custom tool to support sending a message based on the user's
>> groups.
>>
>> Is there any interest in a pull request supporting such an option in
>> the standard wall?  And if so, does anyone have any particular
>> concerns about implementation details?
>>
>> The AIX man page does not describe the implementation details, but
>> experimenting with the command on an AIX system shows that the the
>> message is sent to all users that have the specified group in the
>> primary or supplementary groups.  My plan for doing this on a Linux
>> system is to use the username in the utmp entry to lookup the user's
>> primary and supplementary groups, then skip the utmp entry if the user
>> does not have the specified group.
>>
>> Thanks in advance,
>> Jim P
>>
>> PS. I'm not subscribed to the group, so please reply to this address also.
>
> Hi Jim,
>
> Adding -g, --group <groupname|gid> option should be doable. Do you want
> to write this change or prefer someone else doing the work? Either way I
> don't mind helping a bit.
>
> Reference: http://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.cmds6/wall.htm
>
> p.s. Maintainer is off-line
> http://marc.info/?l=util-linux-ng&m=147877091818853&w=2
>
> --
> Sami Kerola
> http://www.iki.fi/kerolasa/

^ permalink raw reply

* Re: Debugging Ethernet issues
From: Sebastian Frias @ 2016-11-14 17:59 UTC (permalink / raw)
  To: Florian Fainelli, Mason, Andrew Lunn
  Cc: netdev, Mans Rullgard, Sergei Shtylyov, Tom Lendacky, Zach Brown,
	Shaohui Xie, Tim Beale, Brian Hill, Vince Bridgers,
	Balakumaran Kannan, David S. Miller, Kirill Kapranov
In-Reply-To: <3313424a-8d45-0883-5257-ffdc250dd45b@gmail.com>

On 11/14/2016 06:32 PM, Florian Fainelli wrote:
> On 11/14/2016 07:33 AM, Mason wrote:
>> On 14/11/2016 15:58, Mason wrote:
>>
>>> nb8800 26000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
>>> vs
>>> nb8800 26000.ethernet eth0: Link is Up - 100Mbps/Full - flow control off
>>>
>>> I'm not sure whether "flow control" is relevant...
>>
>> Based on phy_print_status()
>> phydev->pause ? "rx/tx" : "off"
>> I added the following patch.
>>
>> diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c
>> index defc22a15f67..4e758c1cfa4e 100644
>> --- a/drivers/net/ethernet/aurora/nb8800.c
>> +++ b/drivers/net/ethernet/aurora/nb8800.c
>> @@ -667,6 +667,8 @@ static void nb8800_link_reconfigure(struct net_device *dev)
>>         struct phy_device *phydev = priv->phydev;
>>         int change = 0;
>>  
>> +       printk("%s from %pf\n", __func__, __builtin_return_address(0));
>> +
>>         if (phydev->link) {
>>                 if (phydev->speed != priv->speed) {
>>                         priv->speed = phydev->speed;
>> @@ -1274,9 +1276,9 @@ static int nb8800_hw_init(struct net_device *dev)
>>         nb8800_writeb(priv, NB8800_PQ2, val & 0xff);
>>  
>>         /* Auto-negotiate by default */
>> -       priv->pause_aneg = true;
>> -       priv->pause_rx = true;
>> -       priv->pause_tx = true;
>> +       priv->pause_aneg = false;
>> +       priv->pause_rx = false;
>> +       priv->pause_tx = false;
>>  
>>         nb8800_mc_init(dev, 0);
>>  
>>
>> Connected to 1000 Mbps switch:
>>
>> # time udhcpc | while read LINE; do date; echo $LINE; done
>> Thu Jan  1 00:00:22 UTC 1970
>> udhcpc (v1.22.1) started
>> Thu Jan  1 00:00:22 UTC 1970
>> Sending discover...
>> [   24.565346] nb8800_link_reconfigure from phy_state_machine
>> Thu Jan  1 00:00:25 UTC 1970
>> Sending discover...
>> [   26.575402] nb8800_link_reconfigure from phy_state_machine
>> [   26.580972] nb8800 26000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
>> Thu Jan  1 00:00:28 UTC 1970
>> Sending discover...
>> Thu Jan  1 00:00:29 UTC 1970
>> Sending select for 172.27.64.58...
>> Thu Jan  1 00:00:29 UTC 1970
>> Lease of 172.27.64.58 obtained, lease time 604800
>> Thu Jan  1 00:00:29 UTC 1970
>> deleting routers
>> Thu Jan  1 00:00:29 UTC 1970
>> adding dns 172.27.0.17
>>
>> real    0m7.388s
>> user    0m0.040s
>> sys     0m0.090s
>>
>>
>>
>> Connected to 100 Mbps switch:
>>
>> # time udhcpc | while read LINE; do date; echo $LINE; done
>> Thu Jan  1 00:00:14 UTC 1970
>> udhcpc (v1.22.1) started
>> Thu Jan  1 00:00:15 UTC 1970
>> Sending discover...
>> [   16.968621] nb8800_link_reconfigure from phy_state_machine
>> [   17.975359] nb8800_link_reconfigure from phy_state_machine
>> [   17.980923] nb8800 26000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
>> Thu Jan  1 00:00:18 UTC 1970
>> Sending discover...
>> Thu Jan  1 00:00:19 UTC 1970
>> Sending select for 172.27.64.58...
>> Thu Jan  1 00:00:19 UTC 1970
>> Lease of 172.27.64.58 obtained, lease time 604800
>> Thu Jan  1 00:00:19 UTC 1970
>> deleting routers
>> Thu Jan  1 00:00:19 UTC 1970
>> adding dns 172.27.0.17
>>
>> real    0m4.355s
>> user    0m0.043s
>> sys     0m0.083s
>>
> 
> And the time difference is clearly accounted for auto-negotiation time
> here, as you can see it takes about 3 seconds for Gigabit Ethernet to
> auto-negotiate and that seems completely acceptable and normal to me
> since it is a more involved process than lower speeds.
> 
>>
>>
>> OK, so now it works (by accident?) even on 100 Mbps switch, but it still
>> prints "flow control rx/tx"...
> 
> Because your link partner advertises flow control, and that's what
> phydev->pause and phydev->asym_pause report (I know it's confusing, but
> that's what it is at the moment).

Thanks.
Could you confirm that Mason's patch is correct and/or that it does not
has negative side-effects?

Right now we know that Mason's patch makes this work, but we do not understand
why nor its implications.

> 
>>
>> # ethtool -a eth0
>> Pause parameters for eth0:
>> Autonegotiate:  off
>> RX:             off
>> TX:             off
>>
>> These values make sense considering my changes in the driver.
>>
>> Are 100 Mbps switches supposed to support these pause features,
>> and are they supposed to be able to auto-negotiate them?
> 
> Yes, switches can support flow control aka pause frames, and unless they
> are configurable, they typically advertise what their EEPROM has defined
> for them, so most likely the full auto-negotiated spectrum:
> 10/100/1000Mbps and support for flow control, but your mileage may vary
> of course.
> 

^ permalink raw reply

* Re: [Qemu-devel] [PATCH V11 1/1] fsdev: add IO throttle support to fsdev devices
From: Greg Kurz @ 2016-11-14 17:57 UTC (permalink / raw)
  To: Pradeep Jagadeesh
  Cc: Pradeep Jagadeesh, Aneesh Kumar K.V, Alberto Garcia, qemu-devel,
	Claudio Fontana
In-Reply-To: <591b301b-91a1-45b1-f10b-b94929d4d0d0@huawei.com>

On Mon, 14 Nov 2016 10:03:40 +0100
Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com> wrote:

> On 11/12/2016 3:13 PM, Greg Kurz wrote:
> > On Fri, 11 Nov 2016 03:54:27 -0500
> > Pradeep Jagadeesh <pradeepkiruvale@gmail.com> wrote:
> >  
> >> Uses throttling APIs to limit I/O bandwidth and number of operations on the
> >> devices which use 9p-local driver.
> >>
> >> Signed-off-by: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
> >> Reviewed-by: Alberto Garcia" <berto@igalia.com>
> >> ---  
> >
> > Hi Pradeep,
> >
> > I'll have a look next week but I'm not sure this can go to 2.8 since we're
> > already in soft feature freeze (only bug fixes are accepted).  
> 
> Hi Greg,
> 
> It is ok even if it does not make it to 2.8.I just want to complete this 
> work from my side.
> 

Hi Pradeep,

The patch looks good to me now. Since we're no more in a hurry to get this
merged, maybe you can now try to address the code duplication issue with
the command line options ? Ideally this should be done in a preparatory
patch.

Cheers.

--
Greg

> Thanks,
> Pradeep
> >
> > Cheers.
> >
> > --
> > Greg
> >  
> >>  fsdev/Makefile.objs         |   2 +-
> >>  fsdev/file-op-9p.h          |   3 ++
> >>  fsdev/qemu-fsdev-opts.c     |  77 ++++++++++++++++++++++++++++-
> >>  fsdev/qemu-fsdev-throttle.c | 117 ++++++++++++++++++++++++++++++++++++++++++++
> >>  fsdev/qemu-fsdev-throttle.h |  39 +++++++++++++++
> >>  hw/9pfs/9p-local.c          |   8 +++
> >>  hw/9pfs/9p.c                |   5 ++
> >>  hw/9pfs/cofile.c            |   2 +
> >>  8 files changed, 251 insertions(+), 2 deletions(-)
> >>  create mode 100644 fsdev/qemu-fsdev-throttle.c
> >>  create mode 100644 fsdev/qemu-fsdev-throttle.h
> >>
> >> This adds the support for the 9p-local driver.
> >> For now this functionality can be enabled only through qemu cli options.
> >> QMP interface and support to other drivers need further extensions.
> >> To make it simple for other drivers, the throttle code has been put in
> >> separate files.
> >>
> >> v1 -> v2:
> >>
> >> -Fixed FsContext redeclaration issue
> >> -Removed couple of function declarations from 9p-throttle.h
> >> -Fixed some of the .help messages
> >>
> >> v2 -> v3:
> >>
> >> -Addressed follwing comments by Claudio Fontana
> >>  -Removed redundant memset calls in fsdev_throttle_configure_iolimits function
> >>  -Checking throttle structure validity before initializing other structures
> >>   in fsdev_throttle_configure_iolimits
> >>
> >> -Addressed following comments by Greg Kurz
> >>  -Moved the code from 9pfs directory to fsdev directory, because the throttling
> >>   is for the fsdev devices.Renamed the files and functions to fsdev_ from 9pfs_
> >>  -Renamed throttling cli options to throttling.*, as in QMP cli options
> >>  -Removed some of the unwanted .h files from qemu-fsdev-throttle.[ch]
> >>  -Using throttle_enabled() function to set the thottle enabled flag for fsdev.
> >>
> >> v3 -> v4:
> >>
> >> -Addressed following comments by Alberto Garcia
> >>  -Removed the unwanted locking and other data structures in qemu-fsdev-throttle.[ch]
> >>
> >> -Addressed following comments by Greg Kurz
> >>  -Removed fsdev_iolimitsenable/disable functions, instead using throttle_enabled function
> >>
> >> v4 -> V5:
> >>  -Fixed the issue with the larger block size accounting.
> >>  (i.e, when the 9pfs mounted using msize=xxx option)
> >>
> >> V5 -> V6:
> >> -Addressed the comments by Alberto Garcia
> >>  -Removed the fsdev_throttle_timer_cb()
> >>  -Simplified the  fsdev_throttle_schedule_next_request() as suggested
> >>
> >> V6 -> V7:
> >> -Addressed the comments by Alberto Garcia
> >>  -changed the  fsdev_throttle_schedule_next_request() as suggested
> >>
> >> v7 -> v8:
> >> -Addressed comments by Alberto Garcia
> >>  -Fixed some indentation issues and split the configure_io_limit function
> >>  -Inlined throttle_timer_check code
> >>
> >> V8 -> v9:
> >> -Addressed the comments by Greg Kurz
> >>  -Inlined the fsdev_throttle_schedule_next_request() code into
> >>   fsdev_co_throttle_request ()
> >>
> >> v9 -> v10:
> >> -Addressed the comments by alberto garcia
> >>  -fixed the indentation issues and minor issues
> >>
> >> v10 -> v11:
> >> -Addressed the comments by alberto garcia
> >>  -renamed err variable to errp issues
> >>
> >>
> >> diff --git a/fsdev/Makefile.objs b/fsdev/Makefile.objs
> >> index 1b120a4..659df6e 100644
> >> --- a/fsdev/Makefile.objs
> >> +++ b/fsdev/Makefile.objs
> >> @@ -5,7 +5,7 @@ common-obj-y = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o
> >>  else
> >>  common-obj-y = qemu-fsdev-dummy.o
> >>  endif
> >> -common-obj-y += qemu-fsdev-opts.o
> >> +common-obj-y += qemu-fsdev-opts.o qemu-fsdev-throttle.o
> >>
> >>  # Toplevel always builds this; targets without virtio will put it in
> >>  # common-obj-y
> >> diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
> >> index 6db9fea..33fe822 100644
> >> --- a/fsdev/file-op-9p.h
> >> +++ b/fsdev/file-op-9p.h
> >> @@ -17,6 +17,7 @@
> >>  #include <dirent.h>
> >>  #include <utime.h>
> >>  #include <sys/vfs.h>
> >> +#include "qemu-fsdev-throttle.h"
> >>
> >>  #define SM_LOCAL_MODE_BITS    0600
> >>  #define SM_LOCAL_DIR_MODE_BITS    0700
> >> @@ -74,6 +75,7 @@ typedef struct FsDriverEntry {
> >>      char *path;
> >>      int export_flags;
> >>      FileOperations *ops;
> >> +    FsThrottle fst;
> >>  } FsDriverEntry;
> >>
> >>  typedef struct FsContext
> >> @@ -83,6 +85,7 @@ typedef struct FsContext
> >>      int export_flags;
> >>      struct xattr_operations **xops;
> >>      struct extended_ops exops;
> >> +    FsThrottle *fst;
> >>      /* fs driver specific data */
> >>      void *private;
> >>  } FsContext;
> >> diff --git a/fsdev/qemu-fsdev-opts.c b/fsdev/qemu-fsdev-opts.c
> >> index 1dd8c7a..385423f0 100644
> >> --- a/fsdev/qemu-fsdev-opts.c
> >> +++ b/fsdev/qemu-fsdev-opts.c
> >> @@ -37,8 +37,83 @@ static QemuOptsList qemu_fsdev_opts = {
> >>          }, {
> >>              .name = "sock_fd",
> >>              .type = QEMU_OPT_NUMBER,
> >> +        }, {
> >> +            .name = "throttling.iops-total",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "limit total I/O operations per second",
> >> +        }, {
> >> +            .name = "throttling.iops-read",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "limit read operations per second",
> >> +        }, {
> >> +            .name = "throttling.iops-write",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "limit write operations per second",
> >> +        }, {
> >> +            .name = "throttling.bps-total",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "limit total bytes per second",
> >> +        }, {
> >> +            .name = "throttling.bps-read",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "limit read bytes per second",
> >> +        }, {
> >> +            .name = "throttling.bps-write",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "limit write bytes per second",
> >> +        }, {
> >> +            .name = "throttling.iops-total-max",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "I/O operations burst",
> >> +        }, {
> >> +            .name = "throttling.iops-read-max",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "I/O operations read burst",
> >> +        }, {
> >> +            .name = "throttling.iops-write-max",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "I/O operations write burst",
> >> +        }, {
> >> +            .name = "throttling.bps-total-max",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "total bytes burst",
> >> +        }, {
> >> +            .name = "throttling.bps-read-max",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "total bytes read burst",
> >> +        }, {
> >> +            .name = "throttling.bps-write-max",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "total bytes write burst",
> >> +        }, {
> >> +            .name = "throttling.iops-total-max-length",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "length of the iops-total-max burst period, in seconds",
> >> +        }, {
> >> +            .name = "throttling.iops-read-max-length",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "length of the iops-read-max burst period, in seconds",
> >> +        }, {
> >> +            .name = "throttling.iops-write-max-length",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "length of the iops-write-max burst period, in seconds",
> >> +        }, {
> >> +            .name = "throttling.bps-total-max-length",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "length of the bps-total-max burst period, in seconds",
> >> +        }, {
> >> +            .name = "throttling.bps-read-max-length",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "length of the bps-read-max burst period, in seconds",
> >> +        }, {
> >> +            .name = "throttling.bps-write-max-length",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "length of the bps-write-max burst period, in seconds",
> >> +        }, {
> >> +            .name = "throttling.iops-size",
> >> +            .type = QEMU_OPT_NUMBER,
> >> +            .help = "when limiting by iops max size of an I/O in bytes",
> >>          },
> >> -
> >>          { /*End of list */ }
> >>      },
> >>  };
> >> diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
> >> new file mode 100644
> >> index 0000000..193ad26
> >> --- /dev/null
> >> +++ b/fsdev/qemu-fsdev-throttle.c
> >> @@ -0,0 +1,117 @@
> >> +/*
> >> + * Fsdev Throttle
> >> + *
> >> + * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
> >> + *
> >> + * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
> >> + *
> >> + * This work is licensed under the terms of the GNU GPL, version 2 or
> >> + * (at your option) any later version.
> >> + *
> >> + * See the COPYING file in the top-level directory for details.
> >> + *
> >> + */
> >> +
> >> +#include "qemu/osdep.h"
> >> +#include "qemu/error-report.h"
> >> +#include "qemu-fsdev-throttle.h"
> >> +#include "qemu/iov.h"
> >> +
> >> +static void fsdev_throttle_read_timer_cb(void *opaque)
> >> +{
> >> +    FsThrottle *fst = opaque;
> >> +    qemu_co_enter_next(&fst->throttled_reqs[false]);
> >> +}
> >> +
> >> +static void fsdev_throttle_write_timer_cb(void *opaque)
> >> +{
> >> +    FsThrottle *fst = opaque;
> >> +    qemu_co_enter_next(&fst->throttled_reqs[true]);
> >> +}
> >> +
> >> +void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
> >> +{
> >> +    fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
> >> +        qemu_opt_get_number(opts, "throttling.bps-total", 0);
> >> +    fst->cfg.buckets[THROTTLE_BPS_READ].avg  =
> >> +        qemu_opt_get_number(opts, "throttling.bps-read", 0);
> >> +    fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
> >> +        qemu_opt_get_number(opts, "throttling.bps-write", 0);
> >> +    fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
> >> +        qemu_opt_get_number(opts, "throttling.iops-total", 0);
> >> +    fst->cfg.buckets[THROTTLE_OPS_READ].avg =
> >> +        qemu_opt_get_number(opts, "throttling.iops-read", 0);
> >> +    fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
> >> +        qemu_opt_get_number(opts, "throttling.iops-write", 0);
> >> +
> >> +    fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
> >> +        qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
> >> +    fst->cfg.buckets[THROTTLE_BPS_READ].max  =
> >> +        qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
> >> +    fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
> >> +        qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
> >> +    fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
> >> +        qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
> >> +    fst->cfg.buckets[THROTTLE_OPS_READ].max =
> >> +        qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
> >> +    fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
> >> +        qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
> >> +
> >> +    fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
> >> +        qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
> >> +    fst->cfg.buckets[THROTTLE_BPS_READ].burst_length  =
> >> +        qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
> >> +    fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
> >> +        qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
> >> +    fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
> >> +        qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
> >> +    fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
> >> +        qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
> >> +    fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
> >> +        qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
> >> +    fst->cfg.op_size =
> >> +        qemu_opt_get_number(opts, "throttling.iops-size", 0);
> >> +
> >> +    throttle_is_valid(&fst->cfg, errp);
> >> +}
> >> +
> >> +void fsdev_throttle_init(FsThrottle *fst)
> >> +{
> >> +    if (throttle_enabled(&fst->cfg)) {
> >> +        throttle_init(&fst->ts);
> >> +        throttle_timers_init(&fst->tt,
> >> +                             qemu_get_aio_context(),
> >> +                             QEMU_CLOCK_REALTIME,
> >> +                             fsdev_throttle_read_timer_cb,
> >> +                             fsdev_throttle_write_timer_cb,
> >> +                             fst);
> >> +        throttle_config(&fst->ts, &fst->tt, &fst->cfg);
> >> +        qemu_co_queue_init(&fst->throttled_reqs[0]);
> >> +        qemu_co_queue_init(&fst->throttled_reqs[1]);
> >> +    }
> >> +}
> >> +
> >> +void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
> >> +                                            struct iovec *iov, int iovcnt)
> >> +{
> >> +    if (throttle_enabled(&fst->cfg)) {
> >> +        if (throttle_schedule_timer(&fst->ts, &fst->tt, is_write) ||
> >> +            !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
> >> +            qemu_co_queue_wait(&fst->throttled_reqs[is_write]);
> >> +        }
> >> +
> >> +        throttle_account(&fst->ts, is_write, iov_size(iov, iovcnt));
> >> +
> >> +        if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
> >> +            !throttle_schedule_timer(&fst->ts, &fst->tt, is_write)) {
> >> +            qemu_co_queue_next(&fst->throttled_reqs[is_write]);
> >> +        }
> >> +    }
> >> +}
> >> +
> >> +void fsdev_throttle_cleanup(FsThrottle *fst)
> >> +{
> >> +    if (throttle_enabled(&fst->cfg)) {
> >> +        throttle_timers_destroy(&fst->tt);
> >> +    }
> >> +}
> >> diff --git a/fsdev/qemu-fsdev-throttle.h b/fsdev/qemu-fsdev-throttle.h
> >> new file mode 100644
> >> index 0000000..e418643
> >> --- /dev/null
> >> +++ b/fsdev/qemu-fsdev-throttle.h
> >> @@ -0,0 +1,39 @@
> >> +/*
> >> + * Fsdev Throttle
> >> + *
> >> + * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
> >> + *
> >> + * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
> >> + *
> >> + * This work is licensed under the terms of the GNU GPL, version 2 or
> >> + * (at your option) any later version.
> >> + *
> >> + * See the COPYING file in the top-level directory for details.
> >> + *
> >> + */
> >> +
> >> +#ifndef _FSDEV_THROTTLE_H
> >> +#define _FSDEV_THROTTLE_H
> >> +
> >> +#include "block/aio.h"
> >> +#include "qemu/main-loop.h"
> >> +#include "qemu/coroutine.h"
> >> +#include "qapi/error.h"
> >> +#include "qemu/throttle.h"
> >> +
> >> +typedef struct FsThrottle {
> >> +    ThrottleState ts;
> >> +    ThrottleTimers tt;
> >> +    ThrottleConfig cfg;
> >> +    CoQueue      throttled_reqs[2];
> >> +} FsThrottle;
> >> +
> >> +void fsdev_throttle_parse_opts(QemuOpts *, FsThrottle *, Error **);
> >> +
> >> +void fsdev_throttle_init(FsThrottle *);
> >> +
> >> +void coroutine_fn fsdev_co_throttle_request(FsThrottle *, bool ,
> >> +                                            struct iovec *, int);
> >> +
> >> +void fsdev_throttle_cleanup(FsThrottle *);
> >> +#endif /* _FSDEV_THROTTLE_H */
> >> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> >> index 845675e..828348d 100644
> >> --- a/hw/9pfs/9p-local.c
> >> +++ b/hw/9pfs/9p-local.c
> >> @@ -1209,6 +1209,7 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
> >>  {
> >>      const char *sec_model = qemu_opt_get(opts, "security_model");
> >>      const char *path = qemu_opt_get(opts, "path");
> >> +    Error *err = NULL;
> >>
> >>      if (!sec_model) {
> >>          error_report("Security model not specified, local fs needs security model");
> >> @@ -1237,6 +1238,13 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
> >>          error_report("fsdev: No path specified");
> >>          return -1;
> >>      }
> >> +
> >> +    fsdev_throttle_parse_opts(opts, &fse->fst, &err);
> >> +    if (err) {
> >> +        error_reportf_err(err, "Throttle configuration is not valid: ");
> >> +        return -1;
> >> +    }
> >> +
> >>      fse->path = g_strdup(path);
> >>
> >>      return 0;
> >> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> >> index e88cf25..8d46a91 100644
> >> --- a/hw/9pfs/9p.c
> >> +++ b/hw/9pfs/9p.c
> >> @@ -3506,6 +3506,10 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
> >>          error_setg(errp, "share path %s is not a directory", fse->path);
> >>          goto out;
> >>      }
> >> +
> >> +    s->ctx.fst = &fse->fst;
> >> +    fsdev_throttle_init(s->ctx.fst);
> >> +
> >>      v9fs_path_free(&path);
> >>
> >>      rc = 0;
> >> @@ -3520,6 +3524,7 @@ out:
> >>
> >>  void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
> >>  {
> >> +    fsdev_throttle_cleanup(s->ctx.fst);
> >>      g_free(s->ctx.fs_root);
> >>      g_free(s->tag);
> >>  }
> >> diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
> >> index 120e267..88791bc 100644
> >> --- a/hw/9pfs/cofile.c
> >> +++ b/hw/9pfs/cofile.c
> >> @@ -247,6 +247,7 @@ int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
> >>      if (v9fs_request_cancelled(pdu)) {
> >>          return -EINTR;
> >>      }
> >> +    fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
> >>      v9fs_co_run_in_worker(
> >>          {
> >>              err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
> >> @@ -266,6 +267,7 @@ int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
> >>      if (v9fs_request_cancelled(pdu)) {
> >>          return -EINTR;
> >>      }
> >> +    fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
> >>      v9fs_co_run_in_worker(
> >>          {
> >>              err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);  
> >  
> 

^ permalink raw reply

* [PATCH tip/core/rcu 1/7] list: Split list_add() debug checking into separate function
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

Right now, __list_add() code is repeated either in list.h or in
list_debug.c, but the only differences between the two versions
are the debug checks. This commit therefore extracts these debug
checks into a separate __list_add_valid() function and consolidates
__list_add(). Additionally this new __list_add_valid() function will stop
list manipulations if a corruption is detected, instead of allowing for
further corruption that may lead to even worse conditions.

This is slight refactoring of the same hardening done in PaX and Grsecurity.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 include/linux/list.h | 22 ++++++++++++++++------
 lib/list_debug.c     | 48 +++++++++++++++++++++++-------------------------
 2 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/include/linux/list.h b/include/linux/list.h
index 5809e9a2de5b..b6da9b1dce4d 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -28,27 +28,37 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
 	list->prev = list;
 }
 
+#ifdef CONFIG_DEBUG_LIST
+extern bool __list_add_valid(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next);
+#else
+static inline bool __list_add_valid(struct list_head *new,
+				struct list_head *prev,
+				struct list_head *next)
+{
+	return true;
+}
+#endif
+
 /*
  * Insert a new entry between two known consecutive entries.
  *
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-#ifndef CONFIG_DEBUG_LIST
 static inline void __list_add(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *next)
 {
+	if (!__list_add_valid(new, prev, next))
+		return;
+
 	next->prev = new;
 	new->next = next;
 	new->prev = prev;
 	WRITE_ONCE(prev->next, new);
 }
-#else
-extern void __list_add(struct list_head *new,
-			      struct list_head *prev,
-			      struct list_head *next);
-#endif
 
 /**
  * list_add - add a new entry
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 3859bf63561c..149dd57b583b 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -2,8 +2,7 @@
  * Copyright 2006, Red Hat, Inc., Dave Jones
  * Released under the General Public License (GPL).
  *
- * This file contains the linked list implementations for
- * DEBUG_LIST.
+ * This file contains the linked list validation for DEBUG_LIST.
  */
 
 #include <linux/export.h>
@@ -13,33 +12,32 @@
 #include <linux/rculist.h>
 
 /*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
+ * Check that the data structures for the list manipulations are reasonably
+ * valid. Failures here indicate memory corruption (and possibly an exploit
+ * attempt).
  */
 
-void __list_add(struct list_head *new,
-			      struct list_head *prev,
-			      struct list_head *next)
+bool __list_add_valid(struct list_head *new, struct list_head *prev,
+		      struct list_head *next)
 {
-	WARN(next->prev != prev,
-		"list_add corruption. next->prev should be "
-		"prev (%p), but was %p. (next=%p).\n",
-		prev, next->prev, next);
-	WARN(prev->next != next,
-		"list_add corruption. prev->next should be "
-		"next (%p), but was %p. (prev=%p).\n",
-		next, prev->next, prev);
-	WARN(new == prev || new == next,
-	     "list_add double add: new=%p, prev=%p, next=%p.\n",
-	     new, prev, next);
-	next->prev = new;
-	new->next = next;
-	new->prev = prev;
-	WRITE_ONCE(prev->next, new);
+	if (unlikely(next->prev != prev)) {
+		WARN(1, "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
+			prev, next->prev, next);
+		return false;
+	}
+	if (unlikely(prev->next != next)) {
+		WARN(1, "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
+			next, prev->next, prev);
+		return false;
+	}
+	if (unlikely(new == prev || new == next)) {
+		WARN(1, "list_add double add: new=%p, prev=%p, next=%p.\n",
+			new, prev, next);
+		return false;
+	}
+	return true;
 }
-EXPORT_SYMBOL(__list_add);
+EXPORT_SYMBOL(__list_add_valid);
 
 void __list_del_entry(struct list_head *entry)
 {
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 2/7] rculist: Consolidate DEBUG_LIST for list_add_rcu()
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

This commit consolidates the debug checking for list_add_rcu() into the
new single __list_add_valid() debug function.  Notably, this commit fixes
the sanity check that was added in commit 17a801f4bfeb ("list_debug:
WARN for adding something already in the list"), which wasn't checking
RCU-protected lists.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 include/linux/rculist.h |  8 +++-----
 lib/list_debug.c        | 19 -------------------
 2 files changed, 3 insertions(+), 24 deletions(-)

diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 8beb98dcf14f..4f7a9561b8c4 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -45,19 +45,17 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-#ifndef CONFIG_DEBUG_LIST
 static inline void __list_add_rcu(struct list_head *new,
 		struct list_head *prev, struct list_head *next)
 {
+	if (!__list_add_valid(new, prev, next))
+		return;
+
 	new->next = next;
 	new->prev = prev;
 	rcu_assign_pointer(list_next_rcu(prev), new);
 	next->prev = new;
 }
-#else
-void __list_add_rcu(struct list_head *new,
-		    struct list_head *prev, struct list_head *next);
-#endif
 
 /**
  * list_add_rcu - add a new entry to rcu-protected list
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 149dd57b583b..d0b89b9d0736 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -77,22 +77,3 @@ void list_del(struct list_head *entry)
 	entry->prev = LIST_POISON2;
 }
 EXPORT_SYMBOL(list_del);
-
-/*
- * RCU variants.
- */
-void __list_add_rcu(struct list_head *new,
-		    struct list_head *prev, struct list_head *next)
-{
-	WARN(next->prev != prev,
-		"list_add_rcu corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
-		prev, next->prev, next);
-	WARN(prev->next != next,
-		"list_add_rcu corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
-		next, prev->next, prev);
-	new->next = next;
-	new->prev = prev;
-	rcu_assign_pointer(list_next_rcu(prev), new);
-	next->prev = new;
-}
-EXPORT_SYMBOL(__list_add_rcu);
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 3/7] list: Split list_del() debug checking into separate function
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

Similar to the list_add() debug consolidation, this commit consolidates
the debug checking performed during CONFIG_DEBUG_LIST into a new
__list_del_entry_valid() function, and stops list updates when corruption
is found.

Refactored from same hardening in PaX and Grsecurity.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 include/linux/list.h | 15 +++++++++------
 lib/list_debug.c     | 53 +++++++++++++++++++++++-----------------------------
 2 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/include/linux/list.h b/include/linux/list.h
index b6da9b1dce4d..d1039ecaf94f 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -32,6 +32,7 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
 extern bool __list_add_valid(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *next);
+extern bool __list_del_entry_valid(struct list_head *entry);
 #else
 static inline bool __list_add_valid(struct list_head *new,
 				struct list_head *prev,
@@ -39,6 +40,10 @@ static inline bool __list_add_valid(struct list_head *new,
 {
 	return true;
 }
+static inline bool __list_del_entry_valid(struct list_head *entry)
+{
+	return true;
+}
 #endif
 
 /*
@@ -106,22 +111,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
  * Note: list_empty() on entry does not return true after this, the entry is
  * in an undefined state.
  */
-#ifndef CONFIG_DEBUG_LIST
 static inline void __list_del_entry(struct list_head *entry)
 {
+	if (!__list_del_entry_valid(entry))
+		return;
+
 	__list_del(entry->prev, entry->next);
 }
 
 static inline void list_del(struct list_head *entry)
 {
-	__list_del(entry->prev, entry->next);
+	__list_del_entry(entry);
 	entry->next = LIST_POISON1;
 	entry->prev = LIST_POISON2;
 }
-#else
-extern void __list_del_entry(struct list_head *entry);
-extern void list_del(struct list_head *entry);
-#endif
 
 /**
  * list_replace - replace old entry by new one
diff --git a/lib/list_debug.c b/lib/list_debug.c
index d0b89b9d0736..276565fca2a6 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -39,41 +39,34 @@ bool __list_add_valid(struct list_head *new, struct list_head *prev,
 }
 EXPORT_SYMBOL(__list_add_valid);
 
-void __list_del_entry(struct list_head *entry)
+bool __list_del_entry_valid(struct list_head *entry)
 {
 	struct list_head *prev, *next;
 
 	prev = entry->prev;
 	next = entry->next;
 
-	if (WARN(next == LIST_POISON1,
-		"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
-		entry, LIST_POISON1) ||
-	    WARN(prev == LIST_POISON2,
-		"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
-		entry, LIST_POISON2) ||
-	    WARN(prev->next != entry,
-		"list_del corruption. prev->next should be %p, "
-		"but was %p\n", entry, prev->next) ||
-	    WARN(next->prev != entry,
-		"list_del corruption. next->prev should be %p, "
-		"but was %p\n", entry, next->prev))
-		return;
-
-	__list_del(prev, next);
-}
-EXPORT_SYMBOL(__list_del_entry);
+	if (unlikely(next == LIST_POISON1)) {
+		WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
+			entry, LIST_POISON1);
+		return false;
+	}
+	if (unlikely(prev == LIST_POISON2)) {
+		WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
+			entry, LIST_POISON2);
+		return false;
+	}
+	if (unlikely(prev->next != entry)) {
+		WARN(1, "list_del corruption. prev->next should be %p, but was %p\n",
+			entry, prev->next);
+		return false;
+	}
+	if (unlikely(next->prev != entry)) {
+		WARN(1, "list_del corruption. next->prev should be %p, but was %p\n",
+			entry, next->prev);
+		return false;
+	}
+	return true;
 
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
- * in an undefined state.
- */
-void list_del(struct list_head *entry)
-{
-	__list_del_entry(entry);
-	entry->next = LIST_POISON1;
-	entry->prev = LIST_POISON2;
 }
-EXPORT_SYMBOL(list_del);
+EXPORT_SYMBOL(__list_del_entry_valid);
-- 
2.5.2

^ permalink raw reply related

* [Buildroot] [PATCH] toolchain: Bump ARC tools to arc-2016.09-rc1
From: Vlad Zakharov @ 2016-11-14 17:56 UTC (permalink / raw)
  To: buildroot

As described at:
4520524ba055706236db9f00dd79f1b2e2e87fde
this commit continues a series of updates of ARC tools.
This time we're updating tools to arc-2016.09-rc1.

This update contains a lot of important fixes, e.g. it fixes:
http://autobuild.buildroot.net/results/4c7/4c77f33c842b37bf28cb931edf1b290e1bf4d93c//
http://autobuild.buildroot.net/results/902/902729a0b98675ad803939e3ecdcf230065a6012//
and other failures.

Other important change is that we also update gdb. Now we are
using gdb 7.12.

This version of gdb requires C++ toolchain support so we add
corresponding dependency to gdb Config.in file.

Signed-off-by: Vlad Zakharov <vzakhar@synopsys.com>
---
 package/binutils/Config.in.host                                         | 2 +-
 .../{arc-2016.09-eng015 => arc-2016.09-rc1}/0300-ld-makefile.patch      | 0
 .../0301-check-ldrunpath-length.patch                                   | 0
 .../0500-add-sysroot-fix-from-bug-3049.patch                            | 0
 .../0600-poison-system-directories.patch                                | 0
 package/binutils/binutils.hash                                          | 2 +-
 package/binutils/binutils.mk                                            | 2 +-
 package/gcc/Config.in.host                                              | 2 +-
 .../301-missing-execinfo_h.patch                                        | 0
 .../gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/860-cilk-wchar.patch    | 0
 .../940-uclinux-enable-threads.patch                                    | 0
 package/gcc/gcc.hash                                                    | 2 +-
 package/gdb/Config.in                                                   | 2 ++
 package/gdb/Config.in.host                                              | 2 +-
 package/gdb/gdb.hash                                                    | 2 +-
 15 files changed, 9 insertions(+), 7 deletions(-)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0300-ld-makefile.patch (100%)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0301-check-ldrunpath-length.patch (100%)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0500-add-sysroot-fix-from-bug-3049.patch (100%)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0600-poison-system-directories.patch (100%)
 rename package/gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/301-missing-execinfo_h.patch (100%)
 rename package/gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/860-cilk-wchar.patch (100%)
 rename package/gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/940-uclinux-enable-threads.patch (100%)

diff --git a/package/binutils/Config.in.host b/package/binutils/Config.in.host
index 3e0c357..af9339e 100644
--- a/package/binutils/Config.in.host
+++ b/package/binutils/Config.in.host
@@ -22,7 +22,7 @@ endchoice
 
 config BR2_BINUTILS_VERSION
 	string
-	default "arc-2016.09-eng015"	if BR2_arc
+	default "arc-2016.09-rc1"	if BR2_arc
 	default "2.25.1"	if BR2_BINUTILS_VERSION_2_25_X
 	default "2.26.1"	if BR2_BINUTILS_VERSION_2_26_X
 	default "2.27"		if BR2_BINUTILS_VERSION_2_27_X
diff --git a/package/binutils/arc-2016.09-eng015/0300-ld-makefile.patch b/package/binutils/arc-2016.09-rc1/0300-ld-makefile.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0300-ld-makefile.patch
rename to package/binutils/arc-2016.09-rc1/0300-ld-makefile.patch
diff --git a/package/binutils/arc-2016.09-eng015/0301-check-ldrunpath-length.patch b/package/binutils/arc-2016.09-rc1/0301-check-ldrunpath-length.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0301-check-ldrunpath-length.patch
rename to package/binutils/arc-2016.09-rc1/0301-check-ldrunpath-length.patch
diff --git a/package/binutils/arc-2016.09-eng015/0500-add-sysroot-fix-from-bug-3049.patch b/package/binutils/arc-2016.09-rc1/0500-add-sysroot-fix-from-bug-3049.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0500-add-sysroot-fix-from-bug-3049.patch
rename to package/binutils/arc-2016.09-rc1/0500-add-sysroot-fix-from-bug-3049.patch
diff --git a/package/binutils/arc-2016.09-eng015/0600-poison-system-directories.patch b/package/binutils/arc-2016.09-rc1/0600-poison-system-directories.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0600-poison-system-directories.patch
rename to package/binutils/arc-2016.09-rc1/0600-poison-system-directories.patch
diff --git a/package/binutils/binutils.hash b/package/binutils/binutils.hash
index f41b39b..80ac9dd 100644
--- a/package/binutils/binutils.hash
+++ b/package/binutils/binutils.hash
@@ -5,4 +5,4 @@ sha512  9d9165609fd3b0f20d616f9891fc8e2b466eb13e2bfce40125e12427f8f201d20e2b8322
 sha512	cf276f84935312361a2ca077e04d0b469d23a3aed979d8ba5d92ea590904ffb2c2e7ed12cc842822bfc402836be86f479660cef3791aa62f3753d8a1a6f564cb  binutils-2.27.tar.bz2
 
 # Locally calculated (fetched from Github)
-sha512  f8cc7529fbe3cb52b666b92e1353063a8a36ea07fa8c5aa8359252f4222feaed15253b6a137033c74dabc0ae784daf8a7978e69ebdb8bf8cd6b8bb61c84bf181  binutils-arc-2016.09-eng015.tar.gz
+sha512  d0befdeb0a7b76efd1ad655fc062cde2aa67be7b26210c913ab2709e069d815c4ff2863ce7add1f6434da5a2f4faf1ce5a5bc3d0e64f3e04548a7479f24edcbc  binutils-arc-2016.09-rc1.tar.gz
diff --git a/package/binutils/binutils.mk b/package/binutils/binutils.mk
index ca481d2..61486a2 100644
--- a/package/binutils/binutils.mk
+++ b/package/binutils/binutils.mk
@@ -9,7 +9,7 @@
 BINUTILS_VERSION = $(call qstrip,$(BR2_BINUTILS_VERSION))
 ifeq ($(BINUTILS_VERSION),)
 ifeq ($(BR2_arc),y)
-BINUTILS_VERSION = arc-2016.09-eng015
+BINUTILS_VERSION = arc-2016.09-rc1
 else
 BINUTILS_VERSION = 2.25.1
 endif
diff --git a/package/gcc/Config.in.host b/package/gcc/Config.in.host
index 0a63e6a..d10798b 100644
--- a/package/gcc/Config.in.host
+++ b/package/gcc/Config.in.host
@@ -98,7 +98,7 @@ config BR2_GCC_VERSION
 	default "4.9.4"     if BR2_GCC_VERSION_4_9_X
 	default "5.4.0"     if BR2_GCC_VERSION_5_X
 	default "6.2.0"     if BR2_GCC_VERSION_6_X
-	default "arc-2016.09-eng015" if BR2_GCC_VERSION_ARC
+	default "arc-2016.09-rc1" if BR2_GCC_VERSION_ARC
 
 config BR2_EXTRA_GCC_CONFIG_OPTIONS
 	string "Additional gcc options"
diff --git a/package/gcc/arc-2016.09-eng015/301-missing-execinfo_h.patch b/package/gcc/arc-2016.09-rc1/301-missing-execinfo_h.patch
similarity index 100%
rename from package/gcc/arc-2016.09-eng015/301-missing-execinfo_h.patch
rename to package/gcc/arc-2016.09-rc1/301-missing-execinfo_h.patch
diff --git a/package/gcc/arc-2016.09-eng015/860-cilk-wchar.patch b/package/gcc/arc-2016.09-rc1/860-cilk-wchar.patch
similarity index 100%
rename from package/gcc/arc-2016.09-eng015/860-cilk-wchar.patch
rename to package/gcc/arc-2016.09-rc1/860-cilk-wchar.patch
diff --git a/package/gcc/arc-2016.09-eng015/940-uclinux-enable-threads.patch b/package/gcc/arc-2016.09-rc1/940-uclinux-enable-threads.patch
similarity index 100%
rename from package/gcc/arc-2016.09-eng015/940-uclinux-enable-threads.patch
rename to package/gcc/arc-2016.09-rc1/940-uclinux-enable-threads.patch
diff --git a/package/gcc/gcc.hash b/package/gcc/gcc.hash
index ce738ef..e5d96f4 100644
--- a/package/gcc/gcc.hash
+++ b/package/gcc/gcc.hash
@@ -12,4 +12,4 @@ sha512  2941cc950c8f2409a314df497631f9b0266211aa74746c1839c46e04f1c7c299afe2528d
 sha512  1e8b826a3d44b9d5899309894e20c03abeb352bf3d273b8ad63af814c0ee2911f1a83ce1cd4cdd2d1cb0b3e3c34e9b7ae1b2ab83dfc649ee817ab05247c76198  gcc-6.2.0.tar.bz2
 
 # Locally calculated (fetched from Github)
-sha512  9f365452f746ae91875d935c2ec5ed16cd11a2973f69bd23193fec9fc6b557e0dd66bb169e7efb7ec63fd78af36139005abcf5a5a1d89d6f49788b2ed7b334fb  gcc-arc-2016.09-eng015.tar.gz
+sha512  7029d7ae1316b9385880f32283aa6c4979b1257500bb21e3fb234475ecb20082f46b114d8b7022c75a8dcf0c0c7b6b02e9384b49dd3189adc3d454502b8b0c26  gcc-arc-2016.09-rc1.tar.gz
diff --git a/package/gdb/Config.in b/package/gdb/Config.in
index 809e02d..e025fe0 100644
--- a/package/gdb/Config.in
+++ b/package/gdb/Config.in
@@ -11,6 +11,8 @@ config BR2_PACKAGE_GDB
 		(!BR2_PACKAGE_GDB_DEBUGGER && !BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY)
 	depends on BR2_TOOLCHAIN_HAS_THREADS && BR2_TOOLCHAIN_HAS_THREADS_DEBUG
 	depends on !BR2_nios2 && !BR2_bfin
+	# Since ARC gdb moved to 7.12 toolchain requires C++ support to build gdb.
+	depends on !BR2_arc || BR2_TOOLCHAIN_BUILDROOT_CXX
 	help
 	  GDB, the GNU Project debugger, allows you to see what is
 	  going on `inside' another program while it executes -- or
diff --git a/package/gdb/Config.in.host b/package/gdb/Config.in.host
index a36dc0f..b6eb41f 100644
--- a/package/gdb/Config.in.host
+++ b/package/gdb/Config.in.host
@@ -56,7 +56,7 @@ endif
 config BR2_GDB_VERSION
 	string
 	depends on BR2_PACKAGE_GDB || BR2_PACKAGE_HOST_GDB
-	default "arc-2016.03-gdb" if BR2_arc
+	default "arc-2016.09-rc1-gdb" if BR2_arc
 	default "6be65fb56ea6694a9260733a536a023a1e2d4d57" if BR2_microblaze
 	default "7.9.1"    if BR2_GDB_VERSION_7_9
 	default "7.10.1"   if BR2_GDB_VERSION_7_10 || !BR2_PACKAGE_HOST_GDB
diff --git a/package/gdb/gdb.hash b/package/gdb/gdb.hash
index 611a75c..8c0d51b 100644
--- a/package/gdb/gdb.hash
+++ b/package/gdb/gdb.hash
@@ -5,4 +5,4 @@ sha512  f80ec6c8a0f0b54c8b945666e875809174402b7e121efb378ebac931a91f9a1cc0048568
 
 # Locally calculated (fetched from Github)
 sha512  0a467091d4b01fbecabb4b8da1cb743025c70e7f4874a0b5c8fa2ec623569a39bde6762b91806de0be6e63711aeb6909715cfbe43860de73d8aec6159a9f10a7	gdb-6be65fb56ea6694a9260733a536a023a1e2d4d57.tar.gz
-sha512  1abef1357896c2b57cfa7f7414eedc49d0de26b54321c680c2d027b1a27ec453d421e7f89a5281336047542379fd4820685802059efbd32b87c5ccffbaf2bd16	gdb-arc-2016.03-gdb.tar.gz
+sha512  e6019ac0d6b1354943d3c06c84f353ba49fef105b07c1a04ad90cc5b65f91e38fe6c671e0c34a9541ee282d0f42cf24579c011a0469d19faaa4d00d64a17afe2	gdb-arc-2016.09-rc1-gdb.tar.gz
-- 
2.6.3

^ permalink raw reply related

* Re: [SPDK] RoCE Version
From: Alex Bowden @ 2016-11-14 17:56 UTC (permalink / raw)
  To: spdk

[-- Attachment #1: Type: text/plain, Size: 723 bytes --]

No. It supports RoCE v1. It supports any RDMA interface that provides a verbs device to the userspace library libibverbs/librdmacm.

On Tue, Nov 8, 2016 at 12:35 PM, Kumaraparameshwaran Rathnavel <krath(a)cloudsimple.com<mailto:krath(a)cloudsimple.com>> wrote:
Hi All,

I think that NVMe userspace target is supported in all RDMA forms. Basically the RoCE version 1 & 2, iWARP. So the config file has Listen RDMA and a IP address. So does this mean that it does not support RoCE version 1? As RoCE version 1 is in Ethernet Layer.

Thanking You,
Param
_______________________________________________
SPDK mailing list
SPDK(a)lists.01.org<mailto:SPDK(a)lists.01.org>
https://lists.01.org/mailman/listinfo/spdk


[-- Attachment #2: attachment.html --]
[-- Type: text/html, Size: 1269 bytes --]

^ permalink raw reply

* [PATCH tip/core/rcu 6/7] lib/Kconfig.debug: Fix typo in select statement
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Valentin Rothberg, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Valentin Rothberg <valentinrothberg@gmail.com>

Commit 484f29c7430b3 ("bug: Provide toggle for BUG on data corruption")
added a Kconfig select statement on CONFIG_DEBUG_LIST, but the CONFIG_
prefix is only used in Make and C(PP) syntax.  Remove the CONFIG_ prefix
to correctly select the Kconfig option DEBUG_LIST.

Signed-off-by: Valentin Rothberg <valentinrothberg@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Kees Cook <keescook@chromium.org>
---
 lib/Kconfig.debug | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 07a6fac930c5..afa30fd52583 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1962,7 +1962,7 @@ config TEST_STATIC_KEYS
 
 config BUG_ON_DATA_CORRUPTION
 	bool "Trigger a BUG when data corruption is detected"
-	select CONFIG_DEBUG_LIST
+	select DEBUG_LIST
 	help
 	  Select this option if the kernel should BUG when it encounters
 	  data corruption in kernel memory structures when they get checked
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 5/7] lkdtm: Add tests for struct list corruption
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

When building under CONFIG_DEBUG_LIST, list addition and removal will be
sanity-checked. This validates that the check is working as expected by
setting up classic corruption attacks against list manipulations, available
with the new lkdtm tests CORRUPT_LIST_ADD and CORRUPT_LIST_DEL.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 drivers/misc/lkdtm.h      |  2 ++
 drivers/misc/lkdtm_bugs.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/misc/lkdtm_core.c |  2 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index fdf954c2107f..cfa1039c62e7 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void);
 void lkdtm_HUNG_TASK(void);
 void lkdtm_ATOMIC_UNDERFLOW(void);
 void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_CORRUPT_LIST_ADD(void);
+void lkdtm_CORRUPT_LIST_DEL(void);
 
 /* lkdtm_heap.c */
 void lkdtm_OVERWRITE_ALLOCATION(void);
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 182ae1894b32..f336206d4b1f 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -5,8 +5,13 @@
  * test source files.
  */
 #include "lkdtm.h"
+#include <linux/list.h>
 #include <linux/sched.h>
 
+struct lkdtm_list {
+	struct list_head node;
+};
+
 /*
  * Make sure our attempts to over run the kernel stack doesn't trigger
  * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -146,3 +151,66 @@ void lkdtm_ATOMIC_OVERFLOW(void)
 	pr_info("attempting bad atomic overflow\n");
 	atomic_inc(&over);
 }
+
+void lkdtm_CORRUPT_LIST_ADD(void)
+{
+	/*
+	 * Initially, an empty list via LIST_HEAD:
+	 *	test_head.next = &test_head
+	 *	test_head.prev = &test_head
+	 */
+	LIST_HEAD(test_head);
+	struct lkdtm_list good, bad;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	pr_info("attempting good list addition\n");
+
+	/*
+	 * Adding to the list performs these actions:
+	 *	test_head.next->prev = &good.node
+	 *	good.node.next = test_head.next
+	 *	good.node.prev = test_head
+	 *	test_head.next = good.node
+	 */
+	list_add(&good.node, &test_head);
+
+	pr_info("attempting corrupted list addition\n");
+	/*
+	 * In simulating this "write what where" primitive, the "what" is
+	 * the address of &bad.node, and the "where" is the address held
+	 * by "redirection".
+	 */
+	test_head.next = redirection;
+	list_add(&bad.node, &test_head);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_add() corruption not detected!\n");
+}
+
+void lkdtm_CORRUPT_LIST_DEL(void)
+{
+	LIST_HEAD(test_head);
+	struct lkdtm_list item;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	list_add(&item.node, &test_head);
+
+	pr_info("attempting good list removal\n");
+	list_del(&item.node);
+
+	pr_info("attempting corrupted list removal\n");
+	list_add(&item.node, &test_head);
+
+	/* As with the list_add() test above, this corrupts "next". */
+	item.node.next = redirection;
+	list_del(&item.node);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_del() corruption not detected!\n");
+}
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index f9154b8d67f6..7eeb71a75549 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -197,6 +197,8 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(EXCEPTION),
 	CRASHTYPE(LOOP),
 	CRASHTYPE(OVERFLOW),
+	CRASHTYPE(CORRUPT_LIST_ADD),
+	CRASHTYPE(CORRUPT_LIST_DEL),
 	CRASHTYPE(CORRUPT_STACK),
 	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
 	CRASHTYPE(OVERWRITE_ALLOCATION),
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 4/7] bug: Provide toggle for BUG on data corruption
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

The kernel checks for cases of data structure corruption under some
CONFIGs (e.g. CONFIG_DEBUG_LIST). When corruption is detected, some
systems may want to BUG() immediately instead of letting the system run
with known corruption.  Usually these kinds of manipulation primitives can
be used by security flaws to gain arbitrary memory write control. This
provides a new config CONFIG_BUG_ON_DATA_CORRUPTION and a corresponding
macro CHECK_DATA_CORRUPTION for handling these situations. Notably, even
if not BUGing, the kernel should not continue processing the corrupted
structure.

This is inspired by similar hardening by Syed Rameez Mustafa in MSM
kernels, and in PaX and Grsecurity, which is likely in response to earlier
removal of the BUG calls in commit 924d9addb9b1 ("list debugging: use
WARN() instead of BUG()").

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 include/linux/bug.h | 17 ++++++++++++++++
 lib/Kconfig.debug   | 10 ++++++++++
 lib/list_debug.c    | 57 +++++++++++++++++++++--------------------------------
 3 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/include/linux/bug.h b/include/linux/bug.h
index 292d6a10b0c2..baff2e8fc8a8 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -121,4 +121,21 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
 }
 
 #endif	/* CONFIG_GENERIC_BUG */
+
+/*
+ * Since detected data corruption should stop operation on the affected
+ * structures, this returns false if the corruption condition is found.
+ */
+#define CHECK_DATA_CORRUPTION(condition, fmt, ...)			 \
+	do {								 \
+		if (unlikely(condition)) {				 \
+			if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
+				pr_err(fmt, ##__VA_ARGS__);		 \
+				BUG();					 \
+			} else						 \
+				WARN(1, fmt, ##__VA_ARGS__);		 \
+			return false;					 \
+		}							 \
+	} while (0)
+
 #endif	/* _LINUX_BUG_H */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 33bc56cf60d7..07a6fac930c5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1960,6 +1960,16 @@ config TEST_STATIC_KEYS
 
 	  If unsure, say N.
 
+config BUG_ON_DATA_CORRUPTION
+	bool "Trigger a BUG when data corruption is detected"
+	select CONFIG_DEBUG_LIST
+	help
+	  Select this option if the kernel should BUG when it encounters
+	  data corruption in kernel memory structures when they get checked
+	  for validity.
+
+	  If unsure, say N.
+
 source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 276565fca2a6..7f7bfa55eb6d 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -20,21 +20,16 @@
 bool __list_add_valid(struct list_head *new, struct list_head *prev,
 		      struct list_head *next)
 {
-	if (unlikely(next->prev != prev)) {
-		WARN(1, "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
-			prev, next->prev, next);
-		return false;
-	}
-	if (unlikely(prev->next != next)) {
-		WARN(1, "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
-			next, prev->next, prev);
-		return false;
-	}
-	if (unlikely(new == prev || new == next)) {
-		WARN(1, "list_add double add: new=%p, prev=%p, next=%p.\n",
-			new, prev, next);
-		return false;
-	}
+	CHECK_DATA_CORRUPTION(next->prev != prev,
+		"list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
+		prev, next->prev, next);
+	CHECK_DATA_CORRUPTION(prev->next != next,
+		"list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
+		next, prev->next, prev);
+	CHECK_DATA_CORRUPTION(new == prev || new == next,
+		"list_add double add: new=%p, prev=%p, next=%p.\n",
+		new, prev, next);
+
 	return true;
 }
 EXPORT_SYMBOL(__list_add_valid);
@@ -46,26 +41,18 @@ bool __list_del_entry_valid(struct list_head *entry)
 	prev = entry->prev;
 	next = entry->next;
 
-	if (unlikely(next == LIST_POISON1)) {
-		WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
-			entry, LIST_POISON1);
-		return false;
-	}
-	if (unlikely(prev == LIST_POISON2)) {
-		WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
-			entry, LIST_POISON2);
-		return false;
-	}
-	if (unlikely(prev->next != entry)) {
-		WARN(1, "list_del corruption. prev->next should be %p, but was %p\n",
-			entry, prev->next);
-		return false;
-	}
-	if (unlikely(next->prev != entry)) {
-		WARN(1, "list_del corruption. next->prev should be %p, but was %p\n",
-			entry, next->prev);
-		return false;
-	}
+	CHECK_DATA_CORRUPTION(next == LIST_POISON1,
+		"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
+		entry, LIST_POISON1);
+	CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
+		"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
+		entry, LIST_POISON2);
+	CHECK_DATA_CORRUPTION(prev->next != entry,
+		"list_del corruption. prev->next should be %p, but was %p\n",
+		entry, prev->next);
+	CHECK_DATA_CORRUPTION(next->prev != entry,
+		"list_del corruption. next->prev should be %p, but was %p\n",
+		entry, next->prev);
 	return true;
 
 }
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 7/7] bug: Avoid Kconfig warning for BUG_ON_DATA_CORRUPTION
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Arnd Bergmann, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Arnd Bergmann <arnd@arndb.de>

The CONFIG_DEBUG_LIST option is normally meant for kernel developers
rather than production machines and is guarded by CONFIG_DEBUG_KERNEL.

In contrast, the newly added CONFIG_BUG_ON_DATA_CORRUPTION is meant
for security hardening and may be used on systems that intentionally
do not enable CONFIG_DEBUG_KERNEL. In this configuration, we get
a warning from Kconfig about the mismatched dependencies:

warning: (BUG_ON_DATA_CORRUPTION) selects DEBUG_LIST which has unmet direct dependencies (DEBUG_KERNEL)

This annotates the DEBUG_LIST option to be selectable by
BUG_ON_DATA_CORRUPTION when DEBUG_KERNEL is disabled.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Fixes: 40cd725cfc7f ("bug: Provide toggle for BUG on data corruption")
Acked-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 lib/Kconfig.debug | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index afa30fd52583..0c6366b77062 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1214,7 +1214,7 @@ config DEBUG_BUGVERBOSE
 
 config DEBUG_LIST
 	bool "Debug linked list manipulation"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL || BUG_ON_DATA_CORRUPTION
 	help
 	  Enable this to turn on extended checks in the linked-list
 	  walking routines.
-- 
2.5.2

^ permalink raw reply related

* [PATCH 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver
From: Akshay Bhat @ 2016-11-14 17:55 UTC (permalink / raw)
  To: wg, mkl, robh+dt
  Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
	Akshay Bhat, Akshay Bhat
In-Reply-To: <1479146144-29143-1-git-send-email-akshay.bhat@timesys.com>

This patch adds support for the Holt HI-311x CAN controller. The HI311x
CAN controller is capable of transmitting and receiving standard data
frames, extended data frames and remote frames. The HI311x interfaces
with the host over SPI.

Datasheet: www.holtic.com/documents/371-hi-3110_v-rev-jpdf.do

Signed-off-by: Akshay Bhat <nodeax@gmail.com>
---
 drivers/net/can/spi/Kconfig  |    6 +
 drivers/net/can/spi/Makefile |    1 +
 drivers/net/can/spi/hi311x.c | 1071 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1078 insertions(+)
 create mode 100644 drivers/net/can/spi/hi311x.c

diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig
index 148cae5..9eb1bb1 100644
--- a/drivers/net/can/spi/Kconfig
+++ b/drivers/net/can/spi/Kconfig
@@ -7,4 +7,10 @@ config CAN_MCP251X
 	---help---
 	  Driver for the Microchip MCP251x SPI CAN controllers.
 
+config CAN_HI311X
+	tristate "Holt HI311x SPI CAN controllers"
+	depends on CAN_DEV && SPI && HAS_DMA
+	---help---
+	  Driver for the Holt HI311x SPI CAN controllers.
+
 endmenu
diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile
index 0e86040..eac7c3a 100644
--- a/drivers/net/can/spi/Makefile
+++ b/drivers/net/can/spi/Makefile
@@ -4,3 +4,4 @@
 
 
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
+obj-$(CONFIG_CAN_HI311X)	+= hi311x.o
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
new file mode 100644
index 0000000..1020166
--- /dev/null
+++ b/drivers/net/can/spi/hi311x.c
@@ -0,0 +1,1071 @@
+/* CAN bus driver for Holt HI3110 CAN Controller with SPI Interface
+ *
+ * Based on Microchip 251x CAN Controller (mcp251x) Linux kernel driver
+ *
+ * Copyright(C) Timesys Corporation 2016
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/can/led.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/freezer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/uaccess.h>
+
+#define HI3110_MASTER_RESET        0x56
+#define HI3110_READ_CTRL0          0xD2
+#define HI3110_READ_CTRL1          0xD4
+#define HI3110_READ_STATF          0xE2
+#define HI3110_WRITE_CTRL0         0x14
+#define HI3110_WRITE_CTRL1         0x16
+#define HI3110_WRITE_INTE          0x1C
+#define HI3110_WRITE_BTR0          0x18
+#define HI3110_WRITE_BTR1          0x1A
+#define HI3110_READ_BTR0           0xD6
+#define HI3110_READ_BTR1           0xD8
+#define HI3110_READ_INTF           0xDE
+#define HI3110_READ_ERR            0xDC
+#define HI3110_READ_FIFO_WOTIME    0x48
+#define HI3110_WRITE_FIFO          0x12
+#define HI3110_READ_MESSTAT        0xDA
+#define HI3110_READ_TEC            0xEC
+
+#define HI3110_CTRL0_MODE_MASK     (7 << 5)
+#define HI3110_CTRL0_NORMAL_MODE   (0 << 5)
+#define HI3110_CTRL0_LOOPBACK_MODE (1 << 5)
+#define HI3110_CTRL0_MONITOR_MODE  (2 << 5)
+#define HI3110_CTRL0_SLEEP_MODE    (3 << 5)
+#define HI3110_CTRL0_INIT_MODE     (4 << 5)
+
+#define HI3110_CTRL1_TXEN          BIT(7)
+
+#define HI3110_INT_RXTMP           BIT(7)
+#define HI3110_INT_RXFIFO          BIT(6)
+#define HI3110_INT_TXCPLT          BIT(5)
+#define HI3110_INT_BUSERR          BIT(4)
+#define HI3110_INT_MCHG            BIT(3)
+#define HI3110_INT_WAKEUP          BIT(2)
+#define HI3110_INT_F1MESS          BIT(1)
+#define HI3110_INT_F0MESS          BIT(0)
+
+#define HI3110_ERR_BUSOFF          BIT(7)
+#define HI3110_ERR_TXERRP          BIT(6)
+#define HI3110_ERR_RXERRP          BIT(5)
+#define HI3110_ERR_BITERR          BIT(4)
+#define HI3110_ERR_FRMERR          BIT(3)
+#define HI3110_ERR_CRCERR          BIT(2)
+#define HI3110_ERR_ACKERR          BIT(1)
+#define HI3110_ERR_STUFERR         BIT(0)
+#define HI3110_ERR_PROTOCOL_MASK   (0x1F)
+
+#define HI3110_STAT_RXFMTY         BIT(1)
+
+#define HI3110_BTR0_SJW_SHIFT      6
+#define HI3110_BTR0_BRP_SHIFT      0
+
+#define HI3110_BTR1_SAMP_3PERBIT   (1 << 7)
+#define HI3110_BTR1_SAMP_1PERBIT   (0 << 7)
+#define HI3110_BTR1_TSEG2_SHIFT    4
+#define HI3110_BTR1_TSEG1_SHIFT    0
+
+#define HI3110_FIFO_WOTIME_TAG_OFF 0
+#define HI3110_FIFO_WOTIME_ID_OFF  1
+#define HI3110_FIFO_WOTIME_DLC_OFF 5
+#define HI3110_FIFO_WOTIME_DAT_OFF 6
+
+#define HI3110_FIFO_WOTIME_TAG_IDE BIT(7)
+#define HI3110_FIFO_WOTIME_ID_RTR  BIT(0)
+
+#define HI3110_FIFO_TAG_OFF        0
+#define HI3110_FIFO_ID_OFF         1
+#define HI3110_FIFO_STD_DLC_OFF    3
+#define HI3110_FIFO_STD_DATA_OFF   4
+#define HI3110_FIFO_EXT_DLC_OFF    5
+#define HI3110_FIFO_EXT_DATA_OFF   6
+
+#define CAN_FRAME_MAX_DATA_LEN 8
+#define RX_BUF_LEN             15
+#define TX_STD_BUF_LEN         12
+#define TX_EXT_BUF_LEN         14
+#define CAN_FRAME_MAX_BITS     128
+
+#define TX_ECHO_SKB_MAX	1
+
+#define HI3110_OST_DELAY_MS (10)
+
+#define DEVICE_NAME "hi3110"
+
+static int hi3110_enable_dma = 1; /* Enable SPI DMA. Default: 1 (On) */
+module_param(hi3110_enable_dma, int, 0444);
+MODULE_PARM_DESC(hi3110_enable_dma, "Enable SPI DMA. Default: 1 (On)");
+
+static const struct can_bittiming_const hi3110_bittiming_const = {
+	.name = DEVICE_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 16,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+enum hi3110_model {
+	CAN_HI3110_HI3110	= 0x3110,
+};
+
+struct hi3110_priv {
+	struct can_priv	   can;
+	struct net_device *net;
+	struct spi_device *spi;
+	enum hi3110_model model;
+
+	struct mutex hi3110_lock; /* SPI device lock */
+
+	u8 *spi_tx_buf;
+	u8 *spi_rx_buf;
+	dma_addr_t spi_tx_dma;
+	dma_addr_t spi_rx_dma;
+
+	struct sk_buff *tx_skb;
+	int tx_len;
+
+	struct workqueue_struct *wq;
+	struct work_struct tx_work;
+	struct work_struct restart_work;
+
+	int force_quit;
+	int after_suspend;
+#define AFTER_SUSPEND_UP 1
+#define AFTER_SUSPEND_DOWN 2
+#define AFTER_SUSPEND_POWER 4
+#define AFTER_SUSPEND_RESTART 8
+	int restart_tx;
+	struct regulator *power;
+	struct regulator *transceiver;
+	struct clk *clk;
+};
+
+static void hi3110_clean(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+
+	if (priv->tx_skb || priv->tx_len)
+		net->stats.tx_errors++;
+	if (priv->tx_skb)
+		dev_kfree_skb(priv->tx_skb);
+	if (priv->tx_len)
+		can_free_echo_skb(priv->net, 0);
+	priv->tx_skb = NULL;
+	priv->tx_len = 0;
+}
+
+/* Note about handling of error return of hi3110_spi_trans: accessing
+ * registers via SPI is not really different conceptually than using
+ * normal I/O assembler instructions, although it's much more
+ * complicated from a practical POV. So it's not advisable to always
+ * check the return value of this function. Imagine that every
+ * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
+ * error();", it would be a great mess (well there are some situation
+ * when exception handling C++ like could be useful after all). So we
+ * just check that transfers are OK at the beginning of our
+ * conversation with the chip and to avoid doing really nasty things
+ * (like injecting bogus packets in the network stack).
+ */
+static int hi3110_spi_trans(struct spi_device *spi, int len)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct spi_transfer t = {
+		.tx_buf = priv->spi_tx_buf,
+		.rx_buf = priv->spi_rx_buf,
+		.len = len,
+		.cs_change = 0,
+	};
+	struct spi_message m;
+	int ret;
+
+	spi_message_init(&m);
+
+	if (hi3110_enable_dma) {
+		t.tx_dma = priv->spi_tx_dma;
+		t.rx_dma = priv->spi_rx_dma;
+		m.is_dma_mapped = 1;
+	}
+
+	spi_message_add_tail(&t, &m);
+
+	ret = spi_sync(spi, &m);
+
+	if (ret)
+		dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret);
+	return ret;
+}
+
+static u8 hi3110_cmd(struct spi_device *spi, uint8_t command)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = command;
+	dev_dbg(&spi->dev, "hi3110_cmd: %02X\n", command);
+
+	return hi3110_spi_trans(spi, 1);
+}
+
+static u8 hi3110_read(struct spi_device *spi, uint8_t command)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	u8 val = 0;
+
+	priv->spi_tx_buf[0] = command;
+	hi3110_spi_trans(spi, 2);
+	val = priv->spi_rx_buf[1];
+	dev_dbg(&spi->dev, "hi3110_read: %02X, %02X\n", command, val);
+
+	return val;
+}
+
+static void hi3110_write(struct spi_device *spi, u8 reg, uint8_t val)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = reg;
+	priv->spi_tx_buf[1] = val;
+	dev_dbg(&spi->dev, "hi3110_write: %02X, %02X\n", reg, val);
+
+	hi3110_spi_trans(spi, 2);
+}
+
+static void hi3110_hw_tx_frame(struct spi_device *spi, u8 *buf, int len)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = HI3110_WRITE_FIFO;
+	memcpy(priv->spi_tx_buf + 1, buf, len);
+	hi3110_spi_trans(spi, len + 1);
+}
+
+static void hi3110_hw_tx(struct spi_device *spi, struct can_frame *frame)
+{
+	u8 buf[TX_EXT_BUF_LEN];
+
+	buf[HI3110_FIFO_TAG_OFF] = 0;
+
+	if (frame->can_id & CAN_EFF_FLAG) {
+		/* Extended frame */
+		buf[HI3110_FIFO_ID_OFF] = (frame->can_id & CAN_EFF_MASK) >> 21;
+		buf[HI3110_FIFO_ID_OFF + 1] =
+			((((frame->can_id & CAN_EFF_MASK) >> 18) & 0x07) << 5) |
+			0x18 | /* Recessive SRR and IDE */
+			(((frame->can_id & CAN_EFF_MASK) >> 15) & 0x07);
+		buf[HI3110_FIFO_ID_OFF + 2] =
+			(frame->can_id & CAN_EFF_MASK) >> 7;
+		buf[HI3110_FIFO_ID_OFF + 3] =
+			((frame->can_id & CAN_EFF_MASK) << 1) |
+			((frame->can_id & CAN_RTR_FLAG) ? 1 : 0);
+
+		buf[HI3110_FIFO_EXT_DLC_OFF] = frame->can_dlc;
+
+		memcpy(buf + HI3110_FIFO_EXT_DATA_OFF,
+		       frame->data, frame->can_dlc);
+
+		hi3110_hw_tx_frame(spi, buf, TX_EXT_BUF_LEN -
+				   (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
+	} else {
+		/* Standard frame */
+		buf[HI3110_FIFO_ID_OFF] =   (frame->can_id & CAN_SFF_MASK) >> 3;
+		buf[HI3110_FIFO_ID_OFF + 1] =
+			((frame->can_id & CAN_SFF_MASK) << 5) |
+			((frame->can_id & CAN_RTR_FLAG) ? (1 << 4) : 0);
+
+		buf[HI3110_FIFO_STD_DLC_OFF] = frame->can_dlc;
+
+		memcpy(buf + HI3110_FIFO_STD_DATA_OFF,
+		       frame->data, frame->can_dlc);
+
+		hi3110_hw_tx_frame(spi, buf, TX_STD_BUF_LEN -
+				   (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
+	}
+}
+
+static void hi3110_hw_rx_frame(struct spi_device *spi, u8 *buf)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = HI3110_READ_FIFO_WOTIME;
+	hi3110_spi_trans(spi, RX_BUF_LEN);
+	memcpy(buf, priv->spi_rx_buf + 1, RX_BUF_LEN - 1);
+}
+
+static void hi3110_hw_rx(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct sk_buff *skb;
+	struct can_frame *frame;
+	u8 buf[RX_BUF_LEN - 1];
+
+	skb = alloc_can_skb(priv->net, &frame);
+	if (!skb) {
+		dev_err(&spi->dev, "cannot allocate RX skb\n");
+		priv->net->stats.rx_dropped++;
+		return;
+	}
+
+	hi3110_hw_rx_frame(spi, buf);
+	if (buf[HI3110_FIFO_WOTIME_TAG_OFF] & HI3110_FIFO_WOTIME_TAG_IDE) {
+		/* IDE is recessive (1), indicating extended 29-bit frame */
+		frame->can_id = CAN_EFF_FLAG;
+		frame->can_id |=
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF] << 21) |
+		 (((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5) << 18) |
+		 ((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0x07) << 15) |
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF + 2] << 7) |
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] >> 1);
+	} else {
+		/* IDE is dominant (0), frame indicating standard 11-bit */
+		frame->can_id =
+			(buf[HI3110_FIFO_WOTIME_ID_OFF] << 3) |
+			((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5);
+	}
+
+	if (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] & HI3110_FIFO_WOTIME_ID_RTR) {
+		/* RTR is recessive (1), indicating remote request frame */
+		frame->can_id |= CAN_RTR_FLAG;
+	}
+
+	/* Data length */
+	frame->can_dlc = get_can_dlc(buf[HI3110_FIFO_WOTIME_DLC_OFF] & 0x0F);
+	memcpy(frame->data, buf + HI3110_FIFO_WOTIME_DAT_OFF, frame->can_dlc);
+
+	priv->net->stats.rx_packets++;
+	priv->net->stats.rx_bytes += frame->can_dlc;
+
+	can_led_event(priv->net, CAN_LED_EVENT_RX);
+
+	netif_rx_ni(skb);
+}
+
+static void hi3110_hw_sleep(struct spi_device *spi)
+{
+	hi3110_write(spi, HI3110_WRITE_CTRL0, HI3110_CTRL0_SLEEP_MODE);
+}
+
+static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
+					  struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	if (priv->tx_skb || priv->tx_len) {
+		dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	if (can_dropped_invalid_skb(net, skb))
+		return NETDEV_TX_OK;
+
+	netif_stop_queue(net);
+	priv->tx_skb = skb;
+	queue_work(priv->wq, &priv->tx_work);
+
+	return NETDEV_TX_OK;
+}
+
+static int hi3110_do_set_mode(struct net_device *net, enum can_mode mode)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+
+	switch (mode) {
+	case CAN_MODE_START:
+		hi3110_clean(net);
+		/* We have to delay work since SPI I/O may sleep */
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		priv->restart_tx = 1;
+		if (priv->can.restart_ms == 0)
+			priv->after_suspend = AFTER_SUSPEND_RESTART;
+		queue_work(priv->wq, &priv->restart_work);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int hi3110_set_normal_mode(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	u8 reg;
+
+	hi3110_write(spi, HI3110_WRITE_INTE, HI3110_INT_BUSERR |
+		     HI3110_INT_RXFIFO | HI3110_INT_TXCPLT);
+
+	/* Enable TX */
+	hi3110_write(spi, HI3110_WRITE_CTRL1, HI3110_CTRL1_TXEN);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+		/* Put device into loopback mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_LOOPBACK_MODE);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+		/* Put device into listen-only mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_MONITOR_MODE);
+	} else {
+		/* Put device into normal mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_NORMAL_MODE);
+
+		/* Wait for the device to enter normal mode */
+		mdelay(HI3110_OST_DELAY_MS);
+		reg = hi3110_read(spi, HI3110_READ_CTRL0);
+		if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_NORMAL_MODE)
+			return -EBUSY;
+	}
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	return 0;
+}
+
+static int hi3110_do_set_bittiming(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	struct spi_device *spi = priv->spi;
+
+	hi3110_write(spi, HI3110_WRITE_BTR0,
+		     ((bt->sjw - 1) << HI3110_BTR0_SJW_SHIFT) |
+		     ((bt->brp - 1) << HI3110_BTR0_BRP_SHIFT));
+
+	hi3110_write(spi, HI3110_WRITE_BTR1,
+		     (priv->can.ctrlmode &
+		     CAN_CTRLMODE_3_SAMPLES ?
+		     HI3110_BTR1_SAMP_3PERBIT : HI3110_BTR1_SAMP_1PERBIT) |
+		     ((bt->phase_seg1 + bt->prop_seg - 1)
+		     << HI3110_BTR1_TSEG1_SHIFT) |
+		     ((bt->phase_seg2 - 1) << HI3110_BTR1_TSEG2_SHIFT));
+
+	dev_dbg(&spi->dev, "BT: 0x%02x 0x%02x\n",
+		hi3110_read(spi, HI3110_READ_BTR0),
+		hi3110_read(spi, HI3110_READ_BTR1));
+
+	return 0;
+}
+
+static int hi3110_setup(struct net_device *net, struct hi3110_priv *priv,
+			struct spi_device *spi)
+{
+	hi3110_do_set_bittiming(net);
+	return 0;
+}
+
+static int hi3110_hw_reset(struct spi_device *spi)
+{
+	u8 reg;
+	int ret;
+
+	/* Wait for oscillator startup timer after power up */
+	mdelay(HI3110_OST_DELAY_MS);
+
+	ret = hi3110_cmd(spi, HI3110_MASTER_RESET);
+	if (ret)
+		return ret;
+
+	/* Wait for oscillator startup timer after reset */
+	mdelay(HI3110_OST_DELAY_MS);
+
+	reg = hi3110_read(spi, HI3110_READ_CTRL0);
+	if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_INIT_MODE)
+		return -ENODEV;
+
+	/* As per the datasheet it appears the error flags are
+	 * not cleared on reset. Explicitly clear them by performing a read
+	 */
+	hi3110_read(spi, HI3110_READ_ERR);
+
+	return 0;
+}
+
+static int hi3110_hw_probe(struct spi_device *spi)
+{
+	u8 statf;
+
+	hi3110_hw_reset(spi);
+
+	/* Confirm correct operation by checking against reset values
+	 * in datasheet
+	 */
+	statf = hi3110_read(spi, HI3110_READ_STATF);
+
+	dev_dbg(&spi->dev, "statf: %02X\n", statf);
+
+	if (statf != 0x82)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int hi3110_power_enable(struct regulator *reg, int enable)
+{
+	if (IS_ERR_OR_NULL(reg))
+		return 0;
+
+	if (enable)
+		return regulator_enable(reg);
+	else
+		return regulator_disable(reg);
+}
+
+static void hi3110_open_clean(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	free_irq(spi->irq, priv);
+	hi3110_hw_sleep(spi);
+	hi3110_power_enable(priv->transceiver, 0);
+	close_candev(net);
+}
+
+static int hi3110_stop(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	close_candev(net);
+
+	priv->force_quit = 1;
+	free_irq(spi->irq, priv);
+	destroy_workqueue(priv->wq);
+	priv->wq = NULL;
+
+	mutex_lock(&priv->hi3110_lock);
+
+	/* Disable transmit, interrupts and clear flags */
+	hi3110_write(spi, HI3110_WRITE_CTRL1, 0x0);
+	hi3110_write(spi, HI3110_WRITE_INTE, 0x0);
+	hi3110_read(spi, HI3110_READ_INTF);
+
+	hi3110_clean(net);
+
+	hi3110_hw_sleep(spi);
+
+	hi3110_power_enable(priv->transceiver, 0);
+
+	priv->can.state = CAN_STATE_STOPPED;
+
+	mutex_unlock(&priv->hi3110_lock);
+
+	can_led_event(net, CAN_LED_EVENT_STOP);
+
+	return 0;
+}
+
+static void hi3110_error_skb(struct net_device *net, int can_id,
+			     int data1, int data2)
+{
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	skb = alloc_can_err_skb(net, &frame);
+	if (skb) {
+		frame->can_id |= can_id;
+		frame->data[1] = data1;
+		frame->data[2] = data2;
+		netif_rx_ni(skb);
+	} else {
+		netdev_err(net, "cannot allocate error skb\n");
+	}
+}
+
+static void hi3110_tx_work_handler(struct work_struct *ws)
+{
+	struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
+						 tx_work);
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+	struct can_frame *frame;
+
+	mutex_lock(&priv->hi3110_lock);
+	if (priv->tx_skb) {
+		if (priv->can.state == CAN_STATE_BUS_OFF) {
+			hi3110_clean(net);
+		} else {
+			frame = (struct can_frame *)priv->tx_skb->data;
+
+			if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
+				frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
+			hi3110_hw_tx(spi, frame);
+			priv->tx_len = 1 + frame->can_dlc;
+			can_put_echo_skb(priv->tx_skb, net, 0);
+			priv->tx_skb = NULL;
+		}
+	}
+	mutex_unlock(&priv->hi3110_lock);
+}
+
+static void hi3110_restart_work_handler(struct work_struct *ws)
+{
+	struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
+						 restart_work);
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+
+	mutex_lock(&priv->hi3110_lock);
+	if (priv->after_suspend) {
+		hi3110_hw_reset(spi);
+		hi3110_setup(net, priv, spi);
+		if (priv->after_suspend & AFTER_SUSPEND_RESTART) {
+			hi3110_set_normal_mode(spi);
+		} else if (priv->after_suspend & AFTER_SUSPEND_UP) {
+			netif_device_attach(net);
+			hi3110_clean(net);
+			hi3110_set_normal_mode(spi);
+			netif_wake_queue(net);
+		} else {
+			hi3110_hw_sleep(spi);
+		}
+		priv->after_suspend = 0;
+		priv->force_quit = 0;
+	}
+
+	if (priv->restart_tx) {
+		priv->restart_tx = 0;
+		hi3110_clean(net);
+		netif_wake_queue(net);
+		hi3110_error_skb(net, CAN_ERR_RESTARTED, 0, 0);
+	}
+	mutex_unlock(&priv->hi3110_lock);
+}
+
+static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
+{
+	struct hi3110_priv *priv = dev_id;
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+
+	mutex_lock(&priv->hi3110_lock);
+
+	while (!priv->force_quit) {
+		enum can_state new_state;
+		u8 intf;
+		u8 eflag;
+		int can_id = 0, data1 = 0, data2 = 0;
+
+		while (!(HI3110_STAT_RXFMTY &
+			hi3110_read(spi, HI3110_READ_STATF))) {
+			hi3110_hw_rx(spi);
+		};
+
+		intf = hi3110_read(spi, HI3110_READ_INTF);
+		eflag = hi3110_read(spi, HI3110_READ_ERR);
+		/* Update can state */
+		if (eflag & HI3110_ERR_BUSOFF) {
+			new_state = CAN_STATE_BUS_OFF;
+			can_id |= CAN_ERR_BUSOFF;
+		} else if (eflag & HI3110_ERR_TXERRP) {
+			new_state = CAN_STATE_ERROR_PASSIVE;
+			can_id |= CAN_ERR_CRTL;
+			data1 |= CAN_ERR_CRTL_TX_PASSIVE;
+		} else if (eflag & HI3110_ERR_RXERRP) {
+			new_state = CAN_STATE_ERROR_PASSIVE;
+			can_id |= CAN_ERR_CRTL;
+			data1 |= CAN_ERR_CRTL_RX_PASSIVE;
+		} else {
+			new_state = CAN_STATE_ERROR_ACTIVE;
+		}
+
+		/* Check for protocol errors */
+		if (eflag & HI3110_ERR_PROTOCOL_MASK) {
+			can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+			priv->can.can_stats.bus_error++;
+			priv->net->stats.rx_errors++;
+			if (eflag & HI3110_ERR_BITERR)
+				data2 |= CAN_ERR_PROT_BIT;
+			else if (eflag & HI3110_ERR_FRMERR)
+				data2 |= CAN_ERR_PROT_FORM;
+			else if (eflag & HI3110_ERR_STUFERR)
+				data2 |= CAN_ERR_PROT_STUFF;
+			else
+				data2 |= CAN_ERR_PROT_UNSPEC;
+		}
+
+		/* Update can state statistics */
+		switch (priv->can.state) {
+		case CAN_STATE_ERROR_ACTIVE:
+			if (new_state >= CAN_STATE_ERROR_WARNING &&
+			    new_state <= CAN_STATE_BUS_OFF)
+				priv->can.can_stats.error_warning++;
+		/* fallthrough */
+		case CAN_STATE_ERROR_WARNING:
+			if (new_state >= CAN_STATE_ERROR_PASSIVE &&
+			    new_state <= CAN_STATE_BUS_OFF)
+				priv->can.can_stats.error_passive++;
+			break;
+		default:
+			break;
+		}
+		priv->can.state = new_state;
+
+		if (intf & HI3110_INT_BUSERR) {
+			/* Note: HI3110 Does report overflow errors */
+			hi3110_error_skb(net, can_id, data1, data2);
+		}
+
+		if (priv->can.state == CAN_STATE_BUS_OFF) {
+			if (priv->can.restart_ms == 0) {
+				priv->force_quit = 1;
+				priv->can.can_stats.bus_off++;
+				can_bus_off(net);
+				hi3110_hw_sleep(spi);
+				break;
+			}
+		}
+
+		if (intf == 0)
+			break;
+
+		if (intf & HI3110_INT_TXCPLT) {
+			net->stats.tx_packets++;
+			net->stats.tx_bytes += priv->tx_len - 1;
+			can_led_event(net, CAN_LED_EVENT_TX);
+			if (priv->tx_len) {
+				can_get_echo_skb(net, 0);
+				priv->tx_len = 0;
+			}
+			netif_wake_queue(net);
+		}
+	}
+	mutex_unlock(&priv->hi3110_lock);
+	return IRQ_HANDLED;
+}
+
+static int hi3110_open(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
+	int ret;
+
+	ret = open_candev(net);
+	if (ret) {
+		dev_err(&spi->dev, "unable to set initial baudrate!\n");
+		return ret;
+	}
+
+	mutex_lock(&priv->hi3110_lock);
+	hi3110_power_enable(priv->transceiver, 1);
+
+	priv->force_quit = 0;
+	priv->tx_skb = NULL;
+	priv->tx_len = 0;
+
+	ret = request_threaded_irq(spi->irq, NULL, hi3110_can_ist,
+				   flags, DEVICE_NAME, priv);
+	if (ret) {
+		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
+		hi3110_power_enable(priv->transceiver, 0);
+		close_candev(net);
+		goto open_unlock;
+	}
+
+	priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
+			   0);
+	INIT_WORK(&priv->tx_work, hi3110_tx_work_handler);
+	INIT_WORK(&priv->restart_work, hi3110_restart_work_handler);
+
+	ret = hi3110_hw_reset(spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	ret = hi3110_setup(net, priv, spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	ret = hi3110_set_normal_mode(spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	can_led_event(net, CAN_LED_EVENT_OPEN);
+	netif_wake_queue(net);
+
+open_unlock:
+	mutex_unlock(&priv->hi3110_lock);
+	return ret;
+}
+
+static const struct net_device_ops hi3110_netdev_ops = {
+	.ndo_open = hi3110_open,
+	.ndo_stop = hi3110_stop,
+	.ndo_start_xmit = hi3110_hard_start_xmit,
+};
+
+static const struct of_device_id hi3110_of_match[] = {
+	{
+		.compatible	= "holt,hi3110",
+		.data		= (void *)CAN_HI3110_HI3110,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hi3110_of_match);
+
+static const struct spi_device_id hi3110_id_table[] = {
+	{
+		.name		= "hi3110",
+		.driver_data	= (kernel_ulong_t)CAN_HI3110_HI3110,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, hi3110_id_table);
+
+static int hi3110_can_probe(struct spi_device *spi)
+{
+	const struct of_device_id *of_id = of_match_device(hi3110_of_match,
+							   &spi->dev);
+	struct net_device *net;
+	struct hi3110_priv *priv;
+	struct clk *clk;
+	int freq, ret;
+
+	clk = devm_clk_get(&spi->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&spi->dev, "no CAN clock source defined\n");
+		return PTR_ERR(clk);
+	}
+	freq = clk_get_rate(clk);
+
+	/* Sanity check */
+	if (freq > 40000000)
+		return -ERANGE;
+
+	/* Allocate can/net device */
+	net = alloc_candev(sizeof(struct hi3110_priv), TX_ECHO_SKB_MAX);
+	if (!net)
+		return -ENOMEM;
+
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret)
+			goto out_free;
+	}
+
+	net->netdev_ops = &hi3110_netdev_ops;
+	net->flags |= IFF_ECHO;
+
+	priv = netdev_priv(net);
+	priv->can.bittiming_const = &hi3110_bittiming_const;
+	priv->can.do_set_mode = hi3110_do_set_mode;
+	priv->can.clock.freq = freq / 2;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
+		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
+	if (of_id)
+		priv->model = (enum hi3110_model)of_id->data;
+	else
+		priv->model = spi_get_device_id(spi)->driver_data;
+	priv->net = net;
+	priv->clk = clk;
+
+	spi_set_drvdata(spi, priv);
+
+	/* Configure the SPI bus */
+	spi->bits_per_word = 8;
+	ret = spi_setup(spi);
+	if (ret)
+		goto out_clk;
+
+	priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
+	priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
+	if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
+	    (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
+		ret = -EPROBE_DEFER;
+		goto out_clk;
+	}
+
+	ret = hi3110_power_enable(priv->power, 1);
+	if (ret)
+		goto out_clk;
+
+	priv->spi = spi;
+	mutex_init(&priv->hi3110_lock);
+
+	/* If requested, allocate DMA buffers */
+	if (hi3110_enable_dma) {
+		spi->dev.coherent_dma_mask = ~0;
+
+		/* Minimum coherent DMA allocation is PAGE_SIZE, so allocate
+		 * that much and share it between Tx and Rx DMA buffers.
+		 */
+		priv->spi_tx_buf = dmam_alloc_coherent(&spi->dev,
+						      PAGE_SIZE,
+						      &priv->spi_tx_dma,
+						      GFP_DMA);
+
+		if (priv->spi_tx_buf) {
+			priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2));
+			priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
+							(PAGE_SIZE / 2));
+		} else {
+			/* Fall back to non-DMA */
+			hi3110_enable_dma = 0;
+		}
+	}
+
+	/* Allocate non-DMA buffers */
+	if (!hi3110_enable_dma) {
+		priv->spi_tx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
+				GFP_KERNEL);
+		if (!priv->spi_tx_buf) {
+			ret = -ENOMEM;
+			goto error_probe;
+		}
+		priv->spi_rx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
+				GFP_KERNEL);
+
+		if (!priv->spi_rx_buf) {
+			ret = -ENOMEM;
+			goto error_probe;
+		}
+	}
+
+	SET_NETDEV_DEV(net, &spi->dev);
+
+	ret = hi3110_hw_probe(spi);
+	if (ret) {
+		if (ret == -ENODEV)
+			dev_err(&spi->dev, "Cannot initialize %x. Wrong wiring?\n",
+				priv->model);
+		goto error_probe;
+	}
+	hi3110_hw_sleep(spi);
+
+	ret = register_candev(net);
+	if (ret)
+		goto error_probe;
+
+	devm_can_led_init(net);
+	netdev_info(net, "%x successfully initialized.\n", priv->model);
+
+	return 0;
+
+error_probe:
+	hi3110_power_enable(priv->power, 0);
+
+out_clk:
+	if (!IS_ERR(clk))
+		clk_disable_unprepare(clk);
+
+out_free:
+	free_candev(net);
+
+	dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
+	return ret;
+}
+
+static int hi3110_can_remove(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct net_device *net = priv->net;
+
+	unregister_candev(net);
+
+	hi3110_power_enable(priv->power, 0);
+
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+
+	free_candev(net);
+
+	return 0;
+}
+
+static int __maybe_unused hi3110_can_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct net_device *net = priv->net;
+
+	priv->force_quit = 1;
+	disable_irq(spi->irq);
+
+	/* Note: at this point neither IST nor workqueues are running.
+	 * open/stop cannot be called anyway so locking is not needed
+	 */
+	if (netif_running(net)) {
+		netif_device_detach(net);
+
+		hi3110_hw_sleep(spi);
+		hi3110_power_enable(priv->transceiver, 0);
+		priv->after_suspend = AFTER_SUSPEND_UP;
+	} else {
+		priv->after_suspend = AFTER_SUSPEND_DOWN;
+	}
+
+	if (!IS_ERR_OR_NULL(priv->power)) {
+		regulator_disable(priv->power);
+		priv->after_suspend |= AFTER_SUSPEND_POWER;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused hi3110_can_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	if (priv->after_suspend & AFTER_SUSPEND_POWER)
+		hi3110_power_enable(priv->power, 1);
+
+	if (priv->after_suspend & AFTER_SUSPEND_UP) {
+		hi3110_power_enable(priv->transceiver, 1);
+		queue_work(priv->wq, &priv->restart_work);
+	} else {
+		priv->after_suspend = 0;
+	}
+
+	priv->force_quit = 0;
+	enable_irq(spi->irq);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend,
+	hi3110_can_resume);
+
+static struct spi_driver hi3110_can_driver = {
+	.driver = {
+		.name = DEVICE_NAME,
+		.of_match_table = hi3110_of_match,
+		.pm = &hi3110_can_pm_ops,
+	},
+	.id_table = hi3110_id_table,
+	.probe = hi3110_can_probe,
+	.remove = hi3110_can_remove,
+};
+
+module_spi_driver(hi3110_can_driver);
+
+MODULE_AUTHOR("Akshay Bhat <akshay.bhat@timesys.com>");
+MODULE_AUTHOR("Casey Fitzpatrick <casey.fitzpatrick@timesys.com>");
+MODULE_DESCRIPTION("Holt HI-3110 CAN driver");
+MODULE_LICENSE("GPL v2");
-- 
2.8.1

^ permalink raw reply related

* [PATCH 1/2] can: holt_hi311x: document device tree bindings
From: Akshay Bhat @ 2016-11-14 17:55 UTC (permalink / raw)
  To: wg, mkl, robh+dt
  Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
	Akshay Bhat, Akshay Bhat

Document the HOLT HI-311x CAN device tree bindings.

Signed-off-by: Akshay Bhat <nodeax@gmail.com>
---
 .../devicetree/bindings/net/can/holt_hi311x.txt    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/can/holt_hi311x.txt

diff --git a/Documentation/devicetree/bindings/net/can/holt_hi311x.txt b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
new file mode 100644
index 0000000..23aa94e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
@@ -0,0 +1,24 @@
+* Holt HI-311X stand-alone CAN controller device tree bindings
+
+Required properties:
+ - compatible: Should be one of the following:
+   - "holt,hi3110" for HI-3110
+ - reg: SPI chip select.
+ - clocks: The clock feeding the CAN controller.
+ - interrupt-parent: The parent interrupt controller.
+ - interrupts: Should contain IRQ line for the CAN controller.
+
+Optional properties:
+ - vdd-supply: Regulator that powers the CAN controller.
+ - xceiver-supply: Regulator that powers the CAN transceiver.
+
+Example:
+	can0: can@1 {
+		compatible = "holt,hi3110";
+		reg = <1>;
+		clocks = <&clk32m>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <13 IRQ_TYPE_EDGE_RISING>;
+		vdd-supply = <&reg5v0>;
+		xceiver-supply = <&reg5v0>;
+	};
-- 
2.8.1

^ permalink raw reply related

* [PATCH tip/core/rcu 0/7] Security-related list changes for 4.10
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani

Hello!

This series contains security-related list changes, some of which stems
in part from PaX and Grsecurity work:

1.	Split __list_add() debug checks into a separate functions,
	courtesy of Kees Cook.

2.	Consolidate DEBUG_LIST() for list_add_rcu(), courtesy of Kees Cook.

3.	Split list_del() debug checking into separate function, courtesy
	of Kees Cook.

4.	Provide toggle for BUG() on data corruption, so that people who
	care more about security than uptime can crash their machines
	in the face of list data corruption, courtesy of Kees Cook.

	Note that CHECK_DATA_CORRUPTION() contains unconventional control
	flow, however, this is intended and is used correctly.

5.	Add tests for list corruption, courtesy of Kees Cook.

6.	Fix typo in "select" Kconfig statement in #4 above, courtesy
	of Valentin Rothberg.

7.	Avoid Kconfig warning from CONFIG_DEBUG_LIST from #4 above,
	courtesy of Arnd Bergmann.

							Thanx, Paul

------------------------------------------------------------------------

 drivers/misc/lkdtm.h      |    2 
 drivers/misc/lkdtm_bugs.c |   68 +++++++++++++++++
 drivers/misc/lkdtm_core.c |    2 
 include/linux/bug.h       |   17 ++++
 include/linux/list.h      |   37 ++++++---
 include/linux/rculist.h   |    8 --
 lib/Kconfig.debug         |   14 +++
 lib/list_debug.c          |  177 +++++++++++++++++-----------------------------
 8 files changed, 197 insertions(+), 128 deletions(-)

^ permalink raw reply

* Re: [net]  2ab9fb18c4: kernel BUG at include/linux/skbuff.h:1935!
From: Duyck, Alexander H @ 2016-11-14 17:54 UTC (permalink / raw)
  To: eric.dumazet@gmail.com, Ye, Xiaolong
  Cc: tom@herbertland.com, ast@kernel.org, willemb@google.com,
	netdev@vger.kernel.org, jojvargh@cisco.com, davem@davemloft.net,
	lkp@01.org, yibyang@cisco.com
In-Reply-To: <5828fc09.rTUEnj6qw0eDHzYL%xiaolong.ye@intel.com>

On Mon, 2016-11-14 at 07:49 +0800, kernel test robot wrote:
> FYI, we noticed the following commit:
> 
> https://github.com/0day-ci/linux Eric-Dumazet/net-__skb_flow_dissect-must-cap-its-return-value/20161110-080839
> commit 2ab9fb18c46b91b16a0f0f329336d3be9fc32deb ("net: __skb_flow_dissect() must cap its return value")
> 
> in testcase: kbuild
> with following parameters:
> 
> 	runtime: 300s
> 	nr_task: 50%
> 	cpufreq_governor: performance
> 
> 
> 
> 
> on test machine: 8 threads Intel(R) Atom(TM) CPU  C2750  @ 2.40GHz with 16G memory
> 
> caused below changes:
> 
> 
> +-------------------------------------------------------+------------+------------+
> > 
> >                                                       | cdb26d3387 | 2ab9fb18c4 |
> +-------------------------------------------------------+------------+------------+
> > 
> > boot_successes                                        | 10         | 3          |
> > boot_failures                                         | 0          | 9          |
> > kernel_BUG_at_include/linux/skbuff.h                  | 0          | 8          |
> > invalid_opcode:#[##]SMP                               | 0          | 8          |
> > RIP:eth_type_trans                                    | 0          | 8          |
> > Kernel_panic-not_syncing:Fatal_exception_in_interrupt | 0          | 5          |
> > WARNING:at_fs/sysfs/dir.c:#sysfs_warn_dup             | 0          | 1          |
> > calltrace:parport_pc_init                             | 0          | 1          |
> > calltrace:SyS_finit_module                            | 0          | 1          |
> > WARNING:at_lib/kobject.c:#kobject_add_internal        | 0          | 1          |
> +-------------------------------------------------------+------------+------------+
> 
> 
> 
> [   20.491020] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [   20.502988] Sending DHCP requests .
> [   20.506729] ------------[ cut here ]------------
> [   20.511369] kernel BUG at include/linux/skbuff.h:1935!
> [   20.517893] invalid opcode: 0000 [#1] SMP
> [   20.521902] Modules linked in:
> [   20.524979] CPU: 4 PID: 0 Comm: swapper/4 Not tainted 4.9.0-rc3-00286-g2ab9fb1 #1
> [   20.532463] Hardware name: Supermicro SYS-5018A-TN4/A1SAi, BIOS 1.1a 08/27/2015
> [   20.539768] task: ffff8804456c2480 task.stack: ffffc90001920000
> [   20.545684] RIP: 0010:[<ffffffff81837b48>]  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.553972] RSP: 0018:ffff88047fd03db8  EFLAGS: 00010297
> [   20.559283] RAX: 0000000000000158 RBX: ffff88047d8ae600 RCX: 0000000000001073
> [   20.566415] RDX: ffff88047bf07dc0 RSI: ffff88047d8a4000 RDI: ffff88047dac0f00
> [   20.573546] RBP: ffff88047fd03e20 R08: ffff88047d8a4000 R09: 0000000000000800
> [   20.580678] R10: ffff88047bf07ec0 R11: ffffea0011f6e400 R12: ffff88047dac0f00
> [   20.587810] R13: ffff880457413000 R14: ffffc90002129000 R15: 000000000000015e
> [   20.594946] FS:  0000000000000000(0000) GS:ffff88047fd00000(0000) knlGS:0000000000000000
> [   20.603032] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   20.608775] CR2: 00007fffadfb4ef0 CR3: 000000047ee07000 CR4: 00000000001006e0
> [   20.615906] Stack:
> [   20.617927]  ffffffff816905a7 ffffea0011f6e400 ffffea0000000008 ffff88047d8ae450
> [   20.625403]  ffff88047d8ae400 0000004000000166 ffffea0011f6e400 0000ffff00000000
> [   20.632873]  0000000000000040 0000000000000000 ffff88047d8ae450 ffff88047d8b1140
> [   20.640352] Call Trace:
> [   20.642805]  <IRQ> 
> [   20.644740]  [<ffffffff816905a7>] ? igb_clean_rx_irq+0x6a7/0x7d0
> [   20.650760]  [<ffffffff81690a52>] igb_poll+0x382/0x700
> [   20.655904]  [<ffffffff8146edd9>] ? timerqueue_add+0x59/0xb0
> [   20.661564]  [<ffffffff8180f2d7>] net_rx_action+0x217/0x360
> [   20.667137]  [<ffffffff81957ef4>] __do_softirq+0x104/0x2ab
> [   20.672624]  [<ffffffff81086961>] irq_exit+0xf1/0x100
> [   20.677673]  [<ffffffff81957c34>] do_IRQ+0x54/0xd0
> [   20.682466]  [<ffffffff81955acc>] common_interrupt+0x8c/0x8c
> [   20.688123]  <EOI> 
> [   20.690054]  [<ffffffff817c1d12>] ? cpuidle_enter_state+0x122/0x2e0
> [   20.696333]  [<ffffffff817c1f07>] cpuidle_enter+0x17/0x20
> [   20.701733]  [<ffffffff810c64c3>] call_cpuidle+0x23/0x40
> [   20.707045]  [<ffffffff810c66f4>] cpu_startup_entry+0x114/0x200
> [   20.712964]  [<ffffffff81051c87>] start_secondary+0x107/0x130
> [   20.718708] Code: 00 04 00 00 c9 c3 48 33 86 70 03 00 00 48 c1 e0 10 48 85 c0 0f b6 87 90 00 00 00 75 28 83 e0 f8 83 c8 01 88 87 90 00 00 00 eb 82 <0f> 0b 0f b6 87 90 00 00 00 83 e0 f8 83 c8 03 88 87 90 00 00 00 
> [   20.738722] RIP  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.744662]  RSP <ffff88047fd03db8>
> [   20.748160] ---[ end trace 153440bf1ca2e6fc ]---
> [   20.748165] ------------[ cut here ]------------
> 
> 
> To reproduce:
> 
>         git clone git://git.kernel.org/pub/scm/linux/kernel/git/wfg/lkp-tests.git
>         cd lkp-tests
>         bin/lkp install job.yaml  # job file is attached in this email
>         bin/lkp run     job.yaml
> 
> 
> 
> Thanks,
> Kernel Test Robot


So I am trying to reproduce this but need some additional data as just
copying the config apparently isn't enough.

I just wanted to confirm.  It looks like you are running serial over
lan over one of the igb ports.  Do I have that right?  I ask because
the igb driver loading in the dmesg log seems to cause a 2.1 second
skip and doesn't display the driver version or any information on the
igb devices.

Another question I had is what versions of gcc are you testing with?  I
see the dmesg for the failing case is using gcc version 6.2.  Are there
any other versions of gcc that are being tested, and if so are they
showing similar failures?

Thanks.

- Alex



^ permalink raw reply

* Re: [net] 2ab9fb18c4: kernel BUG at include/linux/skbuff.h:1935!
From: Duyck, Alexander H @ 2016-11-14 17:54 UTC (permalink / raw)
  To: lkp
In-Reply-To: <5828fc09.rTUEnj6qw0eDHzYL%xiaolong.ye@intel.com>

[-- Attachment #1: Type: text/plain, Size: 5871 bytes --]

On Mon, 2016-11-14 at 07:49 +0800, kernel test robot wrote:
> FYI, we noticed the following commit:
> 
> https://github.com/0day-ci/linux Eric-Dumazet/net-__skb_flow_dissect-must-cap-its-return-value/20161110-080839
> commit 2ab9fb18c46b91b16a0f0f329336d3be9fc32deb ("net: __skb_flow_dissect() must cap its return value")
> 
> in testcase: kbuild
> with following parameters:
> 
> 	runtime: 300s
> 	nr_task: 50%
> 	cpufreq_governor: performance
> 
> 
> 
> 
> on test machine: 8 threads Intel(R) Atom(TM) CPU  C2750  @ 2.40GHz with 16G memory
> 
> caused below changes:
> 
> 
> +-------------------------------------------------------+------------+------------+
> > 
> >                                                       | cdb26d3387 | 2ab9fb18c4 |
> +-------------------------------------------------------+------------+------------+
> > 
> > boot_successes                                        | 10         | 3          |
> > boot_failures                                         | 0          | 9          |
> > kernel_BUG_at_include/linux/skbuff.h                  | 0          | 8          |
> > invalid_opcode:#[##]SMP                               | 0          | 8          |
> > RIP:eth_type_trans                                    | 0          | 8          |
> > Kernel_panic-not_syncing:Fatal_exception_in_interrupt | 0          | 5          |
> > WARNING:at_fs/sysfs/dir.c:#sysfs_warn_dup             | 0          | 1          |
> > calltrace:parport_pc_init                             | 0          | 1          |
> > calltrace:SyS_finit_module                            | 0          | 1          |
> > WARNING:at_lib/kobject.c:#kobject_add_internal        | 0          | 1          |
> +-------------------------------------------------------+------------+------------+
> 
> 
> 
> [   20.491020] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [   20.502988] Sending DHCP requests .
> [   20.506729] ------------[ cut here ]------------
> [   20.511369] kernel BUG at include/linux/skbuff.h:1935!
> [   20.517893] invalid opcode: 0000 [#1] SMP
> [   20.521902] Modules linked in:
> [   20.524979] CPU: 4 PID: 0 Comm: swapper/4 Not tainted 4.9.0-rc3-00286-g2ab9fb1 #1
> [   20.532463] Hardware name: Supermicro SYS-5018A-TN4/A1SAi, BIOS 1.1a 08/27/2015
> [   20.539768] task: ffff8804456c2480 task.stack: ffffc90001920000
> [   20.545684] RIP: 0010:[<ffffffff81837b48>]  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.553972] RSP: 0018:ffff88047fd03db8  EFLAGS: 00010297
> [   20.559283] RAX: 0000000000000158 RBX: ffff88047d8ae600 RCX: 0000000000001073
> [   20.566415] RDX: ffff88047bf07dc0 RSI: ffff88047d8a4000 RDI: ffff88047dac0f00
> [   20.573546] RBP: ffff88047fd03e20 R08: ffff88047d8a4000 R09: 0000000000000800
> [   20.580678] R10: ffff88047bf07ec0 R11: ffffea0011f6e400 R12: ffff88047dac0f00
> [   20.587810] R13: ffff880457413000 R14: ffffc90002129000 R15: 000000000000015e
> [   20.594946] FS:  0000000000000000(0000) GS:ffff88047fd00000(0000) knlGS:0000000000000000
> [   20.603032] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   20.608775] CR2: 00007fffadfb4ef0 CR3: 000000047ee07000 CR4: 00000000001006e0
> [   20.615906] Stack:
> [   20.617927]  ffffffff816905a7 ffffea0011f6e400 ffffea0000000008 ffff88047d8ae450
> [   20.625403]  ffff88047d8ae400 0000004000000166 ffffea0011f6e400 0000ffff00000000
> [   20.632873]  0000000000000040 0000000000000000 ffff88047d8ae450 ffff88047d8b1140
> [   20.640352] Call Trace:
> [   20.642805]  <IRQ> 
> [   20.644740]  [<ffffffff816905a7>] ? igb_clean_rx_irq+0x6a7/0x7d0
> [   20.650760]  [<ffffffff81690a52>] igb_poll+0x382/0x700
> [   20.655904]  [<ffffffff8146edd9>] ? timerqueue_add+0x59/0xb0
> [   20.661564]  [<ffffffff8180f2d7>] net_rx_action+0x217/0x360
> [   20.667137]  [<ffffffff81957ef4>] __do_softirq+0x104/0x2ab
> [   20.672624]  [<ffffffff81086961>] irq_exit+0xf1/0x100
> [   20.677673]  [<ffffffff81957c34>] do_IRQ+0x54/0xd0
> [   20.682466]  [<ffffffff81955acc>] common_interrupt+0x8c/0x8c
> [   20.688123]  <EOI> 
> [   20.690054]  [<ffffffff817c1d12>] ? cpuidle_enter_state+0x122/0x2e0
> [   20.696333]  [<ffffffff817c1f07>] cpuidle_enter+0x17/0x20
> [   20.701733]  [<ffffffff810c64c3>] call_cpuidle+0x23/0x40
> [   20.707045]  [<ffffffff810c66f4>] cpu_startup_entry+0x114/0x200
> [   20.712964]  [<ffffffff81051c87>] start_secondary+0x107/0x130
> [   20.718708] Code: 00 04 00 00 c9 c3 48 33 86 70 03 00 00 48 c1 e0 10 48 85 c0 0f b6 87 90 00 00 00 75 28 83 e0 f8 83 c8 01 88 87 90 00 00 00 eb 82 <0f> 0b 0f b6 87 90 00 00 00 83 e0 f8 83 c8 03 88 87 90 00 00 00 
> [   20.738722] RIP  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.744662]  RSP <ffff88047fd03db8>
> [   20.748160] ---[ end trace 153440bf1ca2e6fc ]---
> [   20.748165] ------------[ cut here ]------------
> 
> 
> To reproduce:
> 
>         git clone git://git.kernel.org/pub/scm/linux/kernel/git/wfg/lkp-tests.git
>         cd lkp-tests
>         bin/lkp install job.yaml  # job file is attached in this email
>         bin/lkp run     job.yaml
> 
> 
> 
> Thanks,
> Kernel Test Robot


So I am trying to reproduce this but need some additional data as just
copying the config apparently isn't enough.

I just wanted to confirm.  It looks like you are running serial over
lan over one of the igb ports.  Do I have that right?  I ask because
the igb driver loading in the dmesg log seems to cause a 2.1 second
skip and doesn't display the driver version or any information on the
igb devices.

Another question I had is what versions of gcc are you testing with?  I
see the dmesg for the failing case is using gcc version 6.2.  Are there
any other versions of gcc that are being tested, and if so are they
showing similar failures?

Thanks.

- Alex



^ permalink raw reply

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Lee Jones, Rob Herring, Andy Gross, devicetree, linux-kernel,
	linux-arm-msm, linux-soc, linux-arm-kernel
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51@linaro.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn

^ permalink raw reply

* [U-Boot] [PATCH v2 2/3] LS1046AQDS: Add NOR Secure Boot Target
From: york sun @ 2016-11-14 17:53 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <1477513031-29292-3-git-send-email-sumit.garg@nxp.com>

On 10/26/2016 03:47 AM, Sumit Garg wrote:
> Add NOR secure boot target. Also enable sec init.
>
> Signed-off-by: Vinitha Pillai <vinitha.pillai@nxp.com>
> Signed-off-by: Sumit Garg <sumit.garg@nxp.com>
> ---
>
> Changes in v2:
> Split patches logically from 2 to 3.
>
>  board/freescale/ls1046aqds/MAINTAINERS   |  4 ++++
>  board/freescale/ls1046aqds/ls1046aqds.c  | 18 ++++++++++++++++++
>  configs/ls1046aqds_SECURE_BOOT_defconfig | 29 +++++++++++++++++++++++++++++
>  3 files changed, 51 insertions(+)
>  create mode 100644 configs/ls1046aqds_SECURE_BOOT_defconfig
>
> diff --git a/board/freescale/ls1046aqds/MAINTAINERS b/board/freescale/ls1046aqds/MAINTAINERS
> index b4549ae..6737d55 100644
> --- a/board/freescale/ls1046aqds/MAINTAINERS
> +++ b/board/freescale/ls1046aqds/MAINTAINERS
> @@ -8,3 +8,7 @@ F:	configs/ls1046aqds_nand_defconfig
>  F:	configs/ls1046aqds_sdcard_ifc_defconfig
>  F:	configs/ls1046aqds_sdcard_qspi_defconfig
>  F:	configs/ls1046aqds_qspi_defconfig
> +
> +M:	Sumit Garg <sumit.garg@nxp.com>
> +S:	Maintained
> +F:	configs/ls1046aqds_SECURE_BOOT_defconfig
> diff --git a/board/freescale/ls1046aqds/ls1046aqds.c b/board/freescale/ls1046aqds/ls1046aqds.c
> index 8c18538..a418590 100644
> --- a/board/freescale/ls1046aqds/ls1046aqds.c
> +++ b/board/freescale/ls1046aqds/ls1046aqds.c
> @@ -20,6 +20,7 @@
>  #include <fsl_csu.h>
>  #include <fsl_esdhc.h>
>  #include <fsl_ifc.h>
> +#include <fsl_sec.h>
>  #include <spl.h>
>
>  #include "../common/vid.h"
> @@ -242,6 +243,23 @@ int board_init(void)
>  	if (adjust_vdd(0))
>  		printf("Warning: Adjusting core voltage failed.\n");
>
> +#ifdef CONFIG_SECURE_BOOT
> +	/* In case of Secure Boot, the IBR configures the SMMU
> +	 * to allow only Secure transactions.
> +	 * SMMU must be reset in bypass mode.
> +	 * Set the ClientPD bit and Clear the USFCFG Bit
> +	 */

Multiple-line comment in wrong format. You just fixed some in your first 
patch.

York

^ permalink raw reply

* [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51@linaro.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn

^ permalink raw reply

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Lee Jones, Rob Herring, Andy Gross,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] cpufreq: intel_pstate: fix intel_pstate_use_acpi_profile helper
From: Pandruvada, Srinivas @ 2016-11-14 17:53 UTC (permalink / raw)
  To: arnd@arndb.de, rjw@rjwysocki.net
  Cc: lenb@kernel.org, viresh.kumar@linaro.org, Gasparini, Stephane,
	philippe.longepe@linux.intel.com, linux-pm@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <1479143663.6544.11.camel@linux.intel.com>

On Mon, 2016-11-14 at 09:14 -0800, Srinivas Pandruvada wrote:
> On Mon, 2016-11-14 at 17:41 +0100, Arnd Bergmann wrote:
> > 
> > The newly added function uses two different prototypes depending
> > on configuration, and one of them does not match the caller:
> > 
> > drivers/cpufreq/intel_pstate.c: In function ‘copy_cpu_funcs’:
> > drivers/cpufreq/intel_pstate.c:1798:2: error: too few arguments to
> > function ‘intel_pstate_use_acpi_profile’
> > 
> > This changes it to look like the other one.
> Sorry about that.

Since this is a compile issue for x86 non ACPI systems, which will be a
problem for git bisect, it is better to resubmit my patch with the fix.

Thanks,
Srinivas

^ permalink raw reply

* [PATCH v3] RFC: pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP
From: Linus Walleij @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Eric Anholt, Stephen Warren, Lee Jones, linux-gpio
  Cc: linux-rpi-kernel, Linus Walleij, Stefan Wahren

It should be possible to use the GPIOLIB_IRQCHIP helper
library with the BCM2835 driver since it is a pretty straight
forward cascaded irqchip.

The only difference from other drivers is that the BCM2835
has several banks for a single gpiochip, and each bank has
a separate IRQ line. Instead of creating one gpiochip per
bank, a single gpiochip covers all banks GPIO lines. This
makes it necessary to resolve the bank ID in the IRQ
handler.

The GPIOLIB_IRQCHIP allows several IRQs to be cascaded off
the same gpiochip by calling gpiochip_set_chained_irqchip()
repeatedly, but we have been a bit short on examples
for how this should be handled in practice, so this is intended
as an example of how this can be achieved.

The old code did not model the chip as a chained interrupt
handler, but this patch also rectifies that situation.

Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Eric Anholt <eric@anholt.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Rebase on top of the two new patches from the vendor tree.
ChangeLog v1->v2:
- Forgot to convert the driver to chained IRQ handler. Now fixed.

Rpi folks: I have no clue if this works or not, but would be happy
if you could test it to see if IRQs fire as expected and provide
some feedback.
---
 drivers/pinctrl/bcm/Kconfig           |   1 +
 drivers/pinctrl/bcm/pinctrl-bcm2835.c | 140 ++++++++++++++++------------------
 2 files changed, 65 insertions(+), 76 deletions(-)

diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index 63246770bd74..8968dd7aebed 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -20,6 +20,7 @@ config PINCTRL_BCM2835
 	bool
 	select PINMUX
 	select PINCONF
+	select GPIOLIB_IRQCHIP
 
 config PINCTRL_IPROC_GPIO
 	bool "Broadcom iProc GPIO (with PINCONF) driver"
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 6128359d3281..1bb38d0493eb 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -24,11 +24,9 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/driver.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
-#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
@@ -87,11 +85,6 @@ enum bcm2835_pinconf_pull {
 #define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
 #define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
 
-struct bcm2835_gpio_irqdata {
-	struct bcm2835_pinctrl *pc;
-	int irqgroup;
-};
-
 struct bcm2835_pinctrl {
 	struct device *dev;
 	void __iomem *base;
@@ -102,16 +95,13 @@ struct bcm2835_pinctrl {
 	unsigned int irq_type[BCM2835_NUM_GPIOS];
 
 	struct pinctrl_dev *pctl_dev;
-	struct irq_domain *irq_domain;
 	struct gpio_chip gpio_chip;
 	struct pinctrl_gpio_range gpio_range;
 
-	struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_IRQS];
+	int irq_group[BCM2835_NUM_IRQS];
 	spinlock_t irq_lock[BCM2835_NUM_BANKS];
 };
 
-static struct lock_class_key gpio_lock_class;
-
 /* pins are just named GPIO0..GPIO53 */
 #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
 static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
@@ -369,13 +359,6 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
 	return pinctrl_gpio_direction_output(chip->base + offset);
 }
 
-static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
-
-	return irq_linear_revmap(pc->irq_domain, offset);
-}
-
 static struct gpio_chip bcm2835_gpio_chip = {
 	.label = MODULE_NAME,
 	.owner = THIS_MODULE,
@@ -386,14 +369,13 @@ static struct gpio_chip bcm2835_gpio_chip = {
 	.get_direction = bcm2835_gpio_get_direction,
 	.get = bcm2835_gpio_get,
 	.set = bcm2835_gpio_set,
-	.to_irq = bcm2835_gpio_to_irq,
 	.base = -1,
 	.ngpio = BCM2835_NUM_GPIOS,
 	.can_sleep = false,
 };
 
-static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
-					unsigned int bank, u32 mask)
+static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
+					 unsigned int bank, u32 mask)
 {
 	unsigned long events;
 	unsigned offset;
@@ -405,34 +387,49 @@ static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
 	events &= pc->enabled_irq_map[bank];
 	for_each_set_bit(offset, &events, 32) {
 		gpio = (32 * bank) + offset;
+		/* FIXME: no clue why the code looks up the type here */
 		type = pc->irq_type[gpio];
 
-		generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio));
+		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain,
+						     gpio));
 	}
-
-	return (events != 0);
 }
 
-static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id)
+static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
 {
-	struct bcm2835_gpio_irqdata *irqdata = dev_id;
-	struct bcm2835_pinctrl *pc = irqdata->pc;
-	int handled = 0;
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+	struct irq_chip *host_chip = irq_desc_get_chip(desc);
+	int irq = irq_desc_get_irq(desc);
+	int group;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pc->irq); i++) {
+		if (pc->irq[i] == irq) {
+			group = pc->irq_group[i];
+			break;
+		}
+	}
+	/* This should not happen, every IRQ has a bank */
+	if (i == ARRAY_SIZE(pc->irq))
+		BUG();
 
-	switch (irqdata->irqgroup) {
+	chained_irq_enter(host_chip, desc);
+
+	switch (group) {
 	case 0: /* IRQ0 covers GPIOs 0-27 */
-		handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
+		bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
 		break;
 	case 1: /* IRQ1 covers GPIOs 28-45 */
-		handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000) |
-			  bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
+		bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
+		bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
 		break;
 	case 2: /* IRQ2 covers GPIOs 46-53 */
-		handled = bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
+		bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
 		break;
 	}
 
-	return handled ? IRQ_HANDLED : IRQ_NONE;
+	chained_irq_exit(host_chip, desc);
 }
 
 static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
@@ -478,7 +475,8 @@ static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
 
 static void bcm2835_gpio_irq_enable(struct irq_data *data)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 	unsigned offset = GPIO_REG_SHIFT(gpio);
 	unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -492,7 +490,8 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
 
 static void bcm2835_gpio_irq_disable(struct irq_data *data)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 	unsigned offset = GPIO_REG_SHIFT(gpio);
 	unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -598,7 +597,8 @@ static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
 
 static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 	unsigned offset = GPIO_REG_SHIFT(gpio);
 	unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -624,7 +624,8 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 
 static void bcm2835_gpio_irq_ack(struct irq_data *data)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 
 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
@@ -667,10 +668,11 @@ static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 		unsigned offset)
 {
 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_chip *chip = &pc->gpio_chip;
 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
 	const char *fname = bcm2835_functions[fsel];
 	int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
-	int irq = irq_find_mapping(pc->irq_domain, offset);
+	int irq = irq_find_mapping(chip->irqdomain, offset);
 
 	seq_printf(s, "function %s in %s; irq %d (%s)",
 		fname, value ? "hi" : "lo",
@@ -1016,21 +1018,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 	pc->gpio_chip.parent = dev;
 	pc->gpio_chip.of_node = np;
 
-	pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
-			&irq_domain_simple_ops, NULL);
-	if (!pc->irq_domain) {
-		dev_err(dev, "could not create IRQ domain\n");
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
-		int irq = irq_create_mapping(pc->irq_domain, i);
-		irq_set_lockdep_class(irq, &gpio_lock_class);
-		irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
-				handle_level_irq);
-		irq_set_chip_data(irq, pc);
-	}
-
 	for (i = 0; i < BCM2835_NUM_BANKS; i++) {
 		unsigned long events;
 		unsigned offset;
@@ -1051,34 +1038,35 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 		spin_lock_init(&pc->irq_lock[i]);
 	}
 
-	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
-		int len;
-		char *name;
-		pc->irq[i] = irq_of_parse_and_map(np, i);
-		pc->irq_data[i].pc = pc;
-		pc->irq_data[i].irqgroup = i;
-
-		len = strlen(dev_name(pc->dev)) + 16;
-		name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
-		if (!name)
-			return -ENOMEM;
-		snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
-
-		err = devm_request_irq(dev, pc->irq[i],
-			bcm2835_gpio_irq_handler, IRQF_SHARED,
-			name, &pc->irq_data[i]);
-		if (err) {
-			dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
-			return err;
-		}
-	}
-
 	err = gpiochip_add_data(&pc->gpio_chip, pc);
 	if (err) {
 		dev_err(dev, "could not add GPIO chip\n");
 		return err;
 	}
 
+	err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip,
+				   0, handle_level_irq, IRQ_TYPE_NONE);
+	if (err) {
+		dev_info(dev, "could not add irqchip\n");
+		return err;
+	}
+
+	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
+		pc->irq[i] = irq_of_parse_and_map(np, i);
+		pc->irq_group[i] = i;
+		/*
+		 * Use the same handler for all groups: this is necessary
+		 * since we use one gpiochip to cover all lines - the
+		 * irq handler then needs to figure out which group and
+		 * bank that was firing the IRQ and look up the per-group
+		 * and bank data.
+		 */
+		gpiochip_set_chained_irqchip(&pc->gpio_chip,
+					     &bcm2835_gpio_irq_chip,
+					     pc->irq[i],
+					     bcm2835_gpio_irq_handler);
+	}
+
 	pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
 	if (IS_ERR(pc->pctl_dev)) {
 		gpiochip_remove(&pc->gpio_chip);
-- 
2.7.4


^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479145933-9849-1-git-send-email-srinivas.kandagatla@linaro.org>

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 arch/arm/boot/dts/qcom-apq8064.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 268bd47..c61ba32 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -627,6 +627,33 @@
 			clock-names = "core";
 		};
 
+		ssbi at c00000 {
+			compatible = "qcom,ssbi";
+			reg = <0x00c00000 0x1000>;
+			qcom,controller-type = "pmic-arbiter";
+
+			pm8821: pmic at 1 {
+				compatible = "qcom,pm8821";
+				interrupt-parent = <&tlmm_pinmux>;
+				interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+				#interrupt-cells = <2>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pm8821_mpps: mpps at 50 {
+					compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
+					reg = <0x50>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>;
+					gpio-controller;
+					#gpio-cells = <2>;
+		                };
+			};
+		};
+
 		qcom,ssbi at 500000 {
 			compatible = "qcom,ssbi";
 			reg = <0x00500000 0x1000>;
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Lee Jones
  Cc: bjorn.andersson, Rob Herring, Andy Gross, devicetree,
	linux-kernel, linux-arm-msm, linux-soc, linux-arm-kernel,
	Srinivas Kandagatla
In-Reply-To: <1479145933-9849-1-git-send-email-srinivas.kandagatla@linaro.org>

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 arch/arm/boot/dts/qcom-apq8064.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 268bd47..c61ba32 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -627,6 +627,33 @@
 			clock-names = "core";
 		};
 
+		ssbi@c00000 {
+			compatible = "qcom,ssbi";
+			reg = <0x00c00000 0x1000>;
+			qcom,controller-type = "pmic-arbiter";
+
+			pm8821: pmic@1 {
+				compatible = "qcom,pm8821";
+				interrupt-parent = <&tlmm_pinmux>;
+				interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+				#interrupt-cells = <2>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pm8821_mpps: mpps@50 {
+					compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
+					reg = <0x50>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>;
+					gpio-controller;
+					#gpio-cells = <2>;
+		                };
+			};
+		};
+
 		qcom,ssbi@500000 {
 			compatible = "qcom,ssbi";
 			reg = <0x00500000 0x1000>;
-- 
2.10.1

^ permalink raw reply related


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.