Re: [PATCH 1/6] perf: Add new type PERF_TYPE_PROBE

2017-11-26 Thread Peter Zijlstra
On Sat, Nov 25, 2017 at 05:59:54PM -0800, Alexei Starovoitov wrote:

> If we were poking into 'struct perf_event_attr __user *uptr'
> directly like get|put_user(.., >config)
> then 32-bit user space with 4-byte aligned u64s would cause
> 64-bit kernel to trap on archs like sparc.

But surely archs that have hardware alignment requirements have __u64 ==
__aligned_u64 ?

It's just that the structure layout can change between archs that have
__u64 != __aligned_u64 and __u64 == __aligned_u64.

But I would argue an architecture that has hardware alignment
requirements and has an unaligned __u64 is just plain broken.

> But in this case you're right. We can use config[12] as-is, since these
> u64 fields are passing the value one way only (into the kernel) and
> we do full perf_copy_attr() first and all further accesses are from
> copied structure and u64_to_user_ptr(event->attr.config) will be fine.

Right. Also note that there are no holes in perf_event_attr, if the
structure itself is allocated aligned the individual fields will be
aligned.

> Do you mind we do
> union {
>  __u64 file_path;
>  __u64 func_name;
>  __u64 config;
> };
> and similar with config1 ?

> Or prefer that we use 'config/config1' to store string+offset there?
> I think config/config1 is cleaner than config1/config2

I would prefer you use config1/config2 for this and leave config itself
for modifiers (like the retprobe thing). It also better lines up with
the BP stuff.

A little something like so perhaps:

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 362493a2f950..b6e76512f757 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -380,10 +380,14 @@ struct perf_event_attr {
__u32   bp_type;
union {
__u64   bp_addr;
+   __u64   uprobe_path;
+   __u64   kprobe_func;
__u64   config1; /* extension of config */
};
union {
__u64   bp_len;
+   __u64   kprobe_addr;
+   __u64   probe_offset;
__u64   config2; /* extension of config1 */
};
__u64   branch_sample_type; /* enum perf_branch_sample_type */





Re: [PATCH 1/6] perf: Add new type PERF_TYPE_PROBE

2017-11-26 Thread Peter Zijlstra
On Sat, Nov 25, 2017 at 05:59:54PM -0800, Alexei Starovoitov wrote:

> If we were poking into 'struct perf_event_attr __user *uptr'
> directly like get|put_user(.., >config)
> then 32-bit user space with 4-byte aligned u64s would cause
> 64-bit kernel to trap on archs like sparc.

But surely archs that have hardware alignment requirements have __u64 ==
__aligned_u64 ?

It's just that the structure layout can change between archs that have
__u64 != __aligned_u64 and __u64 == __aligned_u64.

But I would argue an architecture that has hardware alignment
requirements and has an unaligned __u64 is just plain broken.

> But in this case you're right. We can use config[12] as-is, since these
> u64 fields are passing the value one way only (into the kernel) and
> we do full perf_copy_attr() first and all further accesses are from
> copied structure and u64_to_user_ptr(event->attr.config) will be fine.

Right. Also note that there are no holes in perf_event_attr, if the
structure itself is allocated aligned the individual fields will be
aligned.

> Do you mind we do
> union {
>  __u64 file_path;
>  __u64 func_name;
>  __u64 config;
> };
> and similar with config1 ?

> Or prefer that we use 'config/config1' to store string+offset there?
> I think config/config1 is cleaner than config1/config2

I would prefer you use config1/config2 for this and leave config itself
for modifiers (like the retprobe thing). It also better lines up with
the BP stuff.

A little something like so perhaps:

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 362493a2f950..b6e76512f757 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -380,10 +380,14 @@ struct perf_event_attr {
__u32   bp_type;
union {
__u64   bp_addr;
+   __u64   uprobe_path;
+   __u64   kprobe_func;
__u64   config1; /* extension of config */
};
union {
__u64   bp_len;
+   __u64   kprobe_addr;
+   __u64   probe_offset;
__u64   config2; /* extension of config1 */
};
__u64   branch_sample_type; /* enum perf_branch_sample_type */





Re: [PATCH] input: pegasus_notetaker: add license information

2017-11-26 Thread Greg Kroah-Hartman
On Sun, Nov 26, 2017 at 12:28:49PM +0100, Philippe Ombredanne wrote:
> Greg, Martin:
> 
> On Sun, Nov 26, 2017 at 9:59 AM, Greg Kroah-Hartman
>  wrote:
> > On Sat, Nov 25, 2017 at 04:42:59PM -0800, Dmitry Torokhov wrote:
> >> Hi Martin,
> >>
> >> On Sat, Nov 18, 2017 at 09:45:18AM +0100, Martin Kepplinger wrote:
> >> > This adds an SPDX license identifier to this driver I wrote some time 
> >> > back.
> >> >
> >> > Signed-off-by: Martin Kepplinger 
> >> > ---
> >> >  drivers/input/tablet/pegasus_notetaker.c | 1 +
> >> >  1 file changed, 1 insertion(+)
> >> >
> >> > diff --git a/drivers/input/tablet/pegasus_notetaker.c 
> >> > b/drivers/input/tablet/pegasus_notetaker.c
> >> > index 47de5a81172f..cdf75c989469 100644
> >> > --- a/drivers/input/tablet/pegasus_notetaker.c
> >> > +++ b/drivers/input/tablet/pegasus_notetaker.c
> >> > @@ -1,3 +1,4 @@
> >> > +// SPDX-License-Identifier: GPL-2.0
> >>
> >> Should this be GPL-2.0+? The MODULE_LICENSE specifies that the module is
> >> "GPL" which in kernel land means GPLv2+. Or we should change the module
> >> license to strict "GPLv2"?
> >
> > That is up to Martin, given that he is the author, as to what he wants
> > to mark this as.  Odd that it missed the big "fix up all files with no
> > license information" sweep.
> >
> > Philippe, how did we miss this one?
> 
> It was not missed but instead was set aside by design.
> drivers/input/tablet/pegasus_notetaker.c does not have (or rather did
> not have until now) any licensing information beside a
> MODULE_LICENSE("GPL") and these were left aside as requiring some
> extra review and the eventual need of a clarification by the author,
> just as Martin is rightfully doing so just now.

Ah, thanks for the explaination, that makes more sense.

> >> Doing this would prevent mismatches between license notices, SPDX tags
> >> and MODULE_LCENSE() strings, which happen very often.
> >
> > I agree, but now that we are getting SPDX tags, we can fix up all of the
> > mismatches in MODULE_LICENSE() strings, of which there are a lot.
> 
> I said that I would take a stab at it... but I did not attack this yet:
> Let me get over the ThanksGiving hangover and provide a list this
> week. I guess there could be three lists in fact:
> 
> - modules with only a MODULE_LICENSE and no other license info: these
> could be candidates for adding an SPDX id matching the MODULE_LICENSE
> 
> - modules updated to use an SPDX id and with a conflicting
> MODULE_LICENSE: the MODULE_LICENSE should be aligned to match the SPDX
> id
> 
> - modules not yet updated to use an SPDX id and with a license notice
> conflicting with the MODULE_LICENSE: the MODULE_LICENSE should be
> aligned to match the licensing
> 
> I'll run a scancode-toolkit scan on the tip of Linus' tree and create
> a CSV from that to surface these oddities.
> Unless you prefer me to use another tree like on the USB side for a start.

Just doing a big sweep of all of 4.15-rc1 to catch the new files /
deleted files for the large "here is a first pass of what the spdx id
should be" like you did before would be great as we are working with the
4.14 info at the moment.

Any additional work on the MODULE_LICENSE stuff would also be wonderful,
but might be a bit premature given that we don't have much SPDX coverage
at the moment.

But, if you want to try out the MODULE_LICENSE stuff, doing it on
drivers/usb/ would be great as that should be all finished with SPDX
tags now.

thanks,

greg k-h


Re: [PATCH] input: pegasus_notetaker: add license information

2017-11-26 Thread Greg Kroah-Hartman
On Sun, Nov 26, 2017 at 12:28:49PM +0100, Philippe Ombredanne wrote:
> Greg, Martin:
> 
> On Sun, Nov 26, 2017 at 9:59 AM, Greg Kroah-Hartman
>  wrote:
> > On Sat, Nov 25, 2017 at 04:42:59PM -0800, Dmitry Torokhov wrote:
> >> Hi Martin,
> >>
> >> On Sat, Nov 18, 2017 at 09:45:18AM +0100, Martin Kepplinger wrote:
> >> > This adds an SPDX license identifier to this driver I wrote some time 
> >> > back.
> >> >
> >> > Signed-off-by: Martin Kepplinger 
> >> > ---
> >> >  drivers/input/tablet/pegasus_notetaker.c | 1 +
> >> >  1 file changed, 1 insertion(+)
> >> >
> >> > diff --git a/drivers/input/tablet/pegasus_notetaker.c 
> >> > b/drivers/input/tablet/pegasus_notetaker.c
> >> > index 47de5a81172f..cdf75c989469 100644
> >> > --- a/drivers/input/tablet/pegasus_notetaker.c
> >> > +++ b/drivers/input/tablet/pegasus_notetaker.c
> >> > @@ -1,3 +1,4 @@
> >> > +// SPDX-License-Identifier: GPL-2.0
> >>
> >> Should this be GPL-2.0+? The MODULE_LICENSE specifies that the module is
> >> "GPL" which in kernel land means GPLv2+. Or we should change the module
> >> license to strict "GPLv2"?
> >
> > That is up to Martin, given that he is the author, as to what he wants
> > to mark this as.  Odd that it missed the big "fix up all files with no
> > license information" sweep.
> >
> > Philippe, how did we miss this one?
> 
> It was not missed but instead was set aside by design.
> drivers/input/tablet/pegasus_notetaker.c does not have (or rather did
> not have until now) any licensing information beside a
> MODULE_LICENSE("GPL") and these were left aside as requiring some
> extra review and the eventual need of a clarification by the author,
> just as Martin is rightfully doing so just now.

Ah, thanks for the explaination, that makes more sense.

> >> Doing this would prevent mismatches between license notices, SPDX tags
> >> and MODULE_LCENSE() strings, which happen very often.
> >
> > I agree, but now that we are getting SPDX tags, we can fix up all of the
> > mismatches in MODULE_LICENSE() strings, of which there are a lot.
> 
> I said that I would take a stab at it... but I did not attack this yet:
> Let me get over the ThanksGiving hangover and provide a list this
> week. I guess there could be three lists in fact:
> 
> - modules with only a MODULE_LICENSE and no other license info: these
> could be candidates for adding an SPDX id matching the MODULE_LICENSE
> 
> - modules updated to use an SPDX id and with a conflicting
> MODULE_LICENSE: the MODULE_LICENSE should be aligned to match the SPDX
> id
> 
> - modules not yet updated to use an SPDX id and with a license notice
> conflicting with the MODULE_LICENSE: the MODULE_LICENSE should be
> aligned to match the licensing
> 
> I'll run a scancode-toolkit scan on the tip of Linus' tree and create
> a CSV from that to surface these oddities.
> Unless you prefer me to use another tree like on the USB side for a start.

Just doing a big sweep of all of 4.15-rc1 to catch the new files /
deleted files for the large "here is a first pass of what the spdx id
should be" like you did before would be great as we are working with the
4.14 info at the moment.

Any additional work on the MODULE_LICENSE stuff would also be wonderful,
but might be a bit premature given that we don't have much SPDX coverage
at the moment.

But, if you want to try out the MODULE_LICENSE stuff, doing it on
drivers/usb/ would be great as that should be all finished with SPDX
tags now.

thanks,

greg k-h


[PATCH 1/1] timecounter: Make cyclecounter struct part of timecounter struct

2017-11-26 Thread Sagar Arun Kamble
There is no real need for the users of timecounters to define cyclecounter
and timecounter variables separately. Since timecounter will always be
based on cyclecounter, have cyclecounter struct as member of timecounter
struct.

Suggested-by: Chris Wilson 
Signed-off-by: Sagar Arun Kamble 
Cc: John Stultz 
Cc: Thomas Gleixner 
Cc: Stephen Boyd 
Cc: linux-kernel@vger.kernel.org
---
 arch/microblaze/kernel/timer.c | 20 ++---
 drivers/clocksource/arm_arch_timer.c   | 19 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c   |  3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-ptp.c   |  9 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h   |  1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h|  1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   | 20 ++---
 drivers/net/ethernet/freescale/fec.h   |  1 -
 drivers/net/ethernet/freescale/fec_ptp.c   | 31 ++-
 drivers/net/ethernet/intel/e1000e/e1000.h  |  1 -
 drivers/net/ethernet/intel/e1000e/netdev.c | 27 -
 drivers/net/ethernet/intel/e1000e/ptp.c|  2 +-
 drivers/net/ethernet/intel/igb/igb.h   |  1 -
 drivers/net/ethernet/intel/igb/igb_ptp.c   | 25 
 drivers/net/ethernet/intel/ixgbe/ixgbe.h   |  1 -
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c   | 17 +--
 drivers/net/ethernet/mellanox/mlx4/en_clock.c  | 28 -
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h   |  1 -
 drivers/net/ethernet/mellanox/mlx5/core/en.h   |  1 -
 drivers/net/ethernet/mellanox/mlx5/core/en_clock.c | 33 ++--
 drivers/net/ethernet/qlogic/qede/qede_ptp.c| 20 ++---
 drivers/net/ethernet/ti/cpts.c | 35 +++---
 drivers/net/ethernet/ti/cpts.h |  1 -
 include/linux/timecounter.h|  4 +--
 include/sound/hdaudio.h|  1 -
 kernel/time/timecounter.c  | 28 -
 sound/hda/hdac_stream.c|  7 +++--
 27 files changed, 160 insertions(+), 178 deletions(-)

diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 7de941c..b7f89e9 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -199,27 +199,25 @@ static u64 xilinx_read(struct clocksource *cs)
return (u64)xilinx_clock_read();
 }
 
-static struct timecounter xilinx_tc = {
-   .cc = NULL,
-};
-
 static u64 xilinx_cc_read(const struct cyclecounter *cc)
 {
return xilinx_read(NULL);
 }
 
-static struct cyclecounter xilinx_cc = {
-   .read = xilinx_cc_read,
-   .mask = CLOCKSOURCE_MASK(32),
-   .shift = 8,
+static struct timecounter xilinx_tc = {
+   .cc.read = xilinx_cc_read,
+   .cc.mask = CLOCKSOURCE_MASK(32),
+   .cc.mult = 0,
+   .cc.shift = 8,
 };
 
 static int __init init_xilinx_timecounter(void)
 {
-   xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
-   xilinx_cc.shift);
+   struct cyclecounter *cc = _tc.cc;
+
+   cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift);
 
-   timecounter_init(_tc, _cc, sched_clock());
+   timecounter_init(_tc, sched_clock());
 
return 0;
 }
diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index fd4b7f6..1d60ba0 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -177,11 +177,6 @@ static u64 arch_counter_read_cc(const struct cyclecounter 
*cc)
.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static struct cyclecounter cyclecounter __ro_after_init = {
-   .read   = arch_counter_read_cc,
-   .mask   = CLOCKSOURCE_MASK(56),
-};
-
 struct ate_acpi_oem_info {
char oem_id[ACPI_OEM_ID_SIZE + 1];
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
@@ -877,7 +872,10 @@ static u64 arch_counter_get_cntvct_mem(void)
return ((u64) vct_hi << 32) | vct_lo;
 }
 
-static struct arch_timer_kvm_info arch_timer_kvm_info;
+static struct arch_timer_kvm_info arch_timer_kvm_info = {
+   .timecounter.cc.read = arch_counter_read_cc,
+   .timecounter.cc.mask = CLOCKSOURCE_MASK(56),
+};
 
 struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 {
@@ -887,6 +885,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 static void __init arch_counter_register(unsigned type)
 {
u64 start_count;
+   struct cyclecounter *cc = _timer_kvm_info.timecounter.cc;
 
/* Register the CP15 based counter if we have one */
if (type & ARCH_TIMER_TYPE_CP15) {
@@ -905,10 +904,10 @@ static void __init arch_counter_register(unsigned type)
clocksource_counter.flags |= 

[PATCH 1/1] timecounter: Make cyclecounter struct part of timecounter struct

2017-11-26 Thread Sagar Arun Kamble
There is no real need for the users of timecounters to define cyclecounter
and timecounter variables separately. Since timecounter will always be
based on cyclecounter, have cyclecounter struct as member of timecounter
struct.

Suggested-by: Chris Wilson 
Signed-off-by: Sagar Arun Kamble 
Cc: John Stultz 
Cc: Thomas Gleixner 
Cc: Stephen Boyd 
Cc: linux-kernel@vger.kernel.org
---
 arch/microblaze/kernel/timer.c | 20 ++---
 drivers/clocksource/arm_arch_timer.c   | 19 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c   |  3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-ptp.c   |  9 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h   |  1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h|  1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   | 20 ++---
 drivers/net/ethernet/freescale/fec.h   |  1 -
 drivers/net/ethernet/freescale/fec_ptp.c   | 31 ++-
 drivers/net/ethernet/intel/e1000e/e1000.h  |  1 -
 drivers/net/ethernet/intel/e1000e/netdev.c | 27 -
 drivers/net/ethernet/intel/e1000e/ptp.c|  2 +-
 drivers/net/ethernet/intel/igb/igb.h   |  1 -
 drivers/net/ethernet/intel/igb/igb_ptp.c   | 25 
 drivers/net/ethernet/intel/ixgbe/ixgbe.h   |  1 -
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c   | 17 +--
 drivers/net/ethernet/mellanox/mlx4/en_clock.c  | 28 -
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h   |  1 -
 drivers/net/ethernet/mellanox/mlx5/core/en.h   |  1 -
 drivers/net/ethernet/mellanox/mlx5/core/en_clock.c | 33 ++--
 drivers/net/ethernet/qlogic/qede/qede_ptp.c| 20 ++---
 drivers/net/ethernet/ti/cpts.c | 35 +++---
 drivers/net/ethernet/ti/cpts.h |  1 -
 include/linux/timecounter.h|  4 +--
 include/sound/hdaudio.h|  1 -
 kernel/time/timecounter.c  | 28 -
 sound/hda/hdac_stream.c|  7 +++--
 27 files changed, 160 insertions(+), 178 deletions(-)

diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 7de941c..b7f89e9 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -199,27 +199,25 @@ static u64 xilinx_read(struct clocksource *cs)
return (u64)xilinx_clock_read();
 }
 
-static struct timecounter xilinx_tc = {
-   .cc = NULL,
-};
-
 static u64 xilinx_cc_read(const struct cyclecounter *cc)
 {
return xilinx_read(NULL);
 }
 
-static struct cyclecounter xilinx_cc = {
-   .read = xilinx_cc_read,
-   .mask = CLOCKSOURCE_MASK(32),
-   .shift = 8,
+static struct timecounter xilinx_tc = {
+   .cc.read = xilinx_cc_read,
+   .cc.mask = CLOCKSOURCE_MASK(32),
+   .cc.mult = 0,
+   .cc.shift = 8,
 };
 
 static int __init init_xilinx_timecounter(void)
 {
-   xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
-   xilinx_cc.shift);
+   struct cyclecounter *cc = _tc.cc;
+
+   cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift);
 
-   timecounter_init(_tc, _cc, sched_clock());
+   timecounter_init(_tc, sched_clock());
 
return 0;
 }
diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index fd4b7f6..1d60ba0 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -177,11 +177,6 @@ static u64 arch_counter_read_cc(const struct cyclecounter 
*cc)
.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static struct cyclecounter cyclecounter __ro_after_init = {
-   .read   = arch_counter_read_cc,
-   .mask   = CLOCKSOURCE_MASK(56),
-};
-
 struct ate_acpi_oem_info {
char oem_id[ACPI_OEM_ID_SIZE + 1];
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
@@ -877,7 +872,10 @@ static u64 arch_counter_get_cntvct_mem(void)
return ((u64) vct_hi << 32) | vct_lo;
 }
 
-static struct arch_timer_kvm_info arch_timer_kvm_info;
+static struct arch_timer_kvm_info arch_timer_kvm_info = {
+   .timecounter.cc.read = arch_counter_read_cc,
+   .timecounter.cc.mask = CLOCKSOURCE_MASK(56),
+};
 
 struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 {
@@ -887,6 +885,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 static void __init arch_counter_register(unsigned type)
 {
u64 start_count;
+   struct cyclecounter *cc = _timer_kvm_info.timecounter.cc;
 
/* Register the CP15 based counter if we have one */
if (type & ARCH_TIMER_TYPE_CP15) {
@@ -905,10 +904,10 @@ static void __init arch_counter_register(unsigned type)
clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
start_count = arch_timer_read_counter();
clocksource_register_hz(_counter, 

Re: [PATCH v2] input: pegasus_notetaker: add license information

2017-11-26 Thread Greg KH
On Mon, Nov 27, 2017 at 08:44:01AM +0100, Martin Kepplinger wrote:
> This adds an SPDX license identifier to this driver I wrote some time back.
> 
> Signed-off-by: Martin Kepplinger 
> ---
> 
> Thanks for the feedback. GPL2+ was what I had in mind. My bad. And as I
> already see a lot of SPDX tags using /**/ comments, I'll use that too.
> I think if it is hand-written, it shouldn't look too ugly. And in case
> that's really a no-go, it seems that many many files need to be changed
> again in any case.

.h files should be the only ones using /* */, and that is for the ones
that break the build if they use // (usually arch-specific and uapi
files)

So please use // as Linus asked to have done.

thanks,

greg k-h


Re: [PATCH v2] input: pegasus_notetaker: add license information

2017-11-26 Thread Greg KH
On Mon, Nov 27, 2017 at 08:44:01AM +0100, Martin Kepplinger wrote:
> This adds an SPDX license identifier to this driver I wrote some time back.
> 
> Signed-off-by: Martin Kepplinger 
> ---
> 
> Thanks for the feedback. GPL2+ was what I had in mind. My bad. And as I
> already see a lot of SPDX tags using /**/ comments, I'll use that too.
> I think if it is hand-written, it shouldn't look too ugly. And in case
> that's really a no-go, it seems that many many files need to be changed
> again in any case.

.h files should be the only ones using /* */, and that is for the ones
that break the build if they use // (usually arch-specific and uapi
files)

So please use // as Linus asked to have done.

thanks,

greg k-h


[lkp-robot] [x86/mm/kasan] d17a1d97dc: WARNING:at_lib/stackdepot.c:#depot_save_stack

2017-11-26 Thread kernel test robot

FYI, we noticed the following commit (built with gcc-7):

commit: d17a1d97dc208d664c91cc387ffb752c7f85dc61 ("x86/mm/kasan: don't use 
vmemmap_populate() to initialize shadow")
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master

in testcase: trinity
with following parameters:

runtime: 300s

test-description: Trinity is a linux system call fuzz tester.
test-url: http://codemonkey.org.uk/projects/trinity/


on test machine: qemu-system-x86_64 -enable-kvm -m 512M

caused below changes (please refer to attached dmesg/kmsg for entire 
log/backtrace):


+---+++
|   | a4a3ede213 | 
d17a1d97dc |
+---+++
| boot_successes| 0  | 0
  |
| boot_failures | 10 | 8
  |
| WARNING:possible_circular_locking_dependency_detected | 10 | 8
  |
| WARNING:at_lib/stackdepot.c:#depot_save_stack | 0  | 8
  |
| RIP:depot_save_stack  | 0  | 8
  |
+---+++



[  177.837316] WARNING: CPU: 0 PID: 545 at lib/stackdepot.c:119 
depot_save_stack+0x28e/0x550
[  177.837987] CPU: 0 PID: 545 Comm: trinity-main Not tainted 
4.14.0-04319-gd17a1d9 #30
[  177.838518] task: 88000cd8 task.stack: 88000b4f8000
[  177.838933] RIP: 0010:depot_save_stack+0x28e/0x550
[  177.839268] RSP: 0018:88000b4fec18 EFLAGS: 00010086
[  177.839632] RAX: 0022 RBX: 6bdd725e RCX: a014cf41
[  177.840127] RDX:  RSI: dc00 RDI: 
[  177.840619] RBP:  R08: 0001 R09: 0001
[  177.841117] R10: 32ae8775 R11: 6f706564206b6361 R12: 0040
[  177.841609] R13: 0040 R14: 000d725e R15: 0220
[  177.842104] FS:  0104a880() GS:a2ca4000() 
knlGS:
[  177.842663] CS:  0010 DS:  ES:  CR0: 80050033
[  177.843061] CR2: 7f3301646000 CR3: 0b1c2000 CR4: 06b0
[  177.843553] DR0:  DR1:  DR2: 
[  177.844046] DR3:  DR6: fffe0ff0 DR7: 0400
[  177.844535] Call Trace:
[  177.844721]  ? kasan_kmalloc+0x144/0x160
[  177.844999]  ? depot_save_stack+0x1f5/0x550
[  177.845295]  ? do_raw_spin_unlock+0xda/0xf0
[  177.845590]  ? preempt_count_sub+0x13/0xc0
[  177.845887]  ? _raw_spin_unlock_irqrestore+0x52/0x70
[  177.846236]  ? depot_save_stack+0x3b8/0x550
[  177.846533]  ? kasan_kmalloc+0x144/0x160
[  177.846816]  ? do_raw_spin_unlock+0xda/0xf0
[  177.847113]  ? preempt_count_sub+0x13/0xc0
[  177.847404]  ? _raw_spin_unlock+0x29/0x40
[  177.847693]  ? get_partial_node+0x2ca/0x300
[  177.848031]  ? preempt_count_sub+0x13/0xc0
[  177.848321]  ? __might_sleep+0x2e/0xd0
[  177.848591]  ? perf_output_begin_backward+0x840/0x840
[  177.848952]  ? __vm_enough_memory+0x333/0x390
[  177.849260]  ? preempt_count_sub+0x13/0xc0
[  177.849551]  ? in_sched_functions+0x30/0x30
[  177.849851]  ? preempt_count_sub+0x13/0xc0
[  177.850142]  ? __vm_enough_memory+0x333/0x390
[  177.850453]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.850794]  ? in_sched_functions+0x30/0x30
[  177.851090]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.851425]  ? in_sched_functions+0x30/0x30
[  177.851724]  ? fs_reclaim_acquire+0xd/0x30
[  177.852013]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.852348]  ? in_sched_functions+0x30/0x30
[  177.852642]  ? fs_reclaim_acquire+0xd/0x30
[  177.852936]  ? ___slab_alloc+0x2f9/0x330
[  177.853334]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.853673]  ? ___slab_alloc+0x2f9/0x330
[  177.854070]  ? preempt_count_add+0xa6/0xc0
[  177.854358]  ? preempt_count_sub+0x13/0xc0
[  177.854647]  ? __vm_enough_memory+0x333/0x390
[  177.854956]  ? vm_memory_committed+0x10/0x10
[  177.855257]  ? __cleanup_sighand+0x30/0x30
[  177.855545]  ? rb_erase_cached+0x43a/0x1230
[  177.855845]  ? debug_show_all_locks+0x2c0/0x2c0
[  177.856176]  ? rb_next+0x80/0x80
[  177.856409]  ? __need_fs_reclaim+0x2d/0x80
[  177.856704]  ? kmem_cache_alloc+0xd4/0xf0
[  177.856991]  ? anon_vma_clone+0x6e/0x280
[  177.857271]  ? anon_vma_fork+0xb9/0x2f0
[  177.857545]  ? rcu_segcblist_enqueue+0xe7/0x130
[  177.857868]  ? rcu_segcblist_first_pend_cb+0x40/0x40
[  177.858217]  ? anon_vma_clone+0x280/0x280
[  177.858503]  ? __rcu_read_lock+0x20/0x20
[  177.858787]  ? trace_hardirqs_on_caller+0x11/0x260
[  177.859125]  ? lock_downgrade+0x300/0x300
[  177.859409]  ? lock_acquire+0x99/0xd0
[  177.859674]  ? perf_event_task_disable+0xe0/0xe0
[  177.86]  ? copy_process+0x209c/0x3b60
[  177.860285]  ? 

[lkp-robot] [x86/mm/kasan] d17a1d97dc: WARNING:at_lib/stackdepot.c:#depot_save_stack

2017-11-26 Thread kernel test robot

FYI, we noticed the following commit (built with gcc-7):

commit: d17a1d97dc208d664c91cc387ffb752c7f85dc61 ("x86/mm/kasan: don't use 
vmemmap_populate() to initialize shadow")
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master

in testcase: trinity
with following parameters:

runtime: 300s

test-description: Trinity is a linux system call fuzz tester.
test-url: http://codemonkey.org.uk/projects/trinity/


on test machine: qemu-system-x86_64 -enable-kvm -m 512M

caused below changes (please refer to attached dmesg/kmsg for entire 
log/backtrace):


+---+++
|   | a4a3ede213 | 
d17a1d97dc |
+---+++
| boot_successes| 0  | 0
  |
| boot_failures | 10 | 8
  |
| WARNING:possible_circular_locking_dependency_detected | 10 | 8
  |
| WARNING:at_lib/stackdepot.c:#depot_save_stack | 0  | 8
  |
| RIP:depot_save_stack  | 0  | 8
  |
+---+++



[  177.837316] WARNING: CPU: 0 PID: 545 at lib/stackdepot.c:119 
depot_save_stack+0x28e/0x550
[  177.837987] CPU: 0 PID: 545 Comm: trinity-main Not tainted 
4.14.0-04319-gd17a1d9 #30
[  177.838518] task: 88000cd8 task.stack: 88000b4f8000
[  177.838933] RIP: 0010:depot_save_stack+0x28e/0x550
[  177.839268] RSP: 0018:88000b4fec18 EFLAGS: 00010086
[  177.839632] RAX: 0022 RBX: 6bdd725e RCX: a014cf41
[  177.840127] RDX:  RSI: dc00 RDI: 
[  177.840619] RBP:  R08: 0001 R09: 0001
[  177.841117] R10: 32ae8775 R11: 6f706564206b6361 R12: 0040
[  177.841609] R13: 0040 R14: 000d725e R15: 0220
[  177.842104] FS:  0104a880() GS:a2ca4000() 
knlGS:
[  177.842663] CS:  0010 DS:  ES:  CR0: 80050033
[  177.843061] CR2: 7f3301646000 CR3: 0b1c2000 CR4: 06b0
[  177.843553] DR0:  DR1:  DR2: 
[  177.844046] DR3:  DR6: fffe0ff0 DR7: 0400
[  177.844535] Call Trace:
[  177.844721]  ? kasan_kmalloc+0x144/0x160
[  177.844999]  ? depot_save_stack+0x1f5/0x550
[  177.845295]  ? do_raw_spin_unlock+0xda/0xf0
[  177.845590]  ? preempt_count_sub+0x13/0xc0
[  177.845887]  ? _raw_spin_unlock_irqrestore+0x52/0x70
[  177.846236]  ? depot_save_stack+0x3b8/0x550
[  177.846533]  ? kasan_kmalloc+0x144/0x160
[  177.846816]  ? do_raw_spin_unlock+0xda/0xf0
[  177.847113]  ? preempt_count_sub+0x13/0xc0
[  177.847404]  ? _raw_spin_unlock+0x29/0x40
[  177.847693]  ? get_partial_node+0x2ca/0x300
[  177.848031]  ? preempt_count_sub+0x13/0xc0
[  177.848321]  ? __might_sleep+0x2e/0xd0
[  177.848591]  ? perf_output_begin_backward+0x840/0x840
[  177.848952]  ? __vm_enough_memory+0x333/0x390
[  177.849260]  ? preempt_count_sub+0x13/0xc0
[  177.849551]  ? in_sched_functions+0x30/0x30
[  177.849851]  ? preempt_count_sub+0x13/0xc0
[  177.850142]  ? __vm_enough_memory+0x333/0x390
[  177.850453]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.850794]  ? in_sched_functions+0x30/0x30
[  177.851090]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.851425]  ? in_sched_functions+0x30/0x30
[  177.851724]  ? fs_reclaim_acquire+0xd/0x30
[  177.852013]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.852348]  ? in_sched_functions+0x30/0x30
[  177.852642]  ? fs_reclaim_acquire+0xd/0x30
[  177.852936]  ? ___slab_alloc+0x2f9/0x330
[  177.853334]  ? debug_lockdep_rcu_enabled+0x27/0x60
[  177.853673]  ? ___slab_alloc+0x2f9/0x330
[  177.854070]  ? preempt_count_add+0xa6/0xc0
[  177.854358]  ? preempt_count_sub+0x13/0xc0
[  177.854647]  ? __vm_enough_memory+0x333/0x390
[  177.854956]  ? vm_memory_committed+0x10/0x10
[  177.855257]  ? __cleanup_sighand+0x30/0x30
[  177.855545]  ? rb_erase_cached+0x43a/0x1230
[  177.855845]  ? debug_show_all_locks+0x2c0/0x2c0
[  177.856176]  ? rb_next+0x80/0x80
[  177.856409]  ? __need_fs_reclaim+0x2d/0x80
[  177.856704]  ? kmem_cache_alloc+0xd4/0xf0
[  177.856991]  ? anon_vma_clone+0x6e/0x280
[  177.857271]  ? anon_vma_fork+0xb9/0x2f0
[  177.857545]  ? rcu_segcblist_enqueue+0xe7/0x130
[  177.857868]  ? rcu_segcblist_first_pend_cb+0x40/0x40
[  177.858217]  ? anon_vma_clone+0x280/0x280
[  177.858503]  ? __rcu_read_lock+0x20/0x20
[  177.858787]  ? trace_hardirqs_on_caller+0x11/0x260
[  177.859125]  ? lock_downgrade+0x300/0x300
[  177.859409]  ? lock_acquire+0x99/0xd0
[  177.859674]  ? perf_event_task_disable+0xe0/0xe0
[  177.86]  ? copy_process+0x209c/0x3b60
[  177.860285]  ? 

[PATCH] x86/mm/kmmio: Fix mmiotrace for page unaligned addresses

2017-11-26 Thread Karol Herbst
If something calls ioremap with an address not aligned to PAGE_SIZE, the
returned address might be not aligned as well. This led to a probe
registered on exactly the returned address, but the entire page was armed
for mmiotracing.

On calling iounmap the address passed to unregister_kmmio_probe was
PAGE_SIZE aligned by the caller leading to a complete freeze of the
machine.

We should always page align addresses while (un)registerung mappings,
because the mmiotracer works on top of pages, not mappings. We still keep
track of the probes based on their real addresses and lengths though,
because the mmiotrace still needs to know what are mapped memory regions.

Also move the call to mmiotrace_iounmap prior page aligning the address,
so that all probes are unregistered properly, otherwise the kernel ends up
failing memory allocations randomly after disabling the mmiotracer.

Cc: Steven Rostedt 
Cc: Ingo Molnar 
Cc: Thomas Gleixner 
Cc: Pekka Paalanen 
Cc: nouv...@lists.freedesktop.org
Cc: x...@kernel.org
Acked-by: Pekka Paalanen 
Tested-by: Lyude 
Signed-off-by: Karol Herbst 
---
 arch/x86/mm/ioremap.c |  4 ++--
 arch/x86/mm/kmmio.c   | 12 +++-
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 34f0e1847dd6..5d4c358778dd 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -349,11 +349,11 @@ void iounmap(volatile void __iomem *addr)
return;
}
 
+   mmiotrace_iounmap(addr);
+
addr = (volatile void __iomem *)
(PAGE_MASK & (unsigned long __force)addr);
 
-   mmiotrace_iounmap(addr);
-
/* Use the vm area unlocked, assuming the caller
   ensures there isn't another iounmap for the same address
   in parallel. Reuse of the virtual address is prevented by
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index c21c2ed04612..58477ec3d66d 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -435,17 +435,18 @@ int register_kmmio_probe(struct kmmio_probe *p)
unsigned long flags;
int ret = 0;
unsigned long size = 0;
+   unsigned long addr = p->addr & PAGE_MASK;
const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK);
unsigned int l;
pte_t *pte;
 
spin_lock_irqsave(_lock, flags);
-   if (get_kmmio_probe(p->addr)) {
+   if (get_kmmio_probe(addr)) {
ret = -EEXIST;
goto out;
}
 
-   pte = lookup_address(p->addr, );
+   pte = lookup_address(addr, );
if (!pte) {
ret = -EINVAL;
goto out;
@@ -454,7 +455,7 @@ int register_kmmio_probe(struct kmmio_probe *p)
kmmio_count++;
list_add_rcu(>list, _probes);
while (size < size_lim) {
-   if (add_kmmio_fault_page(p->addr + size))
+   if (add_kmmio_fault_page(addr + size))
pr_err("Unable to set page fault.\n");
size += page_level_size(l);
}
@@ -528,19 +529,20 @@ void unregister_kmmio_probe(struct kmmio_probe *p)
 {
unsigned long flags;
unsigned long size = 0;
+   unsigned long addr = p->addr & PAGE_MASK;
const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK);
struct kmmio_fault_page *release_list = NULL;
struct kmmio_delayed_release *drelease;
unsigned int l;
pte_t *pte;
 
-   pte = lookup_address(p->addr, );
+   pte = lookup_address(addr, );
if (!pte)
return;
 
spin_lock_irqsave(_lock, flags);
while (size < size_lim) {
-   release_kmmio_fault_page(p->addr + size, _list);
+   release_kmmio_fault_page(addr + size, _list);
size += page_level_size(l);
}
list_del_rcu(>list);
-- 
2.14.3



[PATCH] x86/mm/kmmio: Fix mmiotrace for page unaligned addresses

2017-11-26 Thread Karol Herbst
If something calls ioremap with an address not aligned to PAGE_SIZE, the
returned address might be not aligned as well. This led to a probe
registered on exactly the returned address, but the entire page was armed
for mmiotracing.

On calling iounmap the address passed to unregister_kmmio_probe was
PAGE_SIZE aligned by the caller leading to a complete freeze of the
machine.

We should always page align addresses while (un)registerung mappings,
because the mmiotracer works on top of pages, not mappings. We still keep
track of the probes based on their real addresses and lengths though,
because the mmiotrace still needs to know what are mapped memory regions.

Also move the call to mmiotrace_iounmap prior page aligning the address,
so that all probes are unregistered properly, otherwise the kernel ends up
failing memory allocations randomly after disabling the mmiotracer.

Cc: Steven Rostedt 
Cc: Ingo Molnar 
Cc: Thomas Gleixner 
Cc: Pekka Paalanen 
Cc: nouv...@lists.freedesktop.org
Cc: x...@kernel.org
Acked-by: Pekka Paalanen 
Tested-by: Lyude 
Signed-off-by: Karol Herbst 
---
 arch/x86/mm/ioremap.c |  4 ++--
 arch/x86/mm/kmmio.c   | 12 +++-
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 34f0e1847dd6..5d4c358778dd 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -349,11 +349,11 @@ void iounmap(volatile void __iomem *addr)
return;
}
 
+   mmiotrace_iounmap(addr);
+
addr = (volatile void __iomem *)
(PAGE_MASK & (unsigned long __force)addr);
 
-   mmiotrace_iounmap(addr);
-
/* Use the vm area unlocked, assuming the caller
   ensures there isn't another iounmap for the same address
   in parallel. Reuse of the virtual address is prevented by
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index c21c2ed04612..58477ec3d66d 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -435,17 +435,18 @@ int register_kmmio_probe(struct kmmio_probe *p)
unsigned long flags;
int ret = 0;
unsigned long size = 0;
+   unsigned long addr = p->addr & PAGE_MASK;
const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK);
unsigned int l;
pte_t *pte;
 
spin_lock_irqsave(_lock, flags);
-   if (get_kmmio_probe(p->addr)) {
+   if (get_kmmio_probe(addr)) {
ret = -EEXIST;
goto out;
}
 
-   pte = lookup_address(p->addr, );
+   pte = lookup_address(addr, );
if (!pte) {
ret = -EINVAL;
goto out;
@@ -454,7 +455,7 @@ int register_kmmio_probe(struct kmmio_probe *p)
kmmio_count++;
list_add_rcu(>list, _probes);
while (size < size_lim) {
-   if (add_kmmio_fault_page(p->addr + size))
+   if (add_kmmio_fault_page(addr + size))
pr_err("Unable to set page fault.\n");
size += page_level_size(l);
}
@@ -528,19 +529,20 @@ void unregister_kmmio_probe(struct kmmio_probe *p)
 {
unsigned long flags;
unsigned long size = 0;
+   unsigned long addr = p->addr & PAGE_MASK;
const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK);
struct kmmio_fault_page *release_list = NULL;
struct kmmio_delayed_release *drelease;
unsigned int l;
pte_t *pte;
 
-   pte = lookup_address(p->addr, );
+   pte = lookup_address(addr, );
if (!pte)
return;
 
spin_lock_irqsave(_lock, flags);
while (size < size_lim) {
-   release_kmmio_fault_page(p->addr + size, _list);
+   release_kmmio_fault_page(addr + size, _list);
size += page_level_size(l);
}
list_del_rcu(>list);
-- 
2.14.3



[RFC PATCH 2/3] net: macb: Tie-off unused RX queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Currently, we only use the first receive queue and leave the
remaining DMA descriptor pointers pointing at 0.

Disable unused queues by connecting them to a looped descriptor
chain without free slots.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  |  2 ++
 drivers/net/ethernet/cadence/macb_main.c | 42 
 2 files changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index acb6578..974c801 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -994,6 +994,7 @@ struct macb {
unsigned intrx_tail;
unsigned intrx_prepared_head;
struct macb_dma_desc*rx_ring;
+   struct macb_dma_desc*rx_ring_tieoff;
struct sk_buff  **rx_skbuff;
void*rx_buffers;
size_t  rx_buffer_size;
@@ -1019,6 +1020,7 @@ struct macb {
}   hw_stats;
 
dma_addr_t  rx_ring_dma;
+   dma_addr_t  rx_ring_tieoff_dma;
dma_addr_t  rx_buffers_dma;
 
struct macb_or_gem_ops  macbgem_ops;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 623ae9c..b14a04d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1755,6 +1755,12 @@ static void macb_free_consistent(struct macb *bp)
bp->rx_ring = NULL;
}
 
+   if (bp->rx_ring_tieoff) {
+   dma_free_coherent(>pdev->dev, sizeof(bp->rx_ring_tieoff[0]),
+ bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
+   bp->rx_ring_tieoff = NULL;
+   }
+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
kfree(queue->tx_skb);
queue->tx_skb = NULL;
@@ -1826,6 +1832,19 @@ static int macb_alloc_consistent(struct macb *bp)
 >rx_ring_dma, GFP_KERNEL);
if (!bp->rx_ring)
goto out_err;
+
+   /* If we have more than one queue, allocate a tie off descriptor
+* that will be used to disable unused RX queues.
+*/
+   if (bp->num_queues > 1) {
+   bp->rx_ring_tieoff = dma_alloc_coherent(>pdev->dev,
+   sizeof(bp->rx_ring_tieoff[0]),
+   >rx_ring_tieoff_dma,
+   GFP_KERNEL);
+   if (!bp->rx_ring_tieoff)
+   goto out_err;
+   }
+
netdev_dbg(bp->dev,
   "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
   size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
@@ -1840,6 +1859,19 @@ static int macb_alloc_consistent(struct macb *bp)
return -ENOMEM;
 }
 
+static void macb_init_tieoff(struct macb *bp)
+{
+   struct macb_dma_desc *d = bp->rx_ring_tieoff;
+
+   if (bp->num_queues > 1) {
+   /* Setup a wrapping descriptor with no free slots
+* (WRAP and USED) to tie off/disable unused RX queues.
+*/
+   d->addr = MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED);
+   d->ctrl = 0;
+   }
+}
+
 static void gem_init_rings(struct macb *bp)
 {
struct macb_queue *queue;
@@ -1862,6 +1894,7 @@ static void gem_init_rings(struct macb *bp)
bp->rx_prepared_head = 0;
 
gem_rx_refill(bp);
+   macb_init_tieoff(bp);
 }
 
 static void macb_init_rings(struct macb *bp)
@@ -1879,6 +1912,7 @@ static void macb_init_rings(struct macb *bp)
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
desc->ctrl |= MACB_BIT(TX_WRAP);
+   macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2063,6 +2097,14 @@ static void macb_init_hw(struct macb *bp)
queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
 #endif
 
+   /* We only use the first queue at the moment. Remaining
+* queues must be tied-off before we enable the receiver.
+*
+* See the documentation for receive_q1_ptr for more info.
+*/
+   if (q)
+   queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
/* Enable interrupts */
queue_writel(queue, IER,
 MACB_RX_INT_FLAGS |
-- 
2.7.4



[RFC PATCH 2/3] net: macb: Tie-off unused RX queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Currently, we only use the first receive queue and leave the
remaining DMA descriptor pointers pointing at 0.

Disable unused queues by connecting them to a looped descriptor
chain without free slots.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  |  2 ++
 drivers/net/ethernet/cadence/macb_main.c | 42 
 2 files changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index acb6578..974c801 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -994,6 +994,7 @@ struct macb {
unsigned intrx_tail;
unsigned intrx_prepared_head;
struct macb_dma_desc*rx_ring;
+   struct macb_dma_desc*rx_ring_tieoff;
struct sk_buff  **rx_skbuff;
void*rx_buffers;
size_t  rx_buffer_size;
@@ -1019,6 +1020,7 @@ struct macb {
}   hw_stats;
 
dma_addr_t  rx_ring_dma;
+   dma_addr_t  rx_ring_tieoff_dma;
dma_addr_t  rx_buffers_dma;
 
struct macb_or_gem_ops  macbgem_ops;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 623ae9c..b14a04d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1755,6 +1755,12 @@ static void macb_free_consistent(struct macb *bp)
bp->rx_ring = NULL;
}
 
+   if (bp->rx_ring_tieoff) {
+   dma_free_coherent(>pdev->dev, sizeof(bp->rx_ring_tieoff[0]),
+ bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
+   bp->rx_ring_tieoff = NULL;
+   }
+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
kfree(queue->tx_skb);
queue->tx_skb = NULL;
@@ -1826,6 +1832,19 @@ static int macb_alloc_consistent(struct macb *bp)
 >rx_ring_dma, GFP_KERNEL);
if (!bp->rx_ring)
goto out_err;
+
+   /* If we have more than one queue, allocate a tie off descriptor
+* that will be used to disable unused RX queues.
+*/
+   if (bp->num_queues > 1) {
+   bp->rx_ring_tieoff = dma_alloc_coherent(>pdev->dev,
+   sizeof(bp->rx_ring_tieoff[0]),
+   >rx_ring_tieoff_dma,
+   GFP_KERNEL);
+   if (!bp->rx_ring_tieoff)
+   goto out_err;
+   }
+
netdev_dbg(bp->dev,
   "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
   size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
@@ -1840,6 +1859,19 @@ static int macb_alloc_consistent(struct macb *bp)
return -ENOMEM;
 }
 
+static void macb_init_tieoff(struct macb *bp)
+{
+   struct macb_dma_desc *d = bp->rx_ring_tieoff;
+
+   if (bp->num_queues > 1) {
+   /* Setup a wrapping descriptor with no free slots
+* (WRAP and USED) to tie off/disable unused RX queues.
+*/
+   d->addr = MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED);
+   d->ctrl = 0;
+   }
+}
+
 static void gem_init_rings(struct macb *bp)
 {
struct macb_queue *queue;
@@ -1862,6 +1894,7 @@ static void gem_init_rings(struct macb *bp)
bp->rx_prepared_head = 0;
 
gem_rx_refill(bp);
+   macb_init_tieoff(bp);
 }
 
 static void macb_init_rings(struct macb *bp)
@@ -1879,6 +1912,7 @@ static void macb_init_rings(struct macb *bp)
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
desc->ctrl |= MACB_BIT(TX_WRAP);
+   macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2063,6 +2097,14 @@ static void macb_init_hw(struct macb *bp)
queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
 #endif
 
+   /* We only use the first queue at the moment. Remaining
+* queues must be tied-off before we enable the receiver.
+*
+* See the documentation for receive_q1_ptr for more info.
+*/
+   if (q)
+   queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
/* Enable interrupts */
queue_writel(queue, IER,
 MACB_RX_INT_FLAGS |
-- 
2.7.4



Re: [PATCH] mm:Add watermark slope for high mark

2017-11-26 Thread kbuild test robot
Hi Peter,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mmotm/master]
[also build test ERROR on v4.15-rc1 next-20171127]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Peter-Enderborg/mm-Add-watermark-slope-for-high-mark/20171127-140339
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: i386-randconfig-s0-201748 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `__setup_per_zone_wmarks':
>> mm/page_alloc.c:7031: undefined reference to `__umoddi3'
>> mm/page_alloc.c:7031: undefined reference to `__udivdi3'
>> mm/page_alloc.c:7031: undefined reference to `__udivdi3'

vim +7031 mm/page_alloc.c

  6977  
  6978  static void __setup_per_zone_wmarks(void)
  6979  {
  6980  unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
  6981  unsigned long lowmem_pages = 0;
  6982  struct zone *zone;
  6983  unsigned long flags;
  6984  
  6985  /* Calculate total number of !ZONE_HIGHMEM pages */
  6986  for_each_zone(zone) {
  6987  if (!is_highmem(zone))
  6988  lowmem_pages += zone->managed_pages;
  6989  }
  6990  
  6991  for_each_zone(zone) {
  6992  u64 tmp;
  6993  u64 tmp_high;
  6994  
  6995  spin_lock_irqsave(>lock, flags);
  6996  tmp = (u64)pages_min * zone->managed_pages;
  6997  do_div(tmp, lowmem_pages);
  6998  if (is_highmem(zone)) {
  6999  /*
  7000   * __GFP_HIGH and PF_MEMALLOC allocations 
usually don't
  7001   * need highmem pages, so cap pages_min to a 
small
  7002   * value here.
  7003   *
  7004   * The WMARK_HIGH-WMARK_LOW and 
(WMARK_LOW-WMARK_MIN)
  7005   * deltas control asynch page reclaim, and so 
should
  7006   * not be capped for highmem.
  7007   */
  7008  unsigned long min_pages;
  7009  
  7010  min_pages = zone->managed_pages / 1024;
  7011  min_pages = clamp(min_pages, SWAP_CLUSTER_MAX, 
128UL);
  7012  zone->watermark[WMARK_MIN] = min_pages;
  7013  } else {
  7014  /*
  7015   * If it's a lowmem zone, reserve a number of 
pages
  7016   * proportionate to the zone's size.
  7017   */
  7018  zone->watermark[WMARK_MIN] = tmp;
  7019  }
  7020  
  7021  /*
  7022   * Set the kswapd watermarks distance according to the
  7023   * scale factor in proportion to available memory, but
  7024   * ensure a minimum size on small systems.
  7025   */
  7026  tmp = max_t(u64, tmp >> 2,
  7027  mult_frac(zone->managed_pages,
  7028watermark_scale_factor, 1));
  7029  
  7030  zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + 
tmp;
> 7031  tmp_high = mult_frac(tmp, watermark_high_factor_slope, 
> 100);
  7032  zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + 
tmp_high;
  7033  
  7034  
  7035  spin_unlock_irqrestore(>lock, flags);
  7036  }
  7037  
  7038  /* update totalreserve_pages */
  7039  calculate_totalreserve_pages();
  7040  }
  7041  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH] mm:Add watermark slope for high mark

2017-11-26 Thread kbuild test robot
Hi Peter,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mmotm/master]
[also build test ERROR on v4.15-rc1 next-20171127]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Peter-Enderborg/mm-Add-watermark-slope-for-high-mark/20171127-140339
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: i386-randconfig-s0-201748 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `__setup_per_zone_wmarks':
>> mm/page_alloc.c:7031: undefined reference to `__umoddi3'
>> mm/page_alloc.c:7031: undefined reference to `__udivdi3'
>> mm/page_alloc.c:7031: undefined reference to `__udivdi3'

vim +7031 mm/page_alloc.c

  6977  
  6978  static void __setup_per_zone_wmarks(void)
  6979  {
  6980  unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
  6981  unsigned long lowmem_pages = 0;
  6982  struct zone *zone;
  6983  unsigned long flags;
  6984  
  6985  /* Calculate total number of !ZONE_HIGHMEM pages */
  6986  for_each_zone(zone) {
  6987  if (!is_highmem(zone))
  6988  lowmem_pages += zone->managed_pages;
  6989  }
  6990  
  6991  for_each_zone(zone) {
  6992  u64 tmp;
  6993  u64 tmp_high;
  6994  
  6995  spin_lock_irqsave(>lock, flags);
  6996  tmp = (u64)pages_min * zone->managed_pages;
  6997  do_div(tmp, lowmem_pages);
  6998  if (is_highmem(zone)) {
  6999  /*
  7000   * __GFP_HIGH and PF_MEMALLOC allocations 
usually don't
  7001   * need highmem pages, so cap pages_min to a 
small
  7002   * value here.
  7003   *
  7004   * The WMARK_HIGH-WMARK_LOW and 
(WMARK_LOW-WMARK_MIN)
  7005   * deltas control asynch page reclaim, and so 
should
  7006   * not be capped for highmem.
  7007   */
  7008  unsigned long min_pages;
  7009  
  7010  min_pages = zone->managed_pages / 1024;
  7011  min_pages = clamp(min_pages, SWAP_CLUSTER_MAX, 
128UL);
  7012  zone->watermark[WMARK_MIN] = min_pages;
  7013  } else {
  7014  /*
  7015   * If it's a lowmem zone, reserve a number of 
pages
  7016   * proportionate to the zone's size.
  7017   */
  7018  zone->watermark[WMARK_MIN] = tmp;
  7019  }
  7020  
  7021  /*
  7022   * Set the kswapd watermarks distance according to the
  7023   * scale factor in proportion to available memory, but
  7024   * ensure a minimum size on small systems.
  7025   */
  7026  tmp = max_t(u64, tmp >> 2,
  7027  mult_frac(zone->managed_pages,
  7028watermark_scale_factor, 1));
  7029  
  7030  zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + 
tmp;
> 7031  tmp_high = mult_frac(tmp, watermark_high_factor_slope, 
> 100);
  7032  zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + 
tmp_high;
  7033  
  7034  
  7035  spin_unlock_irqrestore(>lock, flags);
  7036  }
  7037  
  7038  /* update totalreserve_pages */
  7039  calculate_totalreserve_pages();
  7040  }
  7041  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[PATCH v2] input: pegasus_notetaker: add license information

2017-11-26 Thread Martin Kepplinger
This adds an SPDX license identifier to this driver I wrote some time back.

Signed-off-by: Martin Kepplinger 
---

Thanks for the feedback. GPL2+ was what I had in mind. My bad. And as I
already see a lot of SPDX tags using /**/ comments, I'll use that too.
I think if it is hand-written, it shouldn't look too ugly. And in case
that's really a no-go, it seems that many many files need to be changed
again in any case.

  martin

patch revisions
---
v2: use /**/ comments and fix the license tag to match MODULE_LICENSE()


 drivers/input/tablet/pegasus_notetaker.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/input/tablet/pegasus_notetaker.c 
b/drivers/input/tablet/pegasus_notetaker.c
index 47de5a81172f..93fe8ecab767 100644
--- a/drivers/input/tablet/pegasus_notetaker.c
+++ b/drivers/input/tablet/pegasus_notetaker.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Pegasus Mobile Notetaker Pen input tablet driver
  *
-- 
2.11.0



[PATCH v2] input: pegasus_notetaker: add license information

2017-11-26 Thread Martin Kepplinger
This adds an SPDX license identifier to this driver I wrote some time back.

Signed-off-by: Martin Kepplinger 
---

Thanks for the feedback. GPL2+ was what I had in mind. My bad. And as I
already see a lot of SPDX tags using /**/ comments, I'll use that too.
I think if it is hand-written, it shouldn't look too ugly. And in case
that's really a no-go, it seems that many many files need to be changed
again in any case.

  martin

patch revisions
---
v2: use /**/ comments and fix the license tag to match MODULE_LICENSE()


 drivers/input/tablet/pegasus_notetaker.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/input/tablet/pegasus_notetaker.c 
b/drivers/input/tablet/pegasus_notetaker.c
index 47de5a81172f..93fe8ecab767 100644
--- a/drivers/input/tablet/pegasus_notetaker.c
+++ b/drivers/input/tablet/pegasus_notetaker.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Pegasus Mobile Notetaker Pen input tablet driver
  *
-- 
2.11.0



[RFC PATCH 1/3] net: macb: Add RBQP to the macb queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Add RX queue pointer to macb queues to make it accessible for the
multiple queues available. Currently the first RX queue is used.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  | 1 +
 drivers/net/ethernet/cadence/macb_main.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index c93f3a2..acb6578 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -968,6 +968,7 @@ struct macb_queue {
unsigned intIMR;
unsigned intTBQP;
unsigned intTBQPH;
+   unsigned intRBQP;
 
unsigned inttx_head, tx_tail;
struct macb_dma_desc*tx_ring;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 72a67f7..623ae9c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2875,6 +2875,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
+   queue->RBQP = GEM_RBQP(hw_q - 1);
} else {
/* queue0 uses legacy registers */
queue->ISR  = MACB_ISR;
@@ -2886,6 +2887,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = MACB_TBQPH;
 #endif
+   queue->RBQP = MACB_RBQP;
}
 
/* get irq: here we use the linux queue index, not the hardware
-- 
2.7.4



[RFC PATCH 3/3] net: macb: Handle HRESP error

2017-11-26 Thread Harini Katakam
From: Harini Katakam 

Handle HRESP error by doing a SW reset of RX and TX and
re-initializing the descriptors, RX and TX queue pointers.

Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  |  2 +
 drivers/net/ethernet/cadence/macb_main.c | 65 ++--
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index 974c801..5246ee1 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -1060,6 +1060,8 @@ struct macb {
struct ptp_clock_info ptp_clock_info;
struct tsu_incr tsu_incr;
struct hwtstamp_config tstamp_config;
+
+   struct tasklet_struct   hresp_err_tasklet;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index b14a04d..d76e04f 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1244,6 +1244,63 @@ static int macb_poll(struct napi_struct *napi, int 
budget)
return work_done;
 }
 
+static void macb_hresp_error_task(unsigned long data)
+{
+   struct macb *bp = (struct macb *)data;
+   struct net_device *dev = bp->dev;
+   struct macb_queue *queue = bp->queues;
+   unsigned int q;
+   u32 ctrl;
+
+   for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+   queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
+MACB_TX_INT_FLAGS |
+MACB_BIT(HRESP));
+   }
+   ctrl = macb_readl(bp, NCR);
+   ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE));
+   macb_writel(bp, NCR, ctrl);
+
+   netif_tx_stop_all_queues(dev);
+   netif_carrier_off(dev);
+
+   bp->macbgem_ops.mog_init_rings(bp);
+
+   /* Initialize TX and RX buffers */
+   macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+   if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+   macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
+#endif
+   for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+   queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+   if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+   queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
+#endif
+
+   /* We only use the first queue at the moment. Remaining
+* queues must be tied-off before we enable the receiver.
+*
+* See the documentation for receive_q1_ptr for more info.
+*/
+   if (q)
+   queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
+   /* Enable interrupts */
+   queue_writel(queue, IER,
+MACB_RX_INT_FLAGS |
+MACB_TX_INT_FLAGS |
+MACB_BIT(HRESP));
+   }
+
+   ctrl |= MACB_BIT(RE) | MACB_BIT(TE);
+   macb_writel(bp, NCR, ctrl);
+
+   netif_carrier_on(dev);
+   netif_tx_start_all_queues(dev);
+}
+
 static irqreturn_t macb_interrupt(int irq, void *dev_id)
 {
struct macb_queue *queue = dev_id;
@@ -1333,10 +1390,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
}
 
if (status & MACB_BIT(HRESP)) {
-   /* TODO: Reset the hardware, and maybe move the
-* netdev_err to a lower-priority context as well
-* (work queue?)
-*/
+   tasklet_schedule(>hresp_err_tasklet);
netdev_err(dev, "DMA bus error: HRESP not OK\n");
 
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
@@ -3586,6 +3640,9 @@ static int macb_probe(struct platform_device *pdev)
goto err_out_unregister_mdio;
}
 
+   tasklet_init(>hresp_err_tasklet, macb_hresp_error_task,
+(unsigned long)bp);
+
phy_attached_info(phydev);
 
netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
-- 
2.7.4



[RFC PATCH 1/3] net: macb: Add RBQP to the macb queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Add RX queue pointer to macb queues to make it accessible for the
multiple queues available. Currently the first RX queue is used.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  | 1 +
 drivers/net/ethernet/cadence/macb_main.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index c93f3a2..acb6578 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -968,6 +968,7 @@ struct macb_queue {
unsigned intIMR;
unsigned intTBQP;
unsigned intTBQPH;
+   unsigned intRBQP;
 
unsigned inttx_head, tx_tail;
struct macb_dma_desc*tx_ring;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 72a67f7..623ae9c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2875,6 +2875,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
+   queue->RBQP = GEM_RBQP(hw_q - 1);
} else {
/* queue0 uses legacy registers */
queue->ISR  = MACB_ISR;
@@ -2886,6 +2887,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = MACB_TBQPH;
 #endif
+   queue->RBQP = MACB_RBQP;
}
 
/* get irq: here we use the linux queue index, not the hardware
-- 
2.7.4



[RFC PATCH 3/3] net: macb: Handle HRESP error

2017-11-26 Thread Harini Katakam
From: Harini Katakam 

Handle HRESP error by doing a SW reset of RX and TX and
re-initializing the descriptors, RX and TX queue pointers.

Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  |  2 +
 drivers/net/ethernet/cadence/macb_main.c | 65 ++--
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index 974c801..5246ee1 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -1060,6 +1060,8 @@ struct macb {
struct ptp_clock_info ptp_clock_info;
struct tsu_incr tsu_incr;
struct hwtstamp_config tstamp_config;
+
+   struct tasklet_struct   hresp_err_tasklet;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index b14a04d..d76e04f 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1244,6 +1244,63 @@ static int macb_poll(struct napi_struct *napi, int 
budget)
return work_done;
 }
 
+static void macb_hresp_error_task(unsigned long data)
+{
+   struct macb *bp = (struct macb *)data;
+   struct net_device *dev = bp->dev;
+   struct macb_queue *queue = bp->queues;
+   unsigned int q;
+   u32 ctrl;
+
+   for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+   queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
+MACB_TX_INT_FLAGS |
+MACB_BIT(HRESP));
+   }
+   ctrl = macb_readl(bp, NCR);
+   ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE));
+   macb_writel(bp, NCR, ctrl);
+
+   netif_tx_stop_all_queues(dev);
+   netif_carrier_off(dev);
+
+   bp->macbgem_ops.mog_init_rings(bp);
+
+   /* Initialize TX and RX buffers */
+   macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+   if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+   macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
+#endif
+   for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+   queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+   if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+   queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
+#endif
+
+   /* We only use the first queue at the moment. Remaining
+* queues must be tied-off before we enable the receiver.
+*
+* See the documentation for receive_q1_ptr for more info.
+*/
+   if (q)
+   queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
+   /* Enable interrupts */
+   queue_writel(queue, IER,
+MACB_RX_INT_FLAGS |
+MACB_TX_INT_FLAGS |
+MACB_BIT(HRESP));
+   }
+
+   ctrl |= MACB_BIT(RE) | MACB_BIT(TE);
+   macb_writel(bp, NCR, ctrl);
+
+   netif_carrier_on(dev);
+   netif_tx_start_all_queues(dev);
+}
+
 static irqreturn_t macb_interrupt(int irq, void *dev_id)
 {
struct macb_queue *queue = dev_id;
@@ -1333,10 +1390,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
}
 
if (status & MACB_BIT(HRESP)) {
-   /* TODO: Reset the hardware, and maybe move the
-* netdev_err to a lower-priority context as well
-* (work queue?)
-*/
+   tasklet_schedule(>hresp_err_tasklet);
netdev_err(dev, "DMA bus error: HRESP not OK\n");
 
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
@@ -3586,6 +3640,9 @@ static int macb_probe(struct platform_device *pdev)
goto err_out_unregister_mdio;
}
 
+   tasklet_init(>hresp_err_tasklet, macb_hresp_error_task,
+(unsigned long)bp);
+
phy_attached_info(phydev);
 
netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
-- 
2.7.4



[RFC PATCH 0/3] Miscellaneous fixes in macb driver

2017-11-26 Thread Harini Katakam
This series fixes the following:
-> Ties off unused RX queues
-> Handles RX HRESP error

Edgar E. Iglesias (2):
  net: macb: Add RBQP to the macb queues
  net: macb: Tie-off unused RX queues

Harini Katakam (1):
  net: macb: Handle HRESP error

 drivers/net/ethernet/cadence/macb.h  |   5 ++
 drivers/net/ethernet/cadence/macb_main.c | 109 +--
 2 files changed, 110 insertions(+), 4 deletions(-)

-- 
2.7.4



[RFC PATCH 0/3] Miscellaneous fixes in macb driver

2017-11-26 Thread Harini Katakam
This series fixes the following:
-> Ties off unused RX queues
-> Handles RX HRESP error

Edgar E. Iglesias (2):
  net: macb: Add RBQP to the macb queues
  net: macb: Tie-off unused RX queues

Harini Katakam (1):
  net: macb: Handle HRESP error

 drivers/net/ethernet/cadence/macb.h  |   5 ++
 drivers/net/ethernet/cadence/macb_main.c | 109 +--
 2 files changed, 110 insertions(+), 4 deletions(-)

-- 
2.7.4



Re: [RFC PATCH 1/2] net: macb: Add RBQP to the macb queues

2017-11-26 Thread Harini Katakam
Hi,

Please ignore this series.
I'm sending another updated one.
Sorry for the inconvenience.

Regards,
Harini

On Mon, Nov 27, 2017 at 12:33 PM, Harini Katakam
 wrote:
> From: "Edgar E. Iglesias" 
>
> Add RX queue pointer to macb queues to make it accessible for the
> multiple queues available. Currently the first RX queue is used.
>
> Signed-off-by: Edgar E. Iglesias 
> Signed-off-by: Harini Katakam 
> Signed-off-by: Michal Simek 
> ---
>  drivers/net/ethernet/cadence/macb.h  | 1 +
>  drivers/net/ethernet/cadence/macb_main.c | 2 ++
>  2 files changed, 3 insertions(+)
>
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index c93f3a2..acb6578 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -968,6 +968,7 @@ struct macb_queue {
> unsigned intIMR;
> unsigned intTBQP;
> unsigned intTBQPH;
> +   unsigned intRBQP;
>
> unsigned inttx_head, tx_tail;
> struct macb_dma_desc*tx_ring;
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 72a67f7..623ae9c 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -2875,6 +2875,7 @@ static int macb_init(struct platform_device *pdev)
> if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> queue->TBQPH = GEM_TBQPH(hw_q - 1);
>  #endif
> +   queue->RBQP = GEM_RBQP(hw_q - 1);
> } else {
> /* queue0 uses legacy registers */
> queue->ISR  = MACB_ISR;
> @@ -2886,6 +2887,7 @@ static int macb_init(struct platform_device *pdev)
> if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> queue->TBQPH = MACB_TBQPH;
>  #endif
> +   queue->RBQP = MACB_RBQP;
> }
>
> /* get irq: here we use the linux queue index, not the 
> hardware
> --
> 2.7.4
>


Re: [RFC PATCH 1/2] net: macb: Add RBQP to the macb queues

2017-11-26 Thread Harini Katakam
Hi,

Please ignore this series.
I'm sending another updated one.
Sorry for the inconvenience.

Regards,
Harini

On Mon, Nov 27, 2017 at 12:33 PM, Harini Katakam
 wrote:
> From: "Edgar E. Iglesias" 
>
> Add RX queue pointer to macb queues to make it accessible for the
> multiple queues available. Currently the first RX queue is used.
>
> Signed-off-by: Edgar E. Iglesias 
> Signed-off-by: Harini Katakam 
> Signed-off-by: Michal Simek 
> ---
>  drivers/net/ethernet/cadence/macb.h  | 1 +
>  drivers/net/ethernet/cadence/macb_main.c | 2 ++
>  2 files changed, 3 insertions(+)
>
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index c93f3a2..acb6578 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -968,6 +968,7 @@ struct macb_queue {
> unsigned intIMR;
> unsigned intTBQP;
> unsigned intTBQPH;
> +   unsigned intRBQP;
>
> unsigned inttx_head, tx_tail;
> struct macb_dma_desc*tx_ring;
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 72a67f7..623ae9c 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -2875,6 +2875,7 @@ static int macb_init(struct platform_device *pdev)
> if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> queue->TBQPH = GEM_TBQPH(hw_q - 1);
>  #endif
> +   queue->RBQP = GEM_RBQP(hw_q - 1);
> } else {
> /* queue0 uses legacy registers */
> queue->ISR  = MACB_ISR;
> @@ -2886,6 +2887,7 @@ static int macb_init(struct platform_device *pdev)
> if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> queue->TBQPH = MACB_TBQPH;
>  #endif
> +   queue->RBQP = MACB_RBQP;
> }
>
> /* get irq: here we use the linux queue index, not the 
> hardware
> --
> 2.7.4
>


[PATCH v7,2/2] misc: rtsx: Add support for RTS5260

2017-11-26 Thread rui_feng
From: Rui Feng 

Add support for new chip rts5260.
In order to support rts5260, the definitions of
some internal registers and workflow have to be
modified and are different from its predecessors
and OCP function is added for RTS5260. So we need
this patch to ensure RTS5260 can work.

Signed-off-by: Rui Feng 
Reviewed-by: Daniel Bristot de Oliveira 
---
 drivers/misc/cardreader/Kconfig|   2 +-
 drivers/misc/cardreader/Makefile   |   2 +-
 drivers/misc/cardreader/rts5260.c  | 748 +
 drivers/misc/cardreader/rts5260.h  |  45 +++
 drivers/misc/cardreader/rtsx_pcr.c | 123 +-
 drivers/misc/cardreader/rtsx_pcr.h |  10 +
 include/linux/rtsx_pci.h   | 234 +++-
 7 files changed, 1157 insertions(+), 7 deletions(-)
 create mode 100644 drivers/misc/cardreader/rts5260.c
 create mode 100644 drivers/misc/cardreader/rts5260.h

diff --git a/drivers/misc/cardreader/Kconfig b/drivers/misc/cardreader/Kconfig
index e7d835a..69e815e 100644
--- a/drivers/misc/cardreader/Kconfig
+++ b/drivers/misc/cardreader/Kconfig
@@ -4,7 +4,7 @@ config MISC_RTSX_PCI
select MFD_CORE
help
  This supports for Realtek PCI-Express card reader including rts5209,
- rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411.
+ rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, 
rts5260.
  Realtek card readers support access to many types of memory cards,
  such as Memory Stick, Memory Stick Pro, Secure Digital and
  MultiMediaCard.
diff --git a/drivers/misc/cardreader/Makefile b/drivers/misc/cardreader/Makefile
index 78337b2..9fabfcc 100644
--- a/drivers/misc/cardreader/Makefile
+++ b/drivers/misc/cardreader/Makefile
@@ -1,4 +1,4 @@
-rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
+rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o 
rts5260.o
 
 obj-$(CONFIG_MISC_RTSX_PCI)+= rtsx_pci.o
 obj-$(CONFIG_MISC_RTSX_USB)+= rtsx_usb.o
diff --git a/drivers/misc/cardreader/rts5260.c 
b/drivers/misc/cardreader/rts5260.c
new file mode 100644
index 000..3b30864
--- /dev/null
+++ b/drivers/misc/cardreader/rts5260.c
@@ -0,0 +1,748 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2016-2017 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see .
+ *
+ * Author:
+ *   Steven FENG 
+ *   Rui FENG 
+ *   Wei WANG 
+ */
+
+#include 
+#include 
+#include 
+
+#include "rts5260.h"
+#include "rtsx_pcr.h"
+
+static u8 rts5260_get_ic_version(struct rtsx_pcr *pcr)
+{
+   u8 val;
+
+   rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, );
+   return val & IC_VERSION_MASK;
+}
+
+static void rts5260_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
+{
+   u8 driving_3v3[6][3] = {
+   {0x94, 0x94, 0x94},
+   {0x11, 0x11, 0x18},
+   {0x55, 0x55, 0x5C},
+   {0x94, 0x94, 0x94},
+   {0x94, 0x94, 0x94},
+   {0xFF, 0xFF, 0xFF},
+   };
+   u8 driving_1v8[6][3] = {
+   {0x9A, 0x89, 0x89},
+   {0xC4, 0xC4, 0xC4},
+   {0x3C, 0x3C, 0x3C},
+   {0x9B, 0x99, 0x99},
+   {0x9A, 0x89, 0x89},
+   {0xFE, 0xFE, 0xFE},
+   };
+   u8 (*driving)[3], drive_sel;
+
+   if (voltage == OUTPUT_3V3) {
+   driving = driving_3v3;
+   drive_sel = pcr->sd30_drive_sel_3v3;
+   } else {
+   driving = driving_1v8;
+   drive_sel = pcr->sd30_drive_sel_1v8;
+   }
+
+   rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
+0xFF, driving[drive_sel][0]);
+   rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
+0xFF, driving[drive_sel][1]);
+   rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
+0xFF, driving[drive_sel][2]);
+}
+
+static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+   u32 reg;
+
+   rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, );
+   pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+   if (!rtsx_vendor_setting_valid(reg)) {
+   

[PATCH v7,2/2] misc: rtsx: Add support for RTS5260

2017-11-26 Thread rui_feng
From: Rui Feng 

Add support for new chip rts5260.
In order to support rts5260, the definitions of
some internal registers and workflow have to be
modified and are different from its predecessors
and OCP function is added for RTS5260. So we need
this patch to ensure RTS5260 can work.

Signed-off-by: Rui Feng 
Reviewed-by: Daniel Bristot de Oliveira 
---
 drivers/misc/cardreader/Kconfig|   2 +-
 drivers/misc/cardreader/Makefile   |   2 +-
 drivers/misc/cardreader/rts5260.c  | 748 +
 drivers/misc/cardreader/rts5260.h  |  45 +++
 drivers/misc/cardreader/rtsx_pcr.c | 123 +-
 drivers/misc/cardreader/rtsx_pcr.h |  10 +
 include/linux/rtsx_pci.h   | 234 +++-
 7 files changed, 1157 insertions(+), 7 deletions(-)
 create mode 100644 drivers/misc/cardreader/rts5260.c
 create mode 100644 drivers/misc/cardreader/rts5260.h

diff --git a/drivers/misc/cardreader/Kconfig b/drivers/misc/cardreader/Kconfig
index e7d835a..69e815e 100644
--- a/drivers/misc/cardreader/Kconfig
+++ b/drivers/misc/cardreader/Kconfig
@@ -4,7 +4,7 @@ config MISC_RTSX_PCI
select MFD_CORE
help
  This supports for Realtek PCI-Express card reader including rts5209,
- rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411.
+ rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, 
rts5260.
  Realtek card readers support access to many types of memory cards,
  such as Memory Stick, Memory Stick Pro, Secure Digital and
  MultiMediaCard.
diff --git a/drivers/misc/cardreader/Makefile b/drivers/misc/cardreader/Makefile
index 78337b2..9fabfcc 100644
--- a/drivers/misc/cardreader/Makefile
+++ b/drivers/misc/cardreader/Makefile
@@ -1,4 +1,4 @@
-rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
+rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o 
rts5260.o
 
 obj-$(CONFIG_MISC_RTSX_PCI)+= rtsx_pci.o
 obj-$(CONFIG_MISC_RTSX_USB)+= rtsx_usb.o
diff --git a/drivers/misc/cardreader/rts5260.c 
b/drivers/misc/cardreader/rts5260.c
new file mode 100644
index 000..3b30864
--- /dev/null
+++ b/drivers/misc/cardreader/rts5260.c
@@ -0,0 +1,748 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2016-2017 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see .
+ *
+ * Author:
+ *   Steven FENG 
+ *   Rui FENG 
+ *   Wei WANG 
+ */
+
+#include 
+#include 
+#include 
+
+#include "rts5260.h"
+#include "rtsx_pcr.h"
+
+static u8 rts5260_get_ic_version(struct rtsx_pcr *pcr)
+{
+   u8 val;
+
+   rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, );
+   return val & IC_VERSION_MASK;
+}
+
+static void rts5260_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
+{
+   u8 driving_3v3[6][3] = {
+   {0x94, 0x94, 0x94},
+   {0x11, 0x11, 0x18},
+   {0x55, 0x55, 0x5C},
+   {0x94, 0x94, 0x94},
+   {0x94, 0x94, 0x94},
+   {0xFF, 0xFF, 0xFF},
+   };
+   u8 driving_1v8[6][3] = {
+   {0x9A, 0x89, 0x89},
+   {0xC4, 0xC4, 0xC4},
+   {0x3C, 0x3C, 0x3C},
+   {0x9B, 0x99, 0x99},
+   {0x9A, 0x89, 0x89},
+   {0xFE, 0xFE, 0xFE},
+   };
+   u8 (*driving)[3], drive_sel;
+
+   if (voltage == OUTPUT_3V3) {
+   driving = driving_3v3;
+   drive_sel = pcr->sd30_drive_sel_3v3;
+   } else {
+   driving = driving_1v8;
+   drive_sel = pcr->sd30_drive_sel_1v8;
+   }
+
+   rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
+0xFF, driving[drive_sel][0]);
+   rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
+0xFF, driving[drive_sel][1]);
+   rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
+0xFF, driving[drive_sel][2]);
+}
+
+static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+   u32 reg;
+
+   rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, );
+   pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+   if (!rtsx_vendor_setting_valid(reg)) {
+   pcr_dbg(pcr, "skip fetch vendor setting\n");
+   return;
+   }
+
+   pcr->aspm_en = rtsx_reg_to_aspm(reg);
+   

[PATCH v7,1/2] misc: rtsx: Move Realtek Card Reader Driver to misc

2017-11-26 Thread rui_feng
From: Rui Feng 

Because Realtek card reader drivers are pcie and usb drivers,
and they bridge mmc subsystem and memstick subsystem, they are
not mfd drivers. Greg and Lee Jones had a discussion about
where to put the drivers, the result is that misc is a good
place for them, so I move all files to misc. If I don't move
them to a right place, I can't add any patch for this driver.

Signed-off-by: Rui Feng 
Acked-by: Arnd Bergmann 
Acked-for-MFD-by: Lee Jones 
Reviewed-by: Daniel Bristot de Oliveira 
Acked-by: Ulf Hansson 

v7 changes:
* update missing modification in memstic
* add Acked-by
---
 drivers/memstick/host/Kconfig   |  4 ++--
 drivers/memstick/host/rtsx_pci_ms.c |  2 +-
 drivers/memstick/host/rtsx_usb_ms.c |  2 +-
 drivers/mfd/Kconfig | 21 -
 drivers/mfd/Makefile|  4 
 drivers/misc/Kconfig|  5 +
 drivers/misc/Makefile   |  1 +
 drivers/misc/cardreader/Kconfig | 20 
 drivers/misc/cardreader/Makefile|  4 
 drivers/{mfd => misc/cardreader}/rtl8411.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5209.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5227.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5229.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5249.c  |  3 +--
 drivers/{mfd => misc/cardreader}/rtsx_pcr.c |  2 +-
 drivers/{mfd => misc/cardreader}/rtsx_pcr.h |  2 +-
 drivers/{mfd => misc/cardreader}/rtsx_usb.c |  2 +-
 drivers/mmc/host/Kconfig|  4 ++--
 drivers/mmc/host/rtsx_pci_sdmmc.c   |  2 +-
 drivers/mmc/host/rtsx_usb_sdmmc.c   |  2 +-
 include/linux/{mfd => }/rtsx_common.h   |  0
 include/linux/{mfd => }/rtsx_pci.h  |  2 +-
 include/linux/{mfd => }/rtsx_usb.h  |  0
 23 files changed, 47 insertions(+), 43 deletions(-)
 create mode 100644 drivers/misc/cardreader/Kconfig
 create mode 100644 drivers/misc/cardreader/Makefile
 rename drivers/{mfd => misc/cardreader}/rtl8411.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5209.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5227.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5229.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5249.c (99%)
 rename drivers/{mfd => misc/cardreader}/rtsx_pcr.c (99%)
 rename drivers/{mfd => misc/cardreader}/rtsx_pcr.h (99%)
 rename drivers/{mfd => misc/cardreader}/rtsx_usb.c (99%)
 rename include/linux/{mfd => }/rtsx_common.h (100%)
 rename include/linux/{mfd => }/rtsx_pci.h (99%)
 rename include/linux/{mfd => }/rtsx_usb.h (100%)

diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index 7310e32..aa2b078 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -45,7 +45,7 @@ config MEMSTICK_R592
 
 config MEMSTICK_REALTEK_PCI
tristate "Realtek PCI-E Memstick Card Interface Driver"
-   depends on MFD_RTSX_PCI
+   depends on MISC_RTSX_PCI
help
  Say Y here to include driver code to support Memstick card interface
  of Realtek PCI-E card reader
@@ -55,7 +55,7 @@ config MEMSTICK_REALTEK_PCI
 
 config MEMSTICK_REALTEK_USB
tristate "Realtek USB Memstick Card Interface Driver"
-   depends on MFD_RTSX_USB
+   depends on MISC_RTSX_USB
help
  Say Y here to include driver code to support Memstick card interface
  of Realtek RTS5129/39 series USB card reader
diff --git a/drivers/memstick/host/rtsx_pci_ms.c 
b/drivers/memstick/host/rtsx_pci_ms.c
index 818fa94..a44b457 100644
--- a/drivers/memstick/host/rtsx_pci_ms.c
+++ b/drivers/memstick/host/rtsx_pci_ms.c
@@ -24,7 +24,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 struct realtek_pci_ms {
diff --git a/drivers/memstick/host/rtsx_usb_ms.c 
b/drivers/memstick/host/rtsx_usb_ms.c
index 2e3cf01..4f64563 100644
--- a/drivers/memstick/host/rtsx_usb_ms.c
+++ b/drivers/memstick/host/rtsx_usb_ms.c
@@ -25,7 +25,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fc5e4fe..80fd23f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -916,17 +916,6 @@ config MFD_RDC321X
  southbridge which provides access to GPIOs and Watchdog using the
  southbridge PCI device configuration space.
 
-config MFD_RTSX_PCI
-   tristate "Realtek PCI-E card reader"
-   depends on PCI
-   select MFD_CORE
-   help
- This supports for Realtek PCI-Express card reader including rts5209,
- rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
- Realtek card reader supports access to many types of memory cards,
- such as Memory Stick, Memory Stick Pro, Secure Digital and
- 

[PATCH v7,1/2] misc: rtsx: Move Realtek Card Reader Driver to misc

2017-11-26 Thread rui_feng
From: Rui Feng 

Because Realtek card reader drivers are pcie and usb drivers,
and they bridge mmc subsystem and memstick subsystem, they are
not mfd drivers. Greg and Lee Jones had a discussion about
where to put the drivers, the result is that misc is a good
place for them, so I move all files to misc. If I don't move
them to a right place, I can't add any patch for this driver.

Signed-off-by: Rui Feng 
Acked-by: Arnd Bergmann 
Acked-for-MFD-by: Lee Jones 
Reviewed-by: Daniel Bristot de Oliveira 
Acked-by: Ulf Hansson 

v7 changes:
* update missing modification in memstic
* add Acked-by
---
 drivers/memstick/host/Kconfig   |  4 ++--
 drivers/memstick/host/rtsx_pci_ms.c |  2 +-
 drivers/memstick/host/rtsx_usb_ms.c |  2 +-
 drivers/mfd/Kconfig | 21 -
 drivers/mfd/Makefile|  4 
 drivers/misc/Kconfig|  5 +
 drivers/misc/Makefile   |  1 +
 drivers/misc/cardreader/Kconfig | 20 
 drivers/misc/cardreader/Makefile|  4 
 drivers/{mfd => misc/cardreader}/rtl8411.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5209.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5227.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5229.c  |  2 +-
 drivers/{mfd => misc/cardreader}/rts5249.c  |  3 +--
 drivers/{mfd => misc/cardreader}/rtsx_pcr.c |  2 +-
 drivers/{mfd => misc/cardreader}/rtsx_pcr.h |  2 +-
 drivers/{mfd => misc/cardreader}/rtsx_usb.c |  2 +-
 drivers/mmc/host/Kconfig|  4 ++--
 drivers/mmc/host/rtsx_pci_sdmmc.c   |  2 +-
 drivers/mmc/host/rtsx_usb_sdmmc.c   |  2 +-
 include/linux/{mfd => }/rtsx_common.h   |  0
 include/linux/{mfd => }/rtsx_pci.h  |  2 +-
 include/linux/{mfd => }/rtsx_usb.h  |  0
 23 files changed, 47 insertions(+), 43 deletions(-)
 create mode 100644 drivers/misc/cardreader/Kconfig
 create mode 100644 drivers/misc/cardreader/Makefile
 rename drivers/{mfd => misc/cardreader}/rtl8411.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5209.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5227.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5229.c (99%)
 rename drivers/{mfd => misc/cardreader}/rts5249.c (99%)
 rename drivers/{mfd => misc/cardreader}/rtsx_pcr.c (99%)
 rename drivers/{mfd => misc/cardreader}/rtsx_pcr.h (99%)
 rename drivers/{mfd => misc/cardreader}/rtsx_usb.c (99%)
 rename include/linux/{mfd => }/rtsx_common.h (100%)
 rename include/linux/{mfd => }/rtsx_pci.h (99%)
 rename include/linux/{mfd => }/rtsx_usb.h (100%)

diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index 7310e32..aa2b078 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -45,7 +45,7 @@ config MEMSTICK_R592
 
 config MEMSTICK_REALTEK_PCI
tristate "Realtek PCI-E Memstick Card Interface Driver"
-   depends on MFD_RTSX_PCI
+   depends on MISC_RTSX_PCI
help
  Say Y here to include driver code to support Memstick card interface
  of Realtek PCI-E card reader
@@ -55,7 +55,7 @@ config MEMSTICK_REALTEK_PCI
 
 config MEMSTICK_REALTEK_USB
tristate "Realtek USB Memstick Card Interface Driver"
-   depends on MFD_RTSX_USB
+   depends on MISC_RTSX_USB
help
  Say Y here to include driver code to support Memstick card interface
  of Realtek RTS5129/39 series USB card reader
diff --git a/drivers/memstick/host/rtsx_pci_ms.c 
b/drivers/memstick/host/rtsx_pci_ms.c
index 818fa94..a44b457 100644
--- a/drivers/memstick/host/rtsx_pci_ms.c
+++ b/drivers/memstick/host/rtsx_pci_ms.c
@@ -24,7 +24,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 struct realtek_pci_ms {
diff --git a/drivers/memstick/host/rtsx_usb_ms.c 
b/drivers/memstick/host/rtsx_usb_ms.c
index 2e3cf01..4f64563 100644
--- a/drivers/memstick/host/rtsx_usb_ms.c
+++ b/drivers/memstick/host/rtsx_usb_ms.c
@@ -25,7 +25,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fc5e4fe..80fd23f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -916,17 +916,6 @@ config MFD_RDC321X
  southbridge which provides access to GPIOs and Watchdog using the
  southbridge PCI device configuration space.
 
-config MFD_RTSX_PCI
-   tristate "Realtek PCI-E card reader"
-   depends on PCI
-   select MFD_CORE
-   help
- This supports for Realtek PCI-Express card reader including rts5209,
- rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
- Realtek card reader supports access to many types of memory cards,
- such as Memory Stick, Memory Stick Pro, Secure Digital and
- MultiMediaCard.
-
 config MFD_RT5033
tristate "Richtek RT5033 Power Management IC"
depends on I2C
@@ -940,16 +929,6 @@ 

Re: [PATCH] s390/drivers: use setup_timer instead of init_timer

2017-11-26 Thread Julian Wiedmann
On 11/24/2017 01:50 PM, Colin King wrote:
> From: Colin Ian King 
> 
> Use setup_timer function instead of initializing timer with the
> function and data fields.
> 
> Signed-off-by: Colin Ian King 
> ---
>  drivers/s390/net/fsm.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
> index 8c14c6c3ad3d..16b81be1f07a 100644
> --- a/drivers/s390/net/fsm.c
> +++ b/drivers/s390/net/fsm.c
> @@ -142,13 +142,11 @@ void
>  fsm_settimer(fsm_instance *fi, fsm_timer *this)
>  {
>   this->fi = fi;
> - this->tl.function = (void *)fsm_expire_timer;
> - this->tl.data = (long)this;
>  #if FSM_TIMER_DEBUG
>   printk(KERN_DEBUG "fsm(%s): Create timer %p\n", fi->name,
>  this);
>  #endif
> - init_timer(>tl);
> + setup_timer(>tl, (void *)fsm_expire_timer, (long)this);
>  }
> 
>  void
> 

Thanks Colin, but looks like Kees beat you to it in Linus' tree.



Re: [PATCH] s390/drivers: use setup_timer instead of init_timer

2017-11-26 Thread Julian Wiedmann
On 11/24/2017 01:50 PM, Colin King wrote:
> From: Colin Ian King 
> 
> Use setup_timer function instead of initializing timer with the
> function and data fields.
> 
> Signed-off-by: Colin Ian King 
> ---
>  drivers/s390/net/fsm.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
> index 8c14c6c3ad3d..16b81be1f07a 100644
> --- a/drivers/s390/net/fsm.c
> +++ b/drivers/s390/net/fsm.c
> @@ -142,13 +142,11 @@ void
>  fsm_settimer(fsm_instance *fi, fsm_timer *this)
>  {
>   this->fi = fi;
> - this->tl.function = (void *)fsm_expire_timer;
> - this->tl.data = (long)this;
>  #if FSM_TIMER_DEBUG
>   printk(KERN_DEBUG "fsm(%s): Create timer %p\n", fi->name,
>  this);
>  #endif
> - init_timer(>tl);
> + setup_timer(>tl, (void *)fsm_expire_timer, (long)this);
>  }
> 
>  void
> 

Thanks Colin, but looks like Kees beat you to it in Linus' tree.



Re: [PATCH 2/3] hwrng: exynos - add Samsung Exynos True RNG driver

2017-11-26 Thread Łukasz Stelmach
It was <2017-11-24 pią 16:25>, when PrasannaKumar Muralidharan wrote:
>> +}
>> +
>> +static int exynos_trng_do_read(struct hwrng *rng, void *data, size_t max,
>> +  bool wait)
>> +{
>> +   struct exynos_trng_dev *trng;
>> +   u32 val;
>> +
>> +   max = max > (EXYNOS_TRNG_FIFO_LEN * 4) ?
>> +   (EXYNOS_TRNG_FIFO_LEN * 4) : max;
>
> max is always > 32. This condition is not required.

No, it is not. 
http://elixir.free-electrons.com/linux/latest/source/drivers/char/hw_random/core.c#L67
-- 
Łukasz Stelmach
Samsung R Institute Poland
Samsung Electronics


signature.asc
Description: PGP signature


Re: [PATCH 2/3] hwrng: exynos - add Samsung Exynos True RNG driver

2017-11-26 Thread Łukasz Stelmach
It was <2017-11-24 pią 16:25>, when PrasannaKumar Muralidharan wrote:
>> +}
>> +
>> +static int exynos_trng_do_read(struct hwrng *rng, void *data, size_t max,
>> +  bool wait)
>> +{
>> +   struct exynos_trng_dev *trng;
>> +   u32 val;
>> +
>> +   max = max > (EXYNOS_TRNG_FIFO_LEN * 4) ?
>> +   (EXYNOS_TRNG_FIFO_LEN * 4) : max;
>
> max is always > 32. This condition is not required.

No, it is not. 
http://elixir.free-electrons.com/linux/latest/source/drivers/char/hw_random/core.c#L67
-- 
Łukasz Stelmach
Samsung R Institute Poland
Samsung Electronics


signature.asc
Description: PGP signature


[PATCH v4 2/4] vm: add a syscall to map a process memory into a pipe

2017-11-26 Thread Mike Rapoport
From: Andrei Vagin 

It is a hybrid of process_vm_readv() and vmsplice().

vmsplice can map memory from a current address space into a pipe.
process_vm_readv can read memory of another process.

A new system call can map memory of another process into a pipe.

ssize_t process_vmsplice(pid_t pid, int fd, const struct iovec *iov,
unsigned long nr_segs, unsigned int flags)

All arguments are identical with vmsplice except pid which specifies a
target process.

Currently if we want to dump a process memory to a file or to a socket,
we can use process_vm_readv() + write(), but it works slow, because data
are copied into a temporary user-space buffer.

A second way is to use vmsplice() + splice(). It is more effective,
because data are not copied into a temporary buffer, but here is another
problem. vmsplice works with the currect address space, so it can be
used only if we inject our code into a target process.

The second way suffers from a few other issues:
* a process has to be stopped to run a parasite code
* a number of pipes is limited, so it may be impossible to dump all
  memory in one iteration, and we have to stop process and inject our
  code a few times.
* pages in pipes are unreclaimable, so it isn't good to hold a lot of
  memory in pipes.

The introduced syscall allows to use a second way without injecting any
code into a target process.

My experiments shows that process_vmsplice() + splice() works two time
faster than process_vm_readv() + write().

It is particularly useful on a pre-dump stage. On this stage we enable a
memory tracker, and then we are dumping  a process memory while a
process continues work. On the first iteration we are dumping all
memory, and then we are dumpung only modified memory from a previous
iteration.  After a few pre-dump operations, a process is stopped and
dumped finally. The pre-dump operations allow to significantly decrease
a process downtime, when a process is migrated to another host.

v2: move this syscall under CONFIG_CROSS_MEMORY_ATTACH
give correct flags to get_user_pages_remote()

Signed-off-by: Andrei Vagin 
Signed-off-by: Mike Rapoport 
---
 fs/splice.c   | 205 ++
 include/linux/compat.h|   3 +
 include/linux/syscalls.h  |   4 +
 include/uapi/asm-generic/unistd.h |   5 +-
 kernel/sys_ni.c   |   2 +
 5 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/fs/splice.c b/fs/splice.c
index 7f1ffc5..72397d2 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "internal.h"
 
@@ -1373,6 +1374,210 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec 
__user *, iov,
return error;
 }
 
+#ifdef CONFIG_CROSS_MEMORY_ATTACH
+/*
+ * Map pages from a specified task into a pipe
+ */
+static int remote_single_vec_to_pipe(struct task_struct *task,
+   struct mm_struct *mm,
+   const struct iovec *rvec,
+   struct pipe_inode_info *pipe,
+   unsigned int flags,
+   size_t *total)
+{
+   struct pipe_buffer buf = {
+   .ops = _page_pipe_buf_ops,
+   .flags = flags
+   };
+   unsigned long addr = (unsigned long) rvec->iov_base;
+   unsigned long pa = addr & PAGE_MASK;
+   unsigned long start_offset = addr - pa;
+   unsigned long nr_pages;
+   ssize_t len = rvec->iov_len;
+   struct page *process_pages[16];
+   bool failed = false;
+   int ret = 0;
+
+   nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1;
+   while (nr_pages) {
+   long pages = min(nr_pages, 16UL);
+   int locked = 1;
+   ssize_t copied;
+
+   /*
+* Get the pages we're interested in.  We must
+* access remotely because task/mm might not
+* current/current->mm
+*/
+   down_read(>mmap_sem);
+   pages = get_user_pages_remote(task, mm, pa, pages, 0,
+ process_pages, NULL, );
+   if (locked)
+   up_read(>mmap_sem);
+   if (pages <= 0) {
+   failed = true;
+   ret = -EFAULT;
+   break;
+   }
+
+   copied = pages * PAGE_SIZE - start_offset;
+   if (copied > len)
+   copied = len;
+   len -= copied;
+
+   ret = pages_to_pipe(process_pages, pipe, , total, copied,
+   start_offset);
+   if (unlikely(ret < 0))
+   break;
+
+   start_offset = 0;
+   nr_pages -= pages;
+   pa += pages * PAGE_SIZE;
+   }
+   

[PATCH v4 2/4] vm: add a syscall to map a process memory into a pipe

2017-11-26 Thread Mike Rapoport
From: Andrei Vagin 

It is a hybrid of process_vm_readv() and vmsplice().

vmsplice can map memory from a current address space into a pipe.
process_vm_readv can read memory of another process.

A new system call can map memory of another process into a pipe.

ssize_t process_vmsplice(pid_t pid, int fd, const struct iovec *iov,
unsigned long nr_segs, unsigned int flags)

All arguments are identical with vmsplice except pid which specifies a
target process.

Currently if we want to dump a process memory to a file or to a socket,
we can use process_vm_readv() + write(), but it works slow, because data
are copied into a temporary user-space buffer.

A second way is to use vmsplice() + splice(). It is more effective,
because data are not copied into a temporary buffer, but here is another
problem. vmsplice works with the currect address space, so it can be
used only if we inject our code into a target process.

The second way suffers from a few other issues:
* a process has to be stopped to run a parasite code
* a number of pipes is limited, so it may be impossible to dump all
  memory in one iteration, and we have to stop process and inject our
  code a few times.
* pages in pipes are unreclaimable, so it isn't good to hold a lot of
  memory in pipes.

The introduced syscall allows to use a second way without injecting any
code into a target process.

My experiments shows that process_vmsplice() + splice() works two time
faster than process_vm_readv() + write().

It is particularly useful on a pre-dump stage. On this stage we enable a
memory tracker, and then we are dumping  a process memory while a
process continues work. On the first iteration we are dumping all
memory, and then we are dumpung only modified memory from a previous
iteration.  After a few pre-dump operations, a process is stopped and
dumped finally. The pre-dump operations allow to significantly decrease
a process downtime, when a process is migrated to another host.

v2: move this syscall under CONFIG_CROSS_MEMORY_ATTACH
give correct flags to get_user_pages_remote()

Signed-off-by: Andrei Vagin 
Signed-off-by: Mike Rapoport 
---
 fs/splice.c   | 205 ++
 include/linux/compat.h|   3 +
 include/linux/syscalls.h  |   4 +
 include/uapi/asm-generic/unistd.h |   5 +-
 kernel/sys_ni.c   |   2 +
 5 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/fs/splice.c b/fs/splice.c
index 7f1ffc5..72397d2 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "internal.h"
 
@@ -1373,6 +1374,210 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec 
__user *, iov,
return error;
 }
 
+#ifdef CONFIG_CROSS_MEMORY_ATTACH
+/*
+ * Map pages from a specified task into a pipe
+ */
+static int remote_single_vec_to_pipe(struct task_struct *task,
+   struct mm_struct *mm,
+   const struct iovec *rvec,
+   struct pipe_inode_info *pipe,
+   unsigned int flags,
+   size_t *total)
+{
+   struct pipe_buffer buf = {
+   .ops = _page_pipe_buf_ops,
+   .flags = flags
+   };
+   unsigned long addr = (unsigned long) rvec->iov_base;
+   unsigned long pa = addr & PAGE_MASK;
+   unsigned long start_offset = addr - pa;
+   unsigned long nr_pages;
+   ssize_t len = rvec->iov_len;
+   struct page *process_pages[16];
+   bool failed = false;
+   int ret = 0;
+
+   nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1;
+   while (nr_pages) {
+   long pages = min(nr_pages, 16UL);
+   int locked = 1;
+   ssize_t copied;
+
+   /*
+* Get the pages we're interested in.  We must
+* access remotely because task/mm might not
+* current/current->mm
+*/
+   down_read(>mmap_sem);
+   pages = get_user_pages_remote(task, mm, pa, pages, 0,
+ process_pages, NULL, );
+   if (locked)
+   up_read(>mmap_sem);
+   if (pages <= 0) {
+   failed = true;
+   ret = -EFAULT;
+   break;
+   }
+
+   copied = pages * PAGE_SIZE - start_offset;
+   if (copied > len)
+   copied = len;
+   len -= copied;
+
+   ret = pages_to_pipe(process_pages, pipe, , total, copied,
+   start_offset);
+   if (unlikely(ret < 0))
+   break;
+
+   start_offset = 0;
+   nr_pages -= pages;
+   pa += pages * PAGE_SIZE;
+   }
+   return ret < 0 ? ret : 0;
+}
+
+static ssize_t 

[PATCH] process_vmsplice.2: New page describing process_vmsplice(2) system call.

2017-11-26 Thread Mike Rapoport
Signed-off-by: Mike Rapoport 
---
 man2/process_vmsplice.2 | 188 
 1 file changed, 188 insertions(+)
 create mode 100644 man2/process_vmsplice.2

diff --git a/man2/process_vmsplice.2 b/man2/process_vmsplice.2
new file mode 100644
index 000..b99c06b
--- /dev/null
+++ b/man2/process_vmsplice.2
@@ -0,0 +1,188 @@
+.\" Copyright (c) 2017, IBM Corporation.
+.\" Written by Mike Rapoport 
+.\" Based on vmsplice(2) by Jens Axboe and
+.\" process_vm_read(2) by Christopher Yeoh, Mike Frysinger and Michael Kerrisk
+.\"
+.\" %%%LICENSE_START(VERBATIM)
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date.  The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein.  The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\" %%%LICENSE_END
+.\"
+.TH PROCESS_VMSPLICE 2 2017-11-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+process_vmsplice \- splice user pages from a specific process
+address space into a pipe
+.SH SYNOPSIS
+.nf
+.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
+.B #include 
+.B #include 
+.PP
+.BI "ssize_t process_vmsplice(pid_t " pid ", int " fd ,
+.BI " const struct iovec *" iov ,
+.BI " unsigned long " nr_segs ,
+.BI " unsigned int " flags );
+.fi
+.PP
+.IR Note :
+There is no glibc wrapper for this system call; see NOTES.
+.SH DESCRIPTION
+The
+.BR process_vmsplice ()
+system call maps
+.I nr_segs
+ranges of user memory described by
+.I iov
+from address space of the process identified by
+.I pid
+into a pipe.
+The file descriptor
+.I fd
+must refer to a pipe.
+.PP
+The pointer
+.I iov
+points to an array of
+.I iovec
+structures as defined in
+.IR  :
+.PP
+.in +4n
+.EX
+struct iovec {
+void  *iov_base;/* Starting address */
+size_t iov_len; /* Number of bytes */
+};
+.EE
+.in
+.PP
+The
+.I flags
+argument is a bit mask that is composed by ORing together
+zero or more of the following values:
+.RS
+.TP 1.9i
+.B SPLICE_F_MOVE
+Unused for
+.BR process_vmsplice ();
+see
+.BR splice (2).
+.TP
+.B SPLICE_F_NONBLOCK
+Do not block on I/O; see
+.BR splice (2)
+for further details.
+.TP
+.B SPLICE_F_MORE
+Currently has no effect for
+.BR process_vmsplice ()
+.TP
+.B SPLICE_F_GIFT
+The user pages are a gift to the kernel.
+see
+.BR vmsplice (2)
+for further details.
+.RE
+.PP
+Buffers pointed by the
+.I iov
+parameter are processed in array order.
+This means that
+.BR process_vmsplice ()
+completely fills
+.I iov[0]
+before proceeding to
+.IR iov[1] ,
+and so on.
+.PP
+The
+.BR process_vmsplice ()
+does not check the memory regions in the process
+until just before remapping those regions into the pipe.
+Consequently, a partial read may result if one of the
+.I iov
+elements points to an invalid memory region in the process.
+No further reads will be attempted beyond that point.
+.PP
+Permission to read from or write to another process
+is governed by a ptrace access mode
+.B PTRACE_MODE_ATTACH_REALCREDS
+check; see
+.BR ptrace (2).
+.SH RETURN VALUE
+Upon successful completion,
+.BR process_vmsplice ()
+returns the number of bytes transferred to the pipe.
+On error,
+.BR process_vmsplice ()
+returns \-1 and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EAGAIN
+.B SPLICE_F_NONBLOCK
+was specified in
+.IR flags ,
+and the operation would block.
+.TP
+.B EBADF
+.I fd
+either not valid, or doesn't refer to a pipe.
+.TP
+.B EINVAL
+.I nr_segs
+is greater than
+.BR IOV_MAX ;
+or memory not aligned if
+.B SPLICE_F_GIFT
+set.
+.TP
+.B ENOMEM
+Out of memory.
+.TP
+.B ESRCH
+No process with ID
+.I pid
+exists.
+.SH VERSIONS
+The
+.BR process_vmsplice ()
+system call first appeared in Linux 4.15.
+.SH CONFORMING TO
+This system call is Linux-specific.
+.SH NOTES
+Glibc does not provide a wrapper for this system call; call it using
+.BR syscall (2).
+.BR process_vmsplice ()
+follows the other vectorized read/write type functions when it comes to
+limitations on the number of segments being passed in.
+This limit 

[PATCH] process_vmsplice.2: New page describing process_vmsplice(2) system call.

2017-11-26 Thread Mike Rapoport
Signed-off-by: Mike Rapoport 
---
 man2/process_vmsplice.2 | 188 
 1 file changed, 188 insertions(+)
 create mode 100644 man2/process_vmsplice.2

diff --git a/man2/process_vmsplice.2 b/man2/process_vmsplice.2
new file mode 100644
index 000..b99c06b
--- /dev/null
+++ b/man2/process_vmsplice.2
@@ -0,0 +1,188 @@
+.\" Copyright (c) 2017, IBM Corporation.
+.\" Written by Mike Rapoport 
+.\" Based on vmsplice(2) by Jens Axboe and
+.\" process_vm_read(2) by Christopher Yeoh, Mike Frysinger and Michael Kerrisk
+.\"
+.\" %%%LICENSE_START(VERBATIM)
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date.  The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein.  The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\" %%%LICENSE_END
+.\"
+.TH PROCESS_VMSPLICE 2 2017-11-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+process_vmsplice \- splice user pages from a specific process
+address space into a pipe
+.SH SYNOPSIS
+.nf
+.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
+.B #include 
+.B #include 
+.PP
+.BI "ssize_t process_vmsplice(pid_t " pid ", int " fd ,
+.BI " const struct iovec *" iov ,
+.BI " unsigned long " nr_segs ,
+.BI " unsigned int " flags );
+.fi
+.PP
+.IR Note :
+There is no glibc wrapper for this system call; see NOTES.
+.SH DESCRIPTION
+The
+.BR process_vmsplice ()
+system call maps
+.I nr_segs
+ranges of user memory described by
+.I iov
+from address space of the process identified by
+.I pid
+into a pipe.
+The file descriptor
+.I fd
+must refer to a pipe.
+.PP
+The pointer
+.I iov
+points to an array of
+.I iovec
+structures as defined in
+.IR  :
+.PP
+.in +4n
+.EX
+struct iovec {
+void  *iov_base;/* Starting address */
+size_t iov_len; /* Number of bytes */
+};
+.EE
+.in
+.PP
+The
+.I flags
+argument is a bit mask that is composed by ORing together
+zero or more of the following values:
+.RS
+.TP 1.9i
+.B SPLICE_F_MOVE
+Unused for
+.BR process_vmsplice ();
+see
+.BR splice (2).
+.TP
+.B SPLICE_F_NONBLOCK
+Do not block on I/O; see
+.BR splice (2)
+for further details.
+.TP
+.B SPLICE_F_MORE
+Currently has no effect for
+.BR process_vmsplice ()
+.TP
+.B SPLICE_F_GIFT
+The user pages are a gift to the kernel.
+see
+.BR vmsplice (2)
+for further details.
+.RE
+.PP
+Buffers pointed by the
+.I iov
+parameter are processed in array order.
+This means that
+.BR process_vmsplice ()
+completely fills
+.I iov[0]
+before proceeding to
+.IR iov[1] ,
+and so on.
+.PP
+The
+.BR process_vmsplice ()
+does not check the memory regions in the process
+until just before remapping those regions into the pipe.
+Consequently, a partial read may result if one of the
+.I iov
+elements points to an invalid memory region in the process.
+No further reads will be attempted beyond that point.
+.PP
+Permission to read from or write to another process
+is governed by a ptrace access mode
+.B PTRACE_MODE_ATTACH_REALCREDS
+check; see
+.BR ptrace (2).
+.SH RETURN VALUE
+Upon successful completion,
+.BR process_vmsplice ()
+returns the number of bytes transferred to the pipe.
+On error,
+.BR process_vmsplice ()
+returns \-1 and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EAGAIN
+.B SPLICE_F_NONBLOCK
+was specified in
+.IR flags ,
+and the operation would block.
+.TP
+.B EBADF
+.I fd
+either not valid, or doesn't refer to a pipe.
+.TP
+.B EINVAL
+.I nr_segs
+is greater than
+.BR IOV_MAX ;
+or memory not aligned if
+.B SPLICE_F_GIFT
+set.
+.TP
+.B ENOMEM
+Out of memory.
+.TP
+.B ESRCH
+No process with ID
+.I pid
+exists.
+.SH VERSIONS
+The
+.BR process_vmsplice ()
+system call first appeared in Linux 4.15.
+.SH CONFORMING TO
+This system call is Linux-specific.
+.SH NOTES
+Glibc does not provide a wrapper for this system call; call it using
+.BR syscall (2).
+.BR process_vmsplice ()
+follows the other vectorized read/write type functions when it comes to
+limitations on the number of segments being passed in.
+This limit is
+.B IOV_MAX
+as defined in
+.IR  .
+Currently,

[PATCH v4 1/4] fs/splice: introduce pages_to_pipe helper

2017-11-26 Thread Mike Rapoport
Signed-off-by: Mike Rapoport 
---
 fs/splice.c | 57 -
 1 file changed, 36 insertions(+), 21 deletions(-)

diff --git a/fs/splice.c b/fs/splice.c
index 39e2dc0..7f1ffc5 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1185,6 +1185,36 @@ static long do_splice(struct file *in, loff_t __user 
*off_in,
return -EINVAL;
 }
 
+static int pages_to_pipe(struct page **pages, struct pipe_inode_info *pipe,
+struct pipe_buffer *buf, size_t *total,
+ssize_t copied, size_t start)
+{
+   bool failed = false;
+   size_t len = 0;
+   int ret = 0;
+   int n;
+
+   for (n = 0; copied; n++, start = 0) {
+   int size = min_t(int, copied, PAGE_SIZE - start);
+   if (!failed) {
+   buf->page = pages[n];
+   buf->offset = start;
+   buf->len = size;
+   ret = add_to_pipe(pipe, buf);
+   if (unlikely(ret < 0))
+   failed = true;
+   else
+   len += ret;
+   } else {
+   put_page(pages[n]);
+   }
+   copied -= size;
+   }
+
+   *total += len;
+   return failed ? ret : len;
+}
+
 static int iter_to_pipe(struct iov_iter *from,
struct pipe_inode_info *pipe,
unsigned flags)
@@ -1195,13 +1225,11 @@ static int iter_to_pipe(struct iov_iter *from,
};
size_t total = 0;
int ret = 0;
-   bool failed = false;
 
-   while (iov_iter_count(from) && !failed) {
+   while (iov_iter_count(from)) {
struct page *pages[16];
ssize_t copied;
size_t start;
-   int n;
 
copied = iov_iter_get_pages(from, pages, ~0UL, 16, );
if (copied <= 0) {
@@ -1209,24 +1237,11 @@ static int iter_to_pipe(struct iov_iter *from,
break;
}
 
-   for (n = 0; copied; n++, start = 0) {
-   int size = min_t(int, copied, PAGE_SIZE - start);
-   if (!failed) {
-   buf.page = pages[n];
-   buf.offset = start;
-   buf.len = size;
-   ret = add_to_pipe(pipe, );
-   if (unlikely(ret < 0)) {
-   failed = true;
-   } else {
-   iov_iter_advance(from, ret);
-   total += ret;
-   }
-   } else {
-   put_page(pages[n]);
-   }
-   copied -= size;
-   }
+   ret = pages_to_pipe(pages, pipe, , , copied, start);
+   if (unlikely(ret < 0))
+   break;
+
+   iov_iter_advance(from, ret);
}
return total ? total : ret;
 }
-- 
2.7.4



[PATCH v4 1/4] fs/splice: introduce pages_to_pipe helper

2017-11-26 Thread Mike Rapoport
Signed-off-by: Mike Rapoport 
---
 fs/splice.c | 57 -
 1 file changed, 36 insertions(+), 21 deletions(-)

diff --git a/fs/splice.c b/fs/splice.c
index 39e2dc0..7f1ffc5 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1185,6 +1185,36 @@ static long do_splice(struct file *in, loff_t __user 
*off_in,
return -EINVAL;
 }
 
+static int pages_to_pipe(struct page **pages, struct pipe_inode_info *pipe,
+struct pipe_buffer *buf, size_t *total,
+ssize_t copied, size_t start)
+{
+   bool failed = false;
+   size_t len = 0;
+   int ret = 0;
+   int n;
+
+   for (n = 0; copied; n++, start = 0) {
+   int size = min_t(int, copied, PAGE_SIZE - start);
+   if (!failed) {
+   buf->page = pages[n];
+   buf->offset = start;
+   buf->len = size;
+   ret = add_to_pipe(pipe, buf);
+   if (unlikely(ret < 0))
+   failed = true;
+   else
+   len += ret;
+   } else {
+   put_page(pages[n]);
+   }
+   copied -= size;
+   }
+
+   *total += len;
+   return failed ? ret : len;
+}
+
 static int iter_to_pipe(struct iov_iter *from,
struct pipe_inode_info *pipe,
unsigned flags)
@@ -1195,13 +1225,11 @@ static int iter_to_pipe(struct iov_iter *from,
};
size_t total = 0;
int ret = 0;
-   bool failed = false;
 
-   while (iov_iter_count(from) && !failed) {
+   while (iov_iter_count(from)) {
struct page *pages[16];
ssize_t copied;
size_t start;
-   int n;
 
copied = iov_iter_get_pages(from, pages, ~0UL, 16, );
if (copied <= 0) {
@@ -1209,24 +1237,11 @@ static int iter_to_pipe(struct iov_iter *from,
break;
}
 
-   for (n = 0; copied; n++, start = 0) {
-   int size = min_t(int, copied, PAGE_SIZE - start);
-   if (!failed) {
-   buf.page = pages[n];
-   buf.offset = start;
-   buf.len = size;
-   ret = add_to_pipe(pipe, );
-   if (unlikely(ret < 0)) {
-   failed = true;
-   } else {
-   iov_iter_advance(from, ret);
-   total += ret;
-   }
-   } else {
-   put_page(pages[n]);
-   }
-   copied -= size;
-   }
+   ret = pages_to_pipe(pages, pipe, , , copied, start);
+   if (unlikely(ret < 0))
+   break;
+
+   iov_iter_advance(from, ret);
}
return total ? total : ret;
 }
-- 
2.7.4



[PATCH v4 4/4] test: add a test for the process_vmsplice syscall

2017-11-26 Thread Mike Rapoport
From: Andrei Vagin 

This test checks that process_vmsplice() can splice pages from a remote
process and returns EFAULT, if process_vmsplice() tries to splice pages
by an unaccessiable address.

Signed-off-by: Andrei Vagin 
Signed-off-by: Mike Rapoport 
---
 tools/testing/selftests/process_vmsplice/Makefile  |   5 +
 .../process_vmsplice/process_vmsplice_test.c   | 196 +
 2 files changed, 201 insertions(+)
 create mode 100644 tools/testing/selftests/process_vmsplice/Makefile
 create mode 100644 
tools/testing/selftests/process_vmsplice/process_vmsplice_test.c

diff --git a/tools/testing/selftests/process_vmsplice/Makefile 
b/tools/testing/selftests/process_vmsplice/Makefile
new file mode 100644
index 000..246d5a7
--- /dev/null
+++ b/tools/testing/selftests/process_vmsplice/Makefile
@@ -0,0 +1,5 @@
+CFLAGS += -I../../../../usr/include/
+
+TEST_GEN_PROGS := process_vmsplice_test
+
+include ../lib.mk
diff --git a/tools/testing/selftests/process_vmsplice/process_vmsplice_test.c 
b/tools/testing/selftests/process_vmsplice/process_vmsplice_test.c
new file mode 100644
index 000..1682bdb
--- /dev/null
+++ b/tools/testing/selftests/process_vmsplice/process_vmsplice_test.c
@@ -0,0 +1,196 @@
+#define _GNU_SOURCE
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "../kselftest.h"
+
+#ifndef __NR_process_vmsplice
+#define __NR_process_vmsplice 333
+#endif
+
+#define pr_err(fmt, ...) \
+   ({ \
+   fprintf(stderr, "%s:%d:" fmt, \
+   __func__, __LINE__, ##__VA_ARGS__); \
+   KSFT_FAIL; \
+   })
+#define pr_perror(fmt, ...) pr_err(fmt ": %m\n", ##__VA_ARGS__)
+#define fail(fmt, ...) pr_err("FAIL:" fmt, ##__VA_ARGS__)
+
+static ssize_t process_vmsplice(pid_t pid, int fd, const struct iovec *iov,
+   unsigned long nr_segs, unsigned int flags)
+{
+   return syscall(__NR_process_vmsplice, pid, fd, iov, nr_segs, flags);
+
+}
+
+#define MEM_SIZE (4096 * 100)
+#define MEM_WRONLY_SIZE (4096 * 10)
+
+int main(int argc, char **argv)
+{
+   char *addr, *addr_wronly;
+   int p[2];
+   struct iovec iov[2];
+   char buf[4096];
+   int status, ret;
+   pid_t pid;
+
+   ksft_print_header();
+
+   if (process_vmsplice(0, 0, 0, 0, 0)) {
+   if (errno == ENOSYS) {
+   ksft_exit_skip("process_vmsplice is not supported\n");
+   return 0;
+   }
+   return pr_perror("Zero-length process_vmsplice failed");
+   }
+
+   addr = mmap(0, MEM_SIZE, PROT_READ | PROT_WRITE,
+   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+   if (addr == MAP_FAILED)
+   return pr_perror("Unable to create a mapping");
+
+   addr_wronly = mmap(0, MEM_WRONLY_SIZE, PROT_WRITE,
+   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+   if (addr_wronly == MAP_FAILED)
+   return pr_perror("Unable to create a write-only mapping");
+
+   if (pipe(p))
+   return pr_perror("Unable to create a pipe");
+
+   pid = fork();
+   if (pid < 0)
+   return pr_perror("Unable to fork");
+
+   if (pid == 0) {
+   addr[0] = 'C';
+   addr[4096 + 128] = 'A';
+   addr[4096 + 128 + 4096 - 1] = 'B';
+
+   if (prctl(PR_SET_PDEATHSIG, SIGKILL))
+   return pr_perror("Unable to set PR_SET_PDEATHSIG");
+   if (write(p[1], "c", 1) != 1)
+   return pr_perror("Unable to write data into pipe");
+
+   while (1)
+   sleep(1);
+   return 1;
+   }
+   if (read(p[0], buf, 1) != 1) {
+   pr_perror("Unable to read data from pipe");
+   kill(pid, SIGKILL);
+   wait();
+   return 1;
+   }
+
+   munmap(addr, MEM_SIZE);
+   munmap(addr_wronly, MEM_WRONLY_SIZE);
+
+   iov[0].iov_base = addr;
+   iov[0].iov_len = 1;
+
+   iov[1].iov_base = addr + 4096 + 128;
+   iov[1].iov_len = 4096;
+
+   /* check one iovec */
+   if (process_vmsplice(pid, p[1], iov, 1, SPLICE_F_GIFT) != 1)
+   return pr_perror("Unable to splice pages");
+
+   if (read(p[0], buf, 1) != 1)
+   return pr_perror("Unable to read from pipe");
+
+   if (buf[0] != 'C')
+   ksft_test_result_fail("Get wrong data\n");
+   else
+   ksft_test_result_pass("Check process_vmsplice with one vec\n");
+
+   /* check two iovec-s */
+   if (process_vmsplice(pid, p[1], iov, 2, SPLICE_F_GIFT) != 4097)
+   return pr_perror("Unable to spice pages\n");
+
+   if (read(p[0], buf, 1) != 1)
+   return pr_perror("Unable to read from pipe\n");
+
+  

[PATCH v4 3/4] x86: wire up the process_vmsplice syscall

2017-11-26 Thread Mike Rapoport
From: Andrei Vagin 

Signed-off-by: Andrei Vagin 
---
 arch/x86/entry/syscalls/syscall_32.tbl | 1 +
 arch/x86/entry/syscalls/syscall_64.tbl | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/arch/x86/entry/syscalls/syscall_32.tbl 
b/arch/x86/entry/syscalls/syscall_32.tbl
index 448ac21..dc64bf5 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -391,3 +391,4 @@
 382i386pkey_free   sys_pkey_free
 383i386statx   sys_statx
 384i386arch_prctl  sys_arch_prctl  
compat_sys_arch_prctl
+385i386process_vmsplicesys_process_vmsplice
compat_sys_process_vmsplice
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl 
b/arch/x86/entry/syscalls/syscall_64.tbl
index 5aef183..d2f916c 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -339,6 +339,7 @@
 330common  pkey_alloc  sys_pkey_alloc
 331common  pkey_free   sys_pkey_free
 332common  statx   sys_statx
+33364  process_vmsplicesys_process_vmsplice
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
@@ -380,3 +381,4 @@
 545x32 execveatcompat_sys_execveat/ptregs
 546x32 preadv2 compat_sys_preadv64v2
 547x32 pwritev2compat_sys_pwritev64v2
+548x32 process_vmsplicecompat_sys_process_vmsplice
-- 
2.7.4



[PATCH v4 3/4] x86: wire up the process_vmsplice syscall

2017-11-26 Thread Mike Rapoport
From: Andrei Vagin 

Signed-off-by: Andrei Vagin 
---
 arch/x86/entry/syscalls/syscall_32.tbl | 1 +
 arch/x86/entry/syscalls/syscall_64.tbl | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/arch/x86/entry/syscalls/syscall_32.tbl 
b/arch/x86/entry/syscalls/syscall_32.tbl
index 448ac21..dc64bf5 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -391,3 +391,4 @@
 382i386pkey_free   sys_pkey_free
 383i386statx   sys_statx
 384i386arch_prctl  sys_arch_prctl  
compat_sys_arch_prctl
+385i386process_vmsplicesys_process_vmsplice
compat_sys_process_vmsplice
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl 
b/arch/x86/entry/syscalls/syscall_64.tbl
index 5aef183..d2f916c 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -339,6 +339,7 @@
 330common  pkey_alloc  sys_pkey_alloc
 331common  pkey_free   sys_pkey_free
 332common  statx   sys_statx
+33364  process_vmsplicesys_process_vmsplice
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
@@ -380,3 +381,4 @@
 545x32 execveatcompat_sys_execveat/ptregs
 546x32 preadv2 compat_sys_preadv64v2
 547x32 pwritev2compat_sys_pwritev64v2
+548x32 process_vmsplicecompat_sys_process_vmsplice
-- 
2.7.4



[PATCH v4 4/4] test: add a test for the process_vmsplice syscall

2017-11-26 Thread Mike Rapoport
From: Andrei Vagin 

This test checks that process_vmsplice() can splice pages from a remote
process and returns EFAULT, if process_vmsplice() tries to splice pages
by an unaccessiable address.

Signed-off-by: Andrei Vagin 
Signed-off-by: Mike Rapoport 
---
 tools/testing/selftests/process_vmsplice/Makefile  |   5 +
 .../process_vmsplice/process_vmsplice_test.c   | 196 +
 2 files changed, 201 insertions(+)
 create mode 100644 tools/testing/selftests/process_vmsplice/Makefile
 create mode 100644 
tools/testing/selftests/process_vmsplice/process_vmsplice_test.c

diff --git a/tools/testing/selftests/process_vmsplice/Makefile 
b/tools/testing/selftests/process_vmsplice/Makefile
new file mode 100644
index 000..246d5a7
--- /dev/null
+++ b/tools/testing/selftests/process_vmsplice/Makefile
@@ -0,0 +1,5 @@
+CFLAGS += -I../../../../usr/include/
+
+TEST_GEN_PROGS := process_vmsplice_test
+
+include ../lib.mk
diff --git a/tools/testing/selftests/process_vmsplice/process_vmsplice_test.c 
b/tools/testing/selftests/process_vmsplice/process_vmsplice_test.c
new file mode 100644
index 000..1682bdb
--- /dev/null
+++ b/tools/testing/selftests/process_vmsplice/process_vmsplice_test.c
@@ -0,0 +1,196 @@
+#define _GNU_SOURCE
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "../kselftest.h"
+
+#ifndef __NR_process_vmsplice
+#define __NR_process_vmsplice 333
+#endif
+
+#define pr_err(fmt, ...) \
+   ({ \
+   fprintf(stderr, "%s:%d:" fmt, \
+   __func__, __LINE__, ##__VA_ARGS__); \
+   KSFT_FAIL; \
+   })
+#define pr_perror(fmt, ...) pr_err(fmt ": %m\n", ##__VA_ARGS__)
+#define fail(fmt, ...) pr_err("FAIL:" fmt, ##__VA_ARGS__)
+
+static ssize_t process_vmsplice(pid_t pid, int fd, const struct iovec *iov,
+   unsigned long nr_segs, unsigned int flags)
+{
+   return syscall(__NR_process_vmsplice, pid, fd, iov, nr_segs, flags);
+
+}
+
+#define MEM_SIZE (4096 * 100)
+#define MEM_WRONLY_SIZE (4096 * 10)
+
+int main(int argc, char **argv)
+{
+   char *addr, *addr_wronly;
+   int p[2];
+   struct iovec iov[2];
+   char buf[4096];
+   int status, ret;
+   pid_t pid;
+
+   ksft_print_header();
+
+   if (process_vmsplice(0, 0, 0, 0, 0)) {
+   if (errno == ENOSYS) {
+   ksft_exit_skip("process_vmsplice is not supported\n");
+   return 0;
+   }
+   return pr_perror("Zero-length process_vmsplice failed");
+   }
+
+   addr = mmap(0, MEM_SIZE, PROT_READ | PROT_WRITE,
+   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+   if (addr == MAP_FAILED)
+   return pr_perror("Unable to create a mapping");
+
+   addr_wronly = mmap(0, MEM_WRONLY_SIZE, PROT_WRITE,
+   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+   if (addr_wronly == MAP_FAILED)
+   return pr_perror("Unable to create a write-only mapping");
+
+   if (pipe(p))
+   return pr_perror("Unable to create a pipe");
+
+   pid = fork();
+   if (pid < 0)
+   return pr_perror("Unable to fork");
+
+   if (pid == 0) {
+   addr[0] = 'C';
+   addr[4096 + 128] = 'A';
+   addr[4096 + 128 + 4096 - 1] = 'B';
+
+   if (prctl(PR_SET_PDEATHSIG, SIGKILL))
+   return pr_perror("Unable to set PR_SET_PDEATHSIG");
+   if (write(p[1], "c", 1) != 1)
+   return pr_perror("Unable to write data into pipe");
+
+   while (1)
+   sleep(1);
+   return 1;
+   }
+   if (read(p[0], buf, 1) != 1) {
+   pr_perror("Unable to read data from pipe");
+   kill(pid, SIGKILL);
+   wait();
+   return 1;
+   }
+
+   munmap(addr, MEM_SIZE);
+   munmap(addr_wronly, MEM_WRONLY_SIZE);
+
+   iov[0].iov_base = addr;
+   iov[0].iov_len = 1;
+
+   iov[1].iov_base = addr + 4096 + 128;
+   iov[1].iov_len = 4096;
+
+   /* check one iovec */
+   if (process_vmsplice(pid, p[1], iov, 1, SPLICE_F_GIFT) != 1)
+   return pr_perror("Unable to splice pages");
+
+   if (read(p[0], buf, 1) != 1)
+   return pr_perror("Unable to read from pipe");
+
+   if (buf[0] != 'C')
+   ksft_test_result_fail("Get wrong data\n");
+   else
+   ksft_test_result_pass("Check process_vmsplice with one vec\n");
+
+   /* check two iovec-s */
+   if (process_vmsplice(pid, p[1], iov, 2, SPLICE_F_GIFT) != 4097)
+   return pr_perror("Unable to spice pages\n");
+
+   if (read(p[0], buf, 1) != 1)
+   return pr_perror("Unable to read from pipe\n");
+
+   if (buf[0] != 'C')
+   

[PATCH v4 0/4] vm: add a syscall to map a process memory into a pipe

2017-11-26 Thread Mike Rapoport
Hi,

This patches introduces new process_vmsplice system call that combines
functionality of process_vm_read and vmsplice.

It allows to map the memory of another process into a pipe, similarly to
what vmsplice does for its own address space.

The patch 2/4 ("vm: add a syscall to map a process memory into a pipe")
actually adds the new system call and provides its elaborate description.

The patchset is against -mm tree.

v4: skip test when process_vmsplice syscall is not available
v3: minor refactoring to reduce code duplication
v2: move this syscall under CONFIG_CROSS_MEMORY_ATTACH
give correct flags to get_user_pages_remote()

Andrei Vagin (3):
  vm: add a syscall to map a process memory into a pipe
  x86: wire up the process_vmsplice syscall
  test: add a test for the process_vmsplice syscall

Mike Rapoport (1):
  fs/splice: introduce pages_to_pipe helper

 arch/x86/entry/syscalls/syscall_32.tbl |   1 +
 arch/x86/entry/syscalls/syscall_64.tbl |   2 +
 fs/splice.c| 262 +++--
 include/linux/compat.h |   3 +
 include/linux/syscalls.h   |   4 +
 include/uapi/asm-generic/unistd.h  |   5 +-
 kernel/sys_ni.c|   2 +
 tools/testing/selftests/process_vmsplice/Makefile  |   5 +
 .../process_vmsplice/process_vmsplice_test.c   | 196 +++
 9 files changed, 458 insertions(+), 22 deletions(-)
 create mode 100644 tools/testing/selftests/process_vmsplice/Makefile
 create mode 100644 
tools/testing/selftests/process_vmsplice/process_vmsplice_test.c

-- 
2.7.4



[PATCH v4 0/4] vm: add a syscall to map a process memory into a pipe

2017-11-26 Thread Mike Rapoport
Hi,

This patches introduces new process_vmsplice system call that combines
functionality of process_vm_read and vmsplice.

It allows to map the memory of another process into a pipe, similarly to
what vmsplice does for its own address space.

The patch 2/4 ("vm: add a syscall to map a process memory into a pipe")
actually adds the new system call and provides its elaborate description.

The patchset is against -mm tree.

v4: skip test when process_vmsplice syscall is not available
v3: minor refactoring to reduce code duplication
v2: move this syscall under CONFIG_CROSS_MEMORY_ATTACH
give correct flags to get_user_pages_remote()

Andrei Vagin (3):
  vm: add a syscall to map a process memory into a pipe
  x86: wire up the process_vmsplice syscall
  test: add a test for the process_vmsplice syscall

Mike Rapoport (1):
  fs/splice: introduce pages_to_pipe helper

 arch/x86/entry/syscalls/syscall_32.tbl |   1 +
 arch/x86/entry/syscalls/syscall_64.tbl |   2 +
 fs/splice.c| 262 +++--
 include/linux/compat.h |   3 +
 include/linux/syscalls.h   |   4 +
 include/uapi/asm-generic/unistd.h  |   5 +-
 kernel/sys_ni.c|   2 +
 tools/testing/selftests/process_vmsplice/Makefile  |   5 +
 .../process_vmsplice/process_vmsplice_test.c   | 196 +++
 9 files changed, 458 insertions(+), 22 deletions(-)
 create mode 100644 tools/testing/selftests/process_vmsplice/Makefile
 create mode 100644 
tools/testing/selftests/process_vmsplice/process_vmsplice_test.c

-- 
2.7.4



[PATCH RESEND] net: phy: harmonize phy_id{,_mask} data type

2017-11-26 Thread Richard Leitner
From: Richard Leitner 

Previously phy_id was u32 and phy_id_mask was unsigned int. As the
phy_id_mask defines the important bits of the phy_id (and is therefore
the same size) these two variables should be the same data type.

Signed-off-by: Richard Leitner 
Reviewed-by: Florian Fainelli 
Reviewed-by: Andrew Lunn 
---
RESEND as suggested by Andrew Lunn
---
 include/linux/phy.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index dc82a07cb4fd..e00fd9ce3bce 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -509,7 +509,7 @@ struct phy_driver {
struct mdio_driver_common mdiodrv;
u32 phy_id;
char *name;
-   unsigned int phy_id_mask;
+   u32 phy_id_mask;
u32 features;
u32 flags;
const void *driver_data;
-- 
2.11.0



[PATCH RESEND] net: phy: harmonize phy_id{,_mask} data type

2017-11-26 Thread Richard Leitner
From: Richard Leitner 

Previously phy_id was u32 and phy_id_mask was unsigned int. As the
phy_id_mask defines the important bits of the phy_id (and is therefore
the same size) these two variables should be the same data type.

Signed-off-by: Richard Leitner 
Reviewed-by: Florian Fainelli 
Reviewed-by: Andrew Lunn 
---
RESEND as suggested by Andrew Lunn
---
 include/linux/phy.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index dc82a07cb4fd..e00fd9ce3bce 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -509,7 +509,7 @@ struct phy_driver {
struct mdio_driver_common mdiodrv;
u32 phy_id;
char *name;
-   unsigned int phy_id_mask;
+   u32 phy_id_mask;
u32 features;
u32 flags;
const void *driver_data;
-- 
2.11.0



[RFC PATCH 2/2] net: macb: Tie-off unused RX queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Currently, we only use the first receive queue and leave the
remaining DMA descriptor pointers pointing at 0.

Disable unused queues by connecting them to a looped descriptor
chain without free slots.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  |  2 ++
 drivers/net/ethernet/cadence/macb_main.c | 42 
 2 files changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index acb6578..974c801 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -994,6 +994,7 @@ struct macb {
unsigned intrx_tail;
unsigned intrx_prepared_head;
struct macb_dma_desc*rx_ring;
+   struct macb_dma_desc*rx_ring_tieoff;
struct sk_buff  **rx_skbuff;
void*rx_buffers;
size_t  rx_buffer_size;
@@ -1019,6 +1020,7 @@ struct macb {
}   hw_stats;
 
dma_addr_t  rx_ring_dma;
+   dma_addr_t  rx_ring_tieoff_dma;
dma_addr_t  rx_buffers_dma;
 
struct macb_or_gem_ops  macbgem_ops;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 623ae9c..b14a04d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1755,6 +1755,12 @@ static void macb_free_consistent(struct macb *bp)
bp->rx_ring = NULL;
}
 
+   if (bp->rx_ring_tieoff) {
+   dma_free_coherent(>pdev->dev, sizeof(bp->rx_ring_tieoff[0]),
+ bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
+   bp->rx_ring_tieoff = NULL;
+   }
+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
kfree(queue->tx_skb);
queue->tx_skb = NULL;
@@ -1826,6 +1832,19 @@ static int macb_alloc_consistent(struct macb *bp)
 >rx_ring_dma, GFP_KERNEL);
if (!bp->rx_ring)
goto out_err;
+
+   /* If we have more than one queue, allocate a tie off descriptor
+* that will be used to disable unused RX queues.
+*/
+   if (bp->num_queues > 1) {
+   bp->rx_ring_tieoff = dma_alloc_coherent(>pdev->dev,
+   sizeof(bp->rx_ring_tieoff[0]),
+   >rx_ring_tieoff_dma,
+   GFP_KERNEL);
+   if (!bp->rx_ring_tieoff)
+   goto out_err;
+   }
+
netdev_dbg(bp->dev,
   "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
   size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
@@ -1840,6 +1859,19 @@ static int macb_alloc_consistent(struct macb *bp)
return -ENOMEM;
 }
 
+static void macb_init_tieoff(struct macb *bp)
+{
+   struct macb_dma_desc *d = bp->rx_ring_tieoff;
+
+   if (bp->num_queues > 1) {
+   /* Setup a wrapping descriptor with no free slots
+* (WRAP and USED) to tie off/disable unused RX queues.
+*/
+   d->addr = MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED);
+   d->ctrl = 0;
+   }
+}
+
 static void gem_init_rings(struct macb *bp)
 {
struct macb_queue *queue;
@@ -1862,6 +1894,7 @@ static void gem_init_rings(struct macb *bp)
bp->rx_prepared_head = 0;
 
gem_rx_refill(bp);
+   macb_init_tieoff(bp);
 }
 
 static void macb_init_rings(struct macb *bp)
@@ -1879,6 +1912,7 @@ static void macb_init_rings(struct macb *bp)
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
desc->ctrl |= MACB_BIT(TX_WRAP);
+   macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2063,6 +2097,14 @@ static void macb_init_hw(struct macb *bp)
queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
 #endif
 
+   /* We only use the first queue at the moment. Remaining
+* queues must be tied-off before we enable the receiver.
+*
+* See the documentation for receive_q1_ptr for more info.
+*/
+   if (q)
+   queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
/* Enable interrupts */
queue_writel(queue, IER,
 MACB_RX_INT_FLAGS |
-- 
2.7.4



[RFC PATCH 2/2] net: macb: Tie-off unused RX queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Currently, we only use the first receive queue and leave the
remaining DMA descriptor pointers pointing at 0.

Disable unused queues by connecting them to a looped descriptor
chain without free slots.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  |  2 ++
 drivers/net/ethernet/cadence/macb_main.c | 42 
 2 files changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index acb6578..974c801 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -994,6 +994,7 @@ struct macb {
unsigned intrx_tail;
unsigned intrx_prepared_head;
struct macb_dma_desc*rx_ring;
+   struct macb_dma_desc*rx_ring_tieoff;
struct sk_buff  **rx_skbuff;
void*rx_buffers;
size_t  rx_buffer_size;
@@ -1019,6 +1020,7 @@ struct macb {
}   hw_stats;
 
dma_addr_t  rx_ring_dma;
+   dma_addr_t  rx_ring_tieoff_dma;
dma_addr_t  rx_buffers_dma;
 
struct macb_or_gem_ops  macbgem_ops;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 623ae9c..b14a04d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1755,6 +1755,12 @@ static void macb_free_consistent(struct macb *bp)
bp->rx_ring = NULL;
}
 
+   if (bp->rx_ring_tieoff) {
+   dma_free_coherent(>pdev->dev, sizeof(bp->rx_ring_tieoff[0]),
+ bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
+   bp->rx_ring_tieoff = NULL;
+   }
+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
kfree(queue->tx_skb);
queue->tx_skb = NULL;
@@ -1826,6 +1832,19 @@ static int macb_alloc_consistent(struct macb *bp)
 >rx_ring_dma, GFP_KERNEL);
if (!bp->rx_ring)
goto out_err;
+
+   /* If we have more than one queue, allocate a tie off descriptor
+* that will be used to disable unused RX queues.
+*/
+   if (bp->num_queues > 1) {
+   bp->rx_ring_tieoff = dma_alloc_coherent(>pdev->dev,
+   sizeof(bp->rx_ring_tieoff[0]),
+   >rx_ring_tieoff_dma,
+   GFP_KERNEL);
+   if (!bp->rx_ring_tieoff)
+   goto out_err;
+   }
+
netdev_dbg(bp->dev,
   "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
   size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
@@ -1840,6 +1859,19 @@ static int macb_alloc_consistent(struct macb *bp)
return -ENOMEM;
 }
 
+static void macb_init_tieoff(struct macb *bp)
+{
+   struct macb_dma_desc *d = bp->rx_ring_tieoff;
+
+   if (bp->num_queues > 1) {
+   /* Setup a wrapping descriptor with no free slots
+* (WRAP and USED) to tie off/disable unused RX queues.
+*/
+   d->addr = MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED);
+   d->ctrl = 0;
+   }
+}
+
 static void gem_init_rings(struct macb *bp)
 {
struct macb_queue *queue;
@@ -1862,6 +1894,7 @@ static void gem_init_rings(struct macb *bp)
bp->rx_prepared_head = 0;
 
gem_rx_refill(bp);
+   macb_init_tieoff(bp);
 }
 
 static void macb_init_rings(struct macb *bp)
@@ -1879,6 +1912,7 @@ static void macb_init_rings(struct macb *bp)
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
desc->ctrl |= MACB_BIT(TX_WRAP);
+   macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2063,6 +2097,14 @@ static void macb_init_hw(struct macb *bp)
queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
 #endif
 
+   /* We only use the first queue at the moment. Remaining
+* queues must be tied-off before we enable the receiver.
+*
+* See the documentation for receive_q1_ptr for more info.
+*/
+   if (q)
+   queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
/* Enable interrupts */
queue_writel(queue, IER,
 MACB_RX_INT_FLAGS |
-- 
2.7.4



[RFC PATCH 1/2] net: macb: Add RBQP to the macb queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Add RX queue pointer to macb queues to make it accessible for the
multiple queues available. Currently the first RX queue is used.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  | 1 +
 drivers/net/ethernet/cadence/macb_main.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index c93f3a2..acb6578 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -968,6 +968,7 @@ struct macb_queue {
unsigned intIMR;
unsigned intTBQP;
unsigned intTBQPH;
+   unsigned intRBQP;
 
unsigned inttx_head, tx_tail;
struct macb_dma_desc*tx_ring;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 72a67f7..623ae9c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2875,6 +2875,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
+   queue->RBQP = GEM_RBQP(hw_q - 1);
} else {
/* queue0 uses legacy registers */
queue->ISR  = MACB_ISR;
@@ -2886,6 +2887,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = MACB_TBQPH;
 #endif
+   queue->RBQP = MACB_RBQP;
}
 
/* get irq: here we use the linux queue index, not the hardware
-- 
2.7.4



[RFC PATCH 1/2] net: macb: Add RBQP to the macb queues

2017-11-26 Thread Harini Katakam
From: "Edgar E. Iglesias" 

Add RX queue pointer to macb queues to make it accessible for the
multiple queues available. Currently the first RX queue is used.

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Harini Katakam 
Signed-off-by: Michal Simek 
---
 drivers/net/ethernet/cadence/macb.h  | 1 +
 drivers/net/ethernet/cadence/macb_main.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index c93f3a2..acb6578 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -968,6 +968,7 @@ struct macb_queue {
unsigned intIMR;
unsigned intTBQP;
unsigned intTBQPH;
+   unsigned intRBQP;
 
unsigned inttx_head, tx_tail;
struct macb_dma_desc*tx_ring;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 72a67f7..623ae9c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2875,6 +2875,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
+   queue->RBQP = GEM_RBQP(hw_q - 1);
} else {
/* queue0 uses legacy registers */
queue->ISR  = MACB_ISR;
@@ -2886,6 +2887,7 @@ static int macb_init(struct platform_device *pdev)
if (bp->hw_dma_cap & HW_DMA_CAP_64B)
queue->TBQPH = MACB_TBQPH;
 #endif
+   queue->RBQP = MACB_RBQP;
}
 
/* get irq: here we use the linux queue index, not the hardware
-- 
2.7.4



Re: [PATCH v4 2/4] tpm: ignore burstcount to improve tpm_tis send() performance

2017-11-26 Thread Leendert van Doorn
Hmm, this is almost 20 years old code (

I think the original code did a burst write and didn't check for error 
conditions until the very last byte write. I seem to remember that there was 
some text in the original standard to that effect (this may have gone back as 
far as IBM's ESS spec).

The current code does check for error conditions after each write byte(s) so I 
don't think there is any reason for this anymore. Changing the while condition 
to count < len and setting burstcnt = min_t(int, burstcnt, len - count) and 
remove the tpm_tis_write8/wait_for_tpm_stat/tpm_tis_status clauses after the 
while loop should be sufficient.

Leendert

On 11/26/17, 8:37 AM, "Mimi Zohar"  wrote:

[Cc'ing Dave and Leendeert]

Hi Jarkko,

> > It seems that the last byte was sent from the beginning (27084ef
> > [PATCH] tpm: driver for next generation TPM chips,), does anyone
> > remember the reason ?
> 
> Sent from the beginning?

I went through the commit logs to see if any of the patch descriptions
have an explanation for sending the last byte separately. Based on
commit 27084efee0c3 "[PATCH] tpm: driver for next generation TPM
chips", it seems it's been there since the beginning.

Dave, Leendert, Do either of you remember the reason for
tpm_tis_send_data() sending the last byte separately?

thanks,

Mimi






Re: [PATCH v4 2/4] tpm: ignore burstcount to improve tpm_tis send() performance

2017-11-26 Thread Leendert van Doorn
Hmm, this is almost 20 years old code (

I think the original code did a burst write and didn't check for error 
conditions until the very last byte write. I seem to remember that there was 
some text in the original standard to that effect (this may have gone back as 
far as IBM's ESS spec).

The current code does check for error conditions after each write byte(s) so I 
don't think there is any reason for this anymore. Changing the while condition 
to count < len and setting burstcnt = min_t(int, burstcnt, len - count) and 
remove the tpm_tis_write8/wait_for_tpm_stat/tpm_tis_status clauses after the 
while loop should be sufficient.

Leendert

On 11/26/17, 8:37 AM, "Mimi Zohar"  wrote:

[Cc'ing Dave and Leendeert]

Hi Jarkko,

> > It seems that the last byte was sent from the beginning (27084ef
> > [PATCH] tpm: driver for next generation TPM chips,), does anyone
> > remember the reason ?
> 
> Sent from the beginning?

I went through the commit logs to see if any of the patch descriptions
have an explanation for sending the last byte separately. Based on
commit 27084efee0c3 "[PATCH] tpm: driver for next generation TPM
chips", it seems it's been there since the beginning.

Dave, Leendert, Do either of you remember the reason for
tpm_tis_send_data() sending the last byte separately?

thanks,

Mimi






[PATCH] i2c: core: decrease reference count of device node in i2c_unregister_device

2017-11-26 Thread Lixin Wang
Reference count of device node was increased in of_i2c_register_device,
but without decreasing it in i2c_unregister_device. Then the dynamically
added device node will never be released.
Fix this by adding the of_node_put.

Signed-off-by: Lixin Wang 
---
 drivers/i2c/i2c-core-base.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 56e4658..b76adf9 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -808,8 +808,10 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
-   if (client->dev.of_node)
+   if (client->dev.of_node) {
of_node_clear_flag(client->dev.of_node, OF_POPULATED);
+   of_node_put(client->dev.of_node);
+   }
if (ACPI_COMPANION(>dev))
acpi_device_clear_enumerated(ACPI_COMPANION(>dev));
device_unregister(>dev);
-- 
2.6.2



[PATCH] i2c: core: decrease reference count of device node in i2c_unregister_device

2017-11-26 Thread Lixin Wang
Reference count of device node was increased in of_i2c_register_device,
but without decreasing it in i2c_unregister_device. Then the dynamically
added device node will never be released.
Fix this by adding the of_node_put.

Signed-off-by: Lixin Wang 
---
 drivers/i2c/i2c-core-base.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 56e4658..b76adf9 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -808,8 +808,10 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
-   if (client->dev.of_node)
+   if (client->dev.of_node) {
of_node_clear_flag(client->dev.of_node, OF_POPULATED);
+   of_node_put(client->dev.of_node);
+   }
if (ACPI_COMPANION(>dev))
acpi_device_clear_enumerated(ACPI_COMPANION(>dev));
device_unregister(>dev);
-- 
2.6.2



Re: [PATCH] mm:Add watermark slope for high mark

2017-11-26 Thread kbuild test robot
Hi Peter,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mmotm/master]
[also build test ERROR on v4.15-rc1 next-20171124]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Peter-Enderborg/mm-Add-watermark-slope-for-high-mark/20171127-140339
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: i386-tinyconfig (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `__setup_per_zone_wmarks':
>> page_alloc.c:(.text+0x9eb): undefined reference to `__umoddi3'
>> page_alloc.c:(.text+0xa06): undefined reference to `__udivdi3'
   page_alloc.c:(.text+0xa1d): undefined reference to `__udivdi3'

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH] mm:Add watermark slope for high mark

2017-11-26 Thread kbuild test robot
Hi Peter,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mmotm/master]
[also build test ERROR on v4.15-rc1 next-20171124]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Peter-Enderborg/mm-Add-watermark-slope-for-high-mark/20171127-140339
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: i386-tinyconfig (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `__setup_per_zone_wmarks':
>> page_alloc.c:(.text+0x9eb): undefined reference to `__umoddi3'
>> page_alloc.c:(.text+0xa06): undefined reference to `__udivdi3'
   page_alloc.c:(.text+0xa1d): undefined reference to `__udivdi3'

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[PATCH v3 02/21] fpga: mgr: add region_id to fpga_image_info

2017-11-26 Thread Wu Hao
This patch adds region_id to fpga_image_info data structure, it
allows driver to pass region id information to fpga-mgr via
fpga_image_info for fpga reconfiguration function.

Signed-off-by: Wu Hao 

v3: add one line comment for region_id
---
 include/linux/fpga/fpga-mgr.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 1ad4822..6e98b66 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -88,6 +88,7 @@ enum fpga_mgr_states {
  * @sgt: scatter/gather table containing FPGA image
  * @buf: contiguous buffer containing FPGA image
  * @count: size of buf
+ * @region_id: id of target region
  * @dev: device that owns this
  * @overlay: Device Tree overlay
  */
@@ -100,6 +101,7 @@ struct fpga_image_info {
struct sg_table *sgt;
const char *buf;
size_t count;
+   int region_id;
struct device *dev;
 #ifdef CONFIG_OF
struct device_node *overlay;
-- 
1.8.3.1



[PATCH v3 01/21] docs: fpga: add a document for Intel FPGA driver overview

2017-11-26 Thread Wu Hao
Add a document for Intel FPGA driver overview.

Signed-off-by: Enno Luebbers 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: added FME fpga-mgr/bridge/region platform driver to driver organization.
updated open discussion per current implementation.
fixed some typos.
v3: use FPGA base region as container device instead of fpga-dev class.
split common enumeration code from pcie driver to functions exposed by
device feature list framework.
update FME performance reporting which supports both integrated (iperf/)
and discrete (dperf/) FPGA solutions.
---
 Documentation/fpga/intel-fpga.txt | 261 ++
 1 file changed, 261 insertions(+)
 create mode 100644 Documentation/fpga/intel-fpga.txt

diff --git a/Documentation/fpga/intel-fpga.txt 
b/Documentation/fpga/intel-fpga.txt
new file mode 100644
index 000..0754733
--- /dev/null
+++ b/Documentation/fpga/intel-fpga.txt
@@ -0,0 +1,261 @@
+===
+Intel FPGA driver Overview
+---
+Enno Luebbers 
+Xiao Guangrong 
+Wu Hao 
+
+The Intel FPGA driver provides interfaces for userspace applications to
+configure, enumerate, open, and access FPGA accelerators on platforms equipped
+with Intel(R) FPGA PCIe based solutions and enables system level management
+functions such as FPGA reconfiguration, power management, and virtualization.
+
+HW Architecture
+===
+From the OS's point of view, the FPGA hardware appears as a regular PCIe 
device.
+The FPGA device memory is organized using a predefined data structure (Device
+Feature List). Features supported by the particular FPGA device are exposed
+through these data structures, as illustrated below:
+
+  +---+  +-+
+  |  PF   |  | VF  |
+  +---+  +-+
+  ^^ ^  ^
+  || |  |
++-||-|--|---+
+| || |  |   |
+|  +-+ +---+ +---+  +---+   |
+|  | FME | | Port0 | | Port1 |  | Port2 |   |
+|  +-+ +---+ +---+  +---+   |
+|  ^ ^  ^   |
+|  | |  |   |
+|  +---+ +--+   +---+   |
+|  |  AFU  | |  AFU |   |  AFU  |   |
+|  +---+ +--+   +---+   |
+|   |
+| FPGA PCIe Device  |
++---+
+
+The driver supports PCIe SR-IOV to create virtual functions (VFs) which can be
+used to assign individual accelerators to virtual machines.
+
+FME (FPGA Management Engine)
+
+The FPGA Management Engine performs power and thermal management, error
+reporting, reconfiguration, performance reporting for integrated and discrete
+solution, and other infrastructure functions. Each FPGA has one FME, which is
+always accessed through the physical function (PF).
+
+User-space applications can acquire exclusive access to the FME using open(),
+and release it using close().
+
+The following functions are exposed through ioctls:
+
+   Get driver API version (FPGA_GET_API_VERSION)
+   Check for extensions (FPGA_CHECK_EXTENSION)
+   Assign port to PF (FPGA_FME_PORT_ASSIGN)
+   Release port from PF (FPGA_FME_PORT_RELEASE)
+   Program bitstream (FPGA_FME_PORT_PR)
+
+More functions are exposed through sysfs
+(/sys/class/fpga_region/regionX/fpga-dfl-fme.n/):
+
+   Read bitstream ID (bitstream_id)
+   Read bitstream metadata (bitstream_metadata)
+   Read number of ports (ports_num)
+   Read socket ID (socket_id)
+   Read performance counters (iperf/ and dperf/)
+   Power management (power_mgmt/)
+   Thermal management (thermal_mgmt/)
+   Error reporting (errors/)
+
+PORT
+
+A port represents the interface between the static FPGA fabric (the "blue
+bitstream") and a partially reconfigurable region containing an AFU (the "green
+bitstream"). It controls the communication from SW to the accelerator and
+exposes features such as reset and debug.
+
+A PCIe device may have several ports and each port can be released from PF by
+FPGA_FME_PORT_RELEASE ioctl on FME, and exposed through a VF via PCIe sriov
+sysfs interface.
+
+AFU
+===
+An AFU is attached to a port and exposes a 256k MMIO region to be used for
+accelerator-specific control registers.
+
+User-space applications 

[PATCH v3 00/21] Intel FPGA Device Drivers

2017-11-26 Thread Wu Hao
Hi All,

Here is v3 patch-series adding drivers for Intel FPGA devices.

The Intel FPGA driver provides interfaces for userspace applications to
configure, enumerate, open, and access FPGA accelerators on platforms
equipped with Intel(R) PCIe based FPGA solutions and enables system
level management functions such as FPGA partial reconfiguration, power
management and virtualization. It also provides a common framework to
support FPGA devices which implement Device Feature List (DFL) and feature
devices under DFL for better code reuse.

This patch series only adds the basic functions for FPGA accelerators and
partial reconfiguration. Patches for more functions, e.g power management
and virtualization, will be submitted after this series gets reviewed.

Patch 1: add a document for Intel FPGA driver overview, including the HW
architecture, driver organization, device enumeration, virtualization and
opens.

Patch 2: add region_id for fpga_image_info data structure, which allows
driver to pass region id information to fpga-mgr for FPGA reconfiguration
function. (Used by Patch 13)

Patch 3: add a 'status' sysfs interface to fpga-mgr class, it reflects
the status of the fpga-mgr including reconfiguration errors. (Used by
Patch 14)

Patch 4-7: add FPGA device feature list support, it provides common
enumeration interfaces which creates container device (FPGA base region)
and all feature devices by walking through all the 'Device Feature Lists'
provided low level drivers.

Patch 8-9: implement Intel FPGA PCIe device driver. It locates all 'Device
Feature Lists' in PCIe device memory and invokes common interfaces from
above device feature list framework to finish the enumeration.

Patch 10-13: implement FPGA Management Engine (FME) driver. It's a
platform driver matching with the FME platform device created by above
device feature list framework during enumeration. Sysfs and device file
ioctls are exposed as user interfaces to allow partial reconfiguration
to Accelerated Function Units (AFUs) from user space applications.

Patch 14-16: implement FPGA manager/bridge/region platform drivers for
Intel FPGA Management Engine (FME). These platform drivers match with
platform devices created by above FME driver, they use the generic
fpga-mgr/bridge/region class infrastructure to implement FPGA partial
reconfiguration function.

Patch 17-21: implement FPGA Accelerated Function Unit (AFU) driver.
It's a platform driver matching with AFU platform device created by above
device feature list framework during enumeration. It provides user
interfaces to expose the AFU MMIO region, map/unmap dma buffer, and
control the port which AFU connects to.

Changes from v2:
- Split common enumeration code from pcie driver to a separated module
  which for device feature list support.
- Drop fpga-dev class and switch to use fpga base region as container.
- Update the intel-fpga.txt documentation for new driver organization.
- Rename feature device drivers for future code reuse.
- Rebase code due to fpga APIs changes
- replace bitfields with marco and shift.
- fix typos, checkpatch issue and other comments.

Changes from v1:

- Use GPLv2 license instead of Dual BSD/GPL.
- Move the code to drivers/fpga folder.
- Update the intel-fpga.txt documentation for new driver organization.
- Add documentation for new sysfs interfaces.
- Switch to use common fpga-region interface for partial reconfiguration
  (PR) function in FME. It creates fpga-region/fpga-mgr/fpga-bridge
  platform devices and leave the implementation to their platform drivers.
- Add platform drivers for FME fpga-mgr/bridge/region platform devices.
- Fix kbuild warnings, typos and other comments.

This patch series depends on the below patchset from Alan Tull.
[PATCH v2 0/5] fpga: don't use drvdata in common fpga code[1]

[1] https://marc.info/?l=linux-fpga=151077942606263=2

Kang Luwei (3):
  fpga: dfl: add FPGA Management Engine driver basic framework
  fpga: dfl: fme: add header sub feature support
  fpga: dfl: fme: add partial reconfiguration sub feature support

Wu Hao (15):
  docs: fpga: add a document for Intel FPGA driver overview
  fpga: mgr: add region_id to fpga_image_info
  fpga: mgr: add status for fpga-manager
  fpga: add device feature list support
  fpga: dfl: add chardev support for feature devices
  fpga: dfl: adds fpga_cdev_find_port
  fpga: intel-dfl-pci: add enumeration for feature devices
  fpga: dfl: fme: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
support
  fpga: dfl: add fpga manager platform driver for FME
  fpga: dfl: add fpga bridge platform driver for FME
  fpga: dfl: add fpga region platform driver for FME
  fpga: dfl: add FPGA Accelerated Function Unit driver basic framework
  fpga: dfl: afu: add header sub feature support
  fpga: dfl: afu: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
support
  fpga: dfl: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support

Xiao Guangrong (2):
  fpga: dfl: add feature device infrastructure
  fpga: dfl: afu: 

[PATCH v3 02/21] fpga: mgr: add region_id to fpga_image_info

2017-11-26 Thread Wu Hao
This patch adds region_id to fpga_image_info data structure, it
allows driver to pass region id information to fpga-mgr via
fpga_image_info for fpga reconfiguration function.

Signed-off-by: Wu Hao 

v3: add one line comment for region_id
---
 include/linux/fpga/fpga-mgr.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 1ad4822..6e98b66 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -88,6 +88,7 @@ enum fpga_mgr_states {
  * @sgt: scatter/gather table containing FPGA image
  * @buf: contiguous buffer containing FPGA image
  * @count: size of buf
+ * @region_id: id of target region
  * @dev: device that owns this
  * @overlay: Device Tree overlay
  */
@@ -100,6 +101,7 @@ struct fpga_image_info {
struct sg_table *sgt;
const char *buf;
size_t count;
+   int region_id;
struct device *dev;
 #ifdef CONFIG_OF
struct device_node *overlay;
-- 
1.8.3.1



[PATCH v3 01/21] docs: fpga: add a document for Intel FPGA driver overview

2017-11-26 Thread Wu Hao
Add a document for Intel FPGA driver overview.

Signed-off-by: Enno Luebbers 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: added FME fpga-mgr/bridge/region platform driver to driver organization.
updated open discussion per current implementation.
fixed some typos.
v3: use FPGA base region as container device instead of fpga-dev class.
split common enumeration code from pcie driver to functions exposed by
device feature list framework.
update FME performance reporting which supports both integrated (iperf/)
and discrete (dperf/) FPGA solutions.
---
 Documentation/fpga/intel-fpga.txt | 261 ++
 1 file changed, 261 insertions(+)
 create mode 100644 Documentation/fpga/intel-fpga.txt

diff --git a/Documentation/fpga/intel-fpga.txt 
b/Documentation/fpga/intel-fpga.txt
new file mode 100644
index 000..0754733
--- /dev/null
+++ b/Documentation/fpga/intel-fpga.txt
@@ -0,0 +1,261 @@
+===
+Intel FPGA driver Overview
+---
+Enno Luebbers 
+Xiao Guangrong 
+Wu Hao 
+
+The Intel FPGA driver provides interfaces for userspace applications to
+configure, enumerate, open, and access FPGA accelerators on platforms equipped
+with Intel(R) FPGA PCIe based solutions and enables system level management
+functions such as FPGA reconfiguration, power management, and virtualization.
+
+HW Architecture
+===
+From the OS's point of view, the FPGA hardware appears as a regular PCIe 
device.
+The FPGA device memory is organized using a predefined data structure (Device
+Feature List). Features supported by the particular FPGA device are exposed
+through these data structures, as illustrated below:
+
+  +---+  +-+
+  |  PF   |  | VF  |
+  +---+  +-+
+  ^^ ^  ^
+  || |  |
++-||-|--|---+
+| || |  |   |
+|  +-+ +---+ +---+  +---+   |
+|  | FME | | Port0 | | Port1 |  | Port2 |   |
+|  +-+ +---+ +---+  +---+   |
+|  ^ ^  ^   |
+|  | |  |   |
+|  +---+ +--+   +---+   |
+|  |  AFU  | |  AFU |   |  AFU  |   |
+|  +---+ +--+   +---+   |
+|   |
+| FPGA PCIe Device  |
++---+
+
+The driver supports PCIe SR-IOV to create virtual functions (VFs) which can be
+used to assign individual accelerators to virtual machines.
+
+FME (FPGA Management Engine)
+
+The FPGA Management Engine performs power and thermal management, error
+reporting, reconfiguration, performance reporting for integrated and discrete
+solution, and other infrastructure functions. Each FPGA has one FME, which is
+always accessed through the physical function (PF).
+
+User-space applications can acquire exclusive access to the FME using open(),
+and release it using close().
+
+The following functions are exposed through ioctls:
+
+   Get driver API version (FPGA_GET_API_VERSION)
+   Check for extensions (FPGA_CHECK_EXTENSION)
+   Assign port to PF (FPGA_FME_PORT_ASSIGN)
+   Release port from PF (FPGA_FME_PORT_RELEASE)
+   Program bitstream (FPGA_FME_PORT_PR)
+
+More functions are exposed through sysfs
+(/sys/class/fpga_region/regionX/fpga-dfl-fme.n/):
+
+   Read bitstream ID (bitstream_id)
+   Read bitstream metadata (bitstream_metadata)
+   Read number of ports (ports_num)
+   Read socket ID (socket_id)
+   Read performance counters (iperf/ and dperf/)
+   Power management (power_mgmt/)
+   Thermal management (thermal_mgmt/)
+   Error reporting (errors/)
+
+PORT
+
+A port represents the interface between the static FPGA fabric (the "blue
+bitstream") and a partially reconfigurable region containing an AFU (the "green
+bitstream"). It controls the communication from SW to the accelerator and
+exposes features such as reset and debug.
+
+A PCIe device may have several ports and each port can be released from PF by
+FPGA_FME_PORT_RELEASE ioctl on FME, and exposed through a VF via PCIe sriov
+sysfs interface.
+
+AFU
+===
+An AFU is attached to a port and exposes a 256k MMIO region to be used for
+accelerator-specific control registers.
+
+User-space applications can acquire exclusive access to an AFU attached to a
+port by using open() on the port device node, and release it using close().
+
+The following 

[PATCH v3 00/21] Intel FPGA Device Drivers

2017-11-26 Thread Wu Hao
Hi All,

Here is v3 patch-series adding drivers for Intel FPGA devices.

The Intel FPGA driver provides interfaces for userspace applications to
configure, enumerate, open, and access FPGA accelerators on platforms
equipped with Intel(R) PCIe based FPGA solutions and enables system
level management functions such as FPGA partial reconfiguration, power
management and virtualization. It also provides a common framework to
support FPGA devices which implement Device Feature List (DFL) and feature
devices under DFL for better code reuse.

This patch series only adds the basic functions for FPGA accelerators and
partial reconfiguration. Patches for more functions, e.g power management
and virtualization, will be submitted after this series gets reviewed.

Patch 1: add a document for Intel FPGA driver overview, including the HW
architecture, driver organization, device enumeration, virtualization and
opens.

Patch 2: add region_id for fpga_image_info data structure, which allows
driver to pass region id information to fpga-mgr for FPGA reconfiguration
function. (Used by Patch 13)

Patch 3: add a 'status' sysfs interface to fpga-mgr class, it reflects
the status of the fpga-mgr including reconfiguration errors. (Used by
Patch 14)

Patch 4-7: add FPGA device feature list support, it provides common
enumeration interfaces which creates container device (FPGA base region)
and all feature devices by walking through all the 'Device Feature Lists'
provided low level drivers.

Patch 8-9: implement Intel FPGA PCIe device driver. It locates all 'Device
Feature Lists' in PCIe device memory and invokes common interfaces from
above device feature list framework to finish the enumeration.

Patch 10-13: implement FPGA Management Engine (FME) driver. It's a
platform driver matching with the FME platform device created by above
device feature list framework during enumeration. Sysfs and device file
ioctls are exposed as user interfaces to allow partial reconfiguration
to Accelerated Function Units (AFUs) from user space applications.

Patch 14-16: implement FPGA manager/bridge/region platform drivers for
Intel FPGA Management Engine (FME). These platform drivers match with
platform devices created by above FME driver, they use the generic
fpga-mgr/bridge/region class infrastructure to implement FPGA partial
reconfiguration function.

Patch 17-21: implement FPGA Accelerated Function Unit (AFU) driver.
It's a platform driver matching with AFU platform device created by above
device feature list framework during enumeration. It provides user
interfaces to expose the AFU MMIO region, map/unmap dma buffer, and
control the port which AFU connects to.

Changes from v2:
- Split common enumeration code from pcie driver to a separated module
  which for device feature list support.
- Drop fpga-dev class and switch to use fpga base region as container.
- Update the intel-fpga.txt documentation for new driver organization.
- Rename feature device drivers for future code reuse.
- Rebase code due to fpga APIs changes
- replace bitfields with marco and shift.
- fix typos, checkpatch issue and other comments.

Changes from v1:

- Use GPLv2 license instead of Dual BSD/GPL.
- Move the code to drivers/fpga folder.
- Update the intel-fpga.txt documentation for new driver organization.
- Add documentation for new sysfs interfaces.
- Switch to use common fpga-region interface for partial reconfiguration
  (PR) function in FME. It creates fpga-region/fpga-mgr/fpga-bridge
  platform devices and leave the implementation to their platform drivers.
- Add platform drivers for FME fpga-mgr/bridge/region platform devices.
- Fix kbuild warnings, typos and other comments.

This patch series depends on the below patchset from Alan Tull.
[PATCH v2 0/5] fpga: don't use drvdata in common fpga code[1]

[1] https://marc.info/?l=linux-fpga=151077942606263=2

Kang Luwei (3):
  fpga: dfl: add FPGA Management Engine driver basic framework
  fpga: dfl: fme: add header sub feature support
  fpga: dfl: fme: add partial reconfiguration sub feature support

Wu Hao (15):
  docs: fpga: add a document for Intel FPGA driver overview
  fpga: mgr: add region_id to fpga_image_info
  fpga: mgr: add status for fpga-manager
  fpga: add device feature list support
  fpga: dfl: add chardev support for feature devices
  fpga: dfl: adds fpga_cdev_find_port
  fpga: intel-dfl-pci: add enumeration for feature devices
  fpga: dfl: fme: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
support
  fpga: dfl: add fpga manager platform driver for FME
  fpga: dfl: add fpga bridge platform driver for FME
  fpga: dfl: add fpga region platform driver for FME
  fpga: dfl: add FPGA Accelerated Function Unit driver basic framework
  fpga: dfl: afu: add header sub feature support
  fpga: dfl: afu: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
support
  fpga: dfl: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support

Xiao Guangrong (2):
  fpga: dfl: add feature device infrastructure
  fpga: dfl: afu: 

Re: [PATCH v2] checkpatch: Add a warning for log messages that don't end in a new line

2017-11-26 Thread Julia Lawall


On Sun, 26 Nov 2017, Logan Gunthorpe wrote:

>
>
> On 26/11/17 11:42 PM, Julia Lawall wrote:
> > Although I guess that in that case the whole exercise is pointless?
> > Because every print will at runtime be followed by another print, which
> > will add either the newline or a continuation.
>
> Yes, in practice the '\n' at the end of every log line is optional based
> on what the code actually does. Nothing bad happens if you omit one. But
> reviewers still point out that they are required. (That's what started
> me on this mess -- because I'd rather know what the correct thing is
> before I commit the code for the first time, and not months after the
> code reached mainline.)
>
> The reviewers have a really good point though: if a significant fraction
> of the log calls have no new line and a majority have them, then making
> any kind of change in this area could break things. Not to mention the
> ugliness of the inconsistencies everywhere. Also, the more cases that
> are "wrong" that get into the kernel the more it confuses people trying
> to learn what the "right" thing is.

The problem is probably mostly for the non-standard functions, where a lot
of function/macro unfolding is often required to see what is really going
on.

julia


>
> Honestly, though, I have no dog in this race. I just thought it would be
> useful.
>
> Logan
>
> --
> To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


Re: [PATCH v2] checkpatch: Add a warning for log messages that don't end in a new line

2017-11-26 Thread Julia Lawall


On Sun, 26 Nov 2017, Logan Gunthorpe wrote:

>
>
> On 26/11/17 11:42 PM, Julia Lawall wrote:
> > Although I guess that in that case the whole exercise is pointless?
> > Because every print will at runtime be followed by another print, which
> > will add either the newline or a continuation.
>
> Yes, in practice the '\n' at the end of every log line is optional based
> on what the code actually does. Nothing bad happens if you omit one. But
> reviewers still point out that they are required. (That's what started
> me on this mess -- because I'd rather know what the correct thing is
> before I commit the code for the first time, and not months after the
> code reached mainline.)
>
> The reviewers have a really good point though: if a significant fraction
> of the log calls have no new line and a majority have them, then making
> any kind of change in this area could break things. Not to mention the
> ugliness of the inconsistencies everywhere. Also, the more cases that
> are "wrong" that get into the kernel the more it confuses people trying
> to learn what the "right" thing is.

The problem is probably mostly for the non-standard functions, where a lot
of function/macro unfolding is often required to see what is really going
on.

julia


>
> Honestly, though, I have no dog in this race. I just thought it would be
> useful.
>
> Logan
>
> --
> To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


[PATCH v3 04/21] fpga: add device feature list support

2017-11-26 Thread Wu Hao
Device Feature List (DFL) defines a feature list structure that creates
a link list of feature headers within the MMIO space to provide an
extensible way of adding features. This patch introduces a kernel module
to provide basic infrastructure to support FPGA devices which implement
the Device Feature List.

Usually there will be different features and their sub features linked into
the DFL. This code provides common APIs for feature enumeration, it creates
a container device (FPGA base region), walks through the DFLs and creates
platform devices for feature devices (Currently it only supports two
different feature devices, FPGA Management Engine (FME) and Port which
the Accelerator Function Unit (AFU) connected to). In order to enumerate
the DFLs, the common APIs required low level driver to provide necessary
enumeration information (e.g address for each device feature list for
given device) and fill it to the fpga_enum_info data structure. Please
refer to below description for APIs added for enumeration.

Functions for enumeration information preparation:
 *fpga_enum_info_alloc
   allocate enumeration information data structure.

 *fpga_enum_info_add_dfl
   add a device feature list to fpga_enum_info data structure.

 *fpga_enum_info_free
   free fpga_enum_info data structure and related resources.

Functions for feature device enumeration:
 *fpga_enumerate_feature_devs
   enumerate feature devices and return container device.

 *fpga_remove_feature_devs
   remove feature devices under given container device.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: split from another patch.
separate dfl enumeration code from original pcie driver.
provide common data structures and APIs for enumeration.
update device feature list parsing process according to latest hw.
add dperf/iperf/hssi sub feature placeholder according to latest hw.
remove build_info_add_sub_feature and other small functions.
replace *_feature_num function with macro.
remove writeq/readq.
---
 drivers/fpga/Kconfig|  16 +
 drivers/fpga/Makefile   |   3 +
 drivers/fpga/fpga-dfl.c | 884 
 drivers/fpga/fpga-dfl.h | 365 
 4 files changed, 1268 insertions(+)
 create mode 100644 drivers/fpga/fpga-dfl.c
 create mode 100644 drivers/fpga/fpga-dfl.h

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index f47ef84..01ad31f 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -124,4 +124,20 @@ config OF_FPGA_REGION
  Support for loading FPGA images by applying a Device Tree
  overlay.
 
+config FPGA_DFL
+   tristate "FPGA Device Feature List (DFL) support"
+   select FPGA_BRIDGE
+   select FPGA_REGION
+   help
+ Device Feature List (DFL) defines a feature list structure that
+ creates a link list of feature headers within the MMIO space
+ to provide an extensible way of adding features for FPGA.
+ Driver can walk through the feature headers to enumerate feature
+ devices (e.g FPGA Management Engine, Port and Accelerator
+ Function Unit) and their private features for target FPGA devices.
+
+ Select this option to enable common support for Field-Programmable
+ Gate Array (FPGA) solutions which implement Device Feature List.
+ It provides enumeration APIs, and feature device infrastructure.
+
 endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 3cb276a..447ba2b 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -27,3 +27,6 @@ obj-$(CONFIG_XILINX_PR_DECOUPLER) += xilinx-pr-decoupler.o
 # High Level Interfaces
 obj-$(CONFIG_FPGA_REGION)  += fpga-region.o
 obj-$(CONFIG_OF_FPGA_REGION)   += of-fpga-region.o
+
+# FPGA Device Feature List Support
+obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
new file mode 100644
index 000..6609828
--- /dev/null
+++ b/drivers/fpga/fpga-dfl.c
@@ -0,0 +1,884 @@
+/*
+ * Driver for FPGA Device Feature List (DFL) Support
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Zhang Yi 
+ *   Wu Hao 
+ *   Xiao Guangrong 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+#include 
+
+#include "fpga-dfl.h"
+
+static DEFINE_MUTEX(fpga_id_mutex);
+
+enum fpga_id_type {
+   FME_ID, /* fme id allocation and mapping */
+   PORT_ID,/* port id 

[PATCH v3 04/21] fpga: add device feature list support

2017-11-26 Thread Wu Hao
Device Feature List (DFL) defines a feature list structure that creates
a link list of feature headers within the MMIO space to provide an
extensible way of adding features. This patch introduces a kernel module
to provide basic infrastructure to support FPGA devices which implement
the Device Feature List.

Usually there will be different features and their sub features linked into
the DFL. This code provides common APIs for feature enumeration, it creates
a container device (FPGA base region), walks through the DFLs and creates
platform devices for feature devices (Currently it only supports two
different feature devices, FPGA Management Engine (FME) and Port which
the Accelerator Function Unit (AFU) connected to). In order to enumerate
the DFLs, the common APIs required low level driver to provide necessary
enumeration information (e.g address for each device feature list for
given device) and fill it to the fpga_enum_info data structure. Please
refer to below description for APIs added for enumeration.

Functions for enumeration information preparation:
 *fpga_enum_info_alloc
   allocate enumeration information data structure.

 *fpga_enum_info_add_dfl
   add a device feature list to fpga_enum_info data structure.

 *fpga_enum_info_free
   free fpga_enum_info data structure and related resources.

Functions for feature device enumeration:
 *fpga_enumerate_feature_devs
   enumerate feature devices and return container device.

 *fpga_remove_feature_devs
   remove feature devices under given container device.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: split from another patch.
separate dfl enumeration code from original pcie driver.
provide common data structures and APIs for enumeration.
update device feature list parsing process according to latest hw.
add dperf/iperf/hssi sub feature placeholder according to latest hw.
remove build_info_add_sub_feature and other small functions.
replace *_feature_num function with macro.
remove writeq/readq.
---
 drivers/fpga/Kconfig|  16 +
 drivers/fpga/Makefile   |   3 +
 drivers/fpga/fpga-dfl.c | 884 
 drivers/fpga/fpga-dfl.h | 365 
 4 files changed, 1268 insertions(+)
 create mode 100644 drivers/fpga/fpga-dfl.c
 create mode 100644 drivers/fpga/fpga-dfl.h

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index f47ef84..01ad31f 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -124,4 +124,20 @@ config OF_FPGA_REGION
  Support for loading FPGA images by applying a Device Tree
  overlay.
 
+config FPGA_DFL
+   tristate "FPGA Device Feature List (DFL) support"
+   select FPGA_BRIDGE
+   select FPGA_REGION
+   help
+ Device Feature List (DFL) defines a feature list structure that
+ creates a link list of feature headers within the MMIO space
+ to provide an extensible way of adding features for FPGA.
+ Driver can walk through the feature headers to enumerate feature
+ devices (e.g FPGA Management Engine, Port and Accelerator
+ Function Unit) and their private features for target FPGA devices.
+
+ Select this option to enable common support for Field-Programmable
+ Gate Array (FPGA) solutions which implement Device Feature List.
+ It provides enumeration APIs, and feature device infrastructure.
+
 endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 3cb276a..447ba2b 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -27,3 +27,6 @@ obj-$(CONFIG_XILINX_PR_DECOUPLER) += xilinx-pr-decoupler.o
 # High Level Interfaces
 obj-$(CONFIG_FPGA_REGION)  += fpga-region.o
 obj-$(CONFIG_OF_FPGA_REGION)   += of-fpga-region.o
+
+# FPGA Device Feature List Support
+obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
new file mode 100644
index 000..6609828
--- /dev/null
+++ b/drivers/fpga/fpga-dfl.c
@@ -0,0 +1,884 @@
+/*
+ * Driver for FPGA Device Feature List (DFL) Support
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Zhang Yi 
+ *   Wu Hao 
+ *   Xiao Guangrong 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+#include 
+
+#include "fpga-dfl.h"
+
+static DEFINE_MUTEX(fpga_id_mutex);
+
+enum fpga_id_type {
+   FME_ID, /* fme id allocation and mapping */
+   PORT_ID,/* port id allocation and mapping */
+   FPGA_ID_MAX,
+};
+
+/* it is protected by fpga_id_mutex */
+static struct idr fpga_ids[FPGA_ID_MAX];
+
+static void fpga_ids_init(void)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(fpga_ids); i++)
+   

[PATCH v3 06/21] fpga: dfl: adds fpga_cdev_find_port

2017-11-26 Thread Wu Hao
For feature devices, e.g FPGA Management Engine (FME), it may
require fpga_cdev_find_port function to find dedicate port for
further actions, so export this function from feature device
driver module.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: s/fpga_for_each_port/fpga_cdev_find_port/
move fpga_cdev_find_port to fpga-dfl module.
---
 drivers/fpga/fpga-dfl.c | 27 +++
 drivers/fpga/fpga-dfl.h | 16 
 2 files changed, 43 insertions(+)

diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
index 9294c0a..ce03b17 100644
--- a/drivers/fpga/fpga-dfl.c
+++ b/drivers/fpga/fpga-dfl.c
@@ -873,6 +873,33 @@ void fpga_remove_feature_devs(struct fpga_cdev *cdev)
 }
 EXPORT_SYMBOL_GPL(fpga_remove_feature_devs);
 
+/**
+ * __fpga_cdev_find_port - find a port under given container device
+ * @cdev: container device
+ * @data: data passed to match function
+ * @match: match function used to find specific port from the port device list
+ *
+ * Find a port device under container device. This function needs to be
+ * invoked with lock held.
+ */
+struct platform_device *
+__fpga_cdev_find_port(struct fpga_cdev *cdev, void *data,
+ int (*match)(struct platform_device *, void *))
+{
+   struct feature_platform_data *pdata;
+   struct platform_device *port_dev;
+
+   list_for_each_entry(pdata, >port_dev_list, node) {
+   port_dev = pdata->dev;
+
+   if (match(port_dev, data) && get_device(_dev->dev))
+   return port_dev;
+   }
+
+   return NULL;
+}
+EXPORT_SYMBOL_GPL(__fpga_cdev_find_port);
+
 int fpga_port_id(struct platform_device *pdev)
 {
void __iomem *base;
diff --git a/drivers/fpga/fpga-dfl.h b/drivers/fpga/fpga-dfl.h
index e569a13..36e2394 100644
--- a/drivers/fpga/fpga-dfl.h
+++ b/drivers/fpga/fpga-dfl.h
@@ -375,4 +375,20 @@ struct fpga_cdev {
 struct fpga_cdev *fpga_enumerate_feature_devs(struct fpga_enum_info *info);
 void fpga_remove_feature_devs(struct fpga_cdev *cdev);
 
+struct platform_device *
+__fpga_cdev_find_port(struct fpga_cdev *cdev, void *data,
+ int (*match)(struct platform_device *, void *));
+
+static inline struct platform_device *
+fpga_cdev_find_port(struct fpga_cdev *cdev, void *data,
+   int (*match)(struct platform_device *, void *))
+{
+   struct platform_device *pdev;
+
+   mutex_lock(>lock);
+   pdev = __fpga_cdev_find_port(cdev, data, match);
+   mutex_unlock(>lock);
+
+   return pdev;
+}
 #endif /* __DFL_FPGA_H */
-- 
1.8.3.1



[PATCH v3 07/21] fpga: dfl: add feature device infrastructure

2017-11-26 Thread Wu Hao
From: Xiao Guangrong 

This patch abstracts the common operations of the sub features, and defines
the feature_ops data structure, including init, uinit and ioctl function
pointers. And this patch adds some common helper functions for FME and AFU
drivers, e.g feature_dev_use_begin/end which are used to ensure exclusive
usage of the feature device file.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: rebased
v3: use const for feature_ops.
replace pci related function.
---
 drivers/fpga/fpga-dfl.c | 68 +
 drivers/fpga/fpga-dfl.h | 80 +
 2 files changed, 148 insertions(+)

diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
index ce03b17..1714803 100644
--- a/drivers/fpga/fpga-dfl.c
+++ b/drivers/fpga/fpga-dfl.c
@@ -76,6 +76,74 @@ static enum fpga_id_type feature_dev_id_type(struct 
platform_device *pdev)
return FPGA_ID_MAX;
 }
 
+int fme_feature_to_resource_index(int feature_id)
+{
+   WARN_ON(feature_id >= FME_FEATURE_ID_MAX);
+   return feature_id;
+}
+
+void fpga_dev_feature_uinit(struct platform_device *pdev)
+{
+   struct feature *feature;
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+
+   fpga_dev_for_each_feature(pdata, feature)
+   if (feature->ops) {
+   feature->ops->uinit(pdev, feature);
+   feature->ops = NULL;
+   }
+}
+EXPORT_SYMBOL_GPL(fpga_dev_feature_uinit);
+
+static int
+feature_instance_init(struct platform_device *pdev,
+ struct feature_platform_data *pdata,
+ struct feature *feature, struct feature_driver *drv)
+{
+   int ret;
+
+   WARN_ON(!feature->ioaddr);
+
+   ret = drv->ops->init(pdev, feature);
+   if (ret)
+   return ret;
+
+   feature->ops = drv->ops;
+
+   return ret;
+}
+
+int fpga_dev_feature_init(struct platform_device *pdev,
+ struct feature_driver *feature_drvs)
+{
+   struct feature *feature;
+   struct feature_driver *drv = feature_drvs;
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+   int ret;
+
+   while (drv->ops) {
+   fpga_dev_for_each_feature(pdata, feature) {
+   /* skip the feature which is not initialized. */
+   if (!feature->name)
+   continue;
+
+   if (!strcmp(drv->name, feature->name)) {
+   ret = feature_instance_init(pdev, pdata,
+   feature, drv);
+   if (ret)
+   goto exit;
+   }
+   }
+   drv++;
+   }
+
+   return 0;
+exit:
+   fpga_dev_feature_uinit(pdev);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_dev_feature_init);
+
 struct fpga_chardev_info {
const char *name;
dev_t devt;
diff --git a/drivers/fpga/fpga-dfl.h b/drivers/fpga/fpga-dfl.h
index 36e2394..e5a1094 100644
--- a/drivers/fpga/fpga-dfl.h
+++ b/drivers/fpga/fpga-dfl.h
@@ -176,12 +176,20 @@
 #define PORT_UAFU_DFH  DFH
 #define PORT_UAFU_SIZE DFH_SIZE
 
+struct feature_driver {
+   const char *name;
+   const struct feature_ops *ops;
+};
+
 struct feature {
const char *name;
int resource_index;
void __iomem *ioaddr;
+   const struct feature_ops *ops;
 };
 
+#define DEV_STATUS_IN_USE  0
+
 struct feature_platform_data {
/* list the feature dev to cci_drvdata->port_dev_list. */
struct list_head node;
@@ -189,11 +197,46 @@ struct feature_platform_data {
struct cdev cdev;
struct platform_device *dev;
unsigned int disable_count; /* count for port disable */
+   unsigned long dev_status;
+
+   void *private;  /* ptr to feature dev private data */
 
int num;/* number of features */
struct feature features[0];
 };
 
+static inline int feature_dev_use_begin(struct feature_platform_data *pdata)
+{
+   /* Test and set IN_USE flags to ensure file is exclusively used */
+   if (test_and_set_bit_lock(DEV_STATUS_IN_USE, >dev_status))
+   return -EBUSY;
+
+   return 0;
+}
+
+static inline void feature_dev_use_end(struct feature_platform_data *pdata)
+{
+   clear_bit_unlock(DEV_STATUS_IN_USE, >dev_status);
+}
+
+static inline void

[PATCH v3 06/21] fpga: dfl: adds fpga_cdev_find_port

2017-11-26 Thread Wu Hao
For feature devices, e.g FPGA Management Engine (FME), it may
require fpga_cdev_find_port function to find dedicate port for
further actions, so export this function from feature device
driver module.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: s/fpga_for_each_port/fpga_cdev_find_port/
move fpga_cdev_find_port to fpga-dfl module.
---
 drivers/fpga/fpga-dfl.c | 27 +++
 drivers/fpga/fpga-dfl.h | 16 
 2 files changed, 43 insertions(+)

diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
index 9294c0a..ce03b17 100644
--- a/drivers/fpga/fpga-dfl.c
+++ b/drivers/fpga/fpga-dfl.c
@@ -873,6 +873,33 @@ void fpga_remove_feature_devs(struct fpga_cdev *cdev)
 }
 EXPORT_SYMBOL_GPL(fpga_remove_feature_devs);
 
+/**
+ * __fpga_cdev_find_port - find a port under given container device
+ * @cdev: container device
+ * @data: data passed to match function
+ * @match: match function used to find specific port from the port device list
+ *
+ * Find a port device under container device. This function needs to be
+ * invoked with lock held.
+ */
+struct platform_device *
+__fpga_cdev_find_port(struct fpga_cdev *cdev, void *data,
+ int (*match)(struct platform_device *, void *))
+{
+   struct feature_platform_data *pdata;
+   struct platform_device *port_dev;
+
+   list_for_each_entry(pdata, >port_dev_list, node) {
+   port_dev = pdata->dev;
+
+   if (match(port_dev, data) && get_device(_dev->dev))
+   return port_dev;
+   }
+
+   return NULL;
+}
+EXPORT_SYMBOL_GPL(__fpga_cdev_find_port);
+
 int fpga_port_id(struct platform_device *pdev)
 {
void __iomem *base;
diff --git a/drivers/fpga/fpga-dfl.h b/drivers/fpga/fpga-dfl.h
index e569a13..36e2394 100644
--- a/drivers/fpga/fpga-dfl.h
+++ b/drivers/fpga/fpga-dfl.h
@@ -375,4 +375,20 @@ struct fpga_cdev {
 struct fpga_cdev *fpga_enumerate_feature_devs(struct fpga_enum_info *info);
 void fpga_remove_feature_devs(struct fpga_cdev *cdev);
 
+struct platform_device *
+__fpga_cdev_find_port(struct fpga_cdev *cdev, void *data,
+ int (*match)(struct platform_device *, void *));
+
+static inline struct platform_device *
+fpga_cdev_find_port(struct fpga_cdev *cdev, void *data,
+   int (*match)(struct platform_device *, void *))
+{
+   struct platform_device *pdev;
+
+   mutex_lock(>lock);
+   pdev = __fpga_cdev_find_port(cdev, data, match);
+   mutex_unlock(>lock);
+
+   return pdev;
+}
 #endif /* __DFL_FPGA_H */
-- 
1.8.3.1



[PATCH v3 07/21] fpga: dfl: add feature device infrastructure

2017-11-26 Thread Wu Hao
From: Xiao Guangrong 

This patch abstracts the common operations of the sub features, and defines
the feature_ops data structure, including init, uinit and ioctl function
pointers. And this patch adds some common helper functions for FME and AFU
drivers, e.g feature_dev_use_begin/end which are used to ensure exclusive
usage of the feature device file.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: rebased
v3: use const for feature_ops.
replace pci related function.
---
 drivers/fpga/fpga-dfl.c | 68 +
 drivers/fpga/fpga-dfl.h | 80 +
 2 files changed, 148 insertions(+)

diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
index ce03b17..1714803 100644
--- a/drivers/fpga/fpga-dfl.c
+++ b/drivers/fpga/fpga-dfl.c
@@ -76,6 +76,74 @@ static enum fpga_id_type feature_dev_id_type(struct 
platform_device *pdev)
return FPGA_ID_MAX;
 }
 
+int fme_feature_to_resource_index(int feature_id)
+{
+   WARN_ON(feature_id >= FME_FEATURE_ID_MAX);
+   return feature_id;
+}
+
+void fpga_dev_feature_uinit(struct platform_device *pdev)
+{
+   struct feature *feature;
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+
+   fpga_dev_for_each_feature(pdata, feature)
+   if (feature->ops) {
+   feature->ops->uinit(pdev, feature);
+   feature->ops = NULL;
+   }
+}
+EXPORT_SYMBOL_GPL(fpga_dev_feature_uinit);
+
+static int
+feature_instance_init(struct platform_device *pdev,
+ struct feature_platform_data *pdata,
+ struct feature *feature, struct feature_driver *drv)
+{
+   int ret;
+
+   WARN_ON(!feature->ioaddr);
+
+   ret = drv->ops->init(pdev, feature);
+   if (ret)
+   return ret;
+
+   feature->ops = drv->ops;
+
+   return ret;
+}
+
+int fpga_dev_feature_init(struct platform_device *pdev,
+ struct feature_driver *feature_drvs)
+{
+   struct feature *feature;
+   struct feature_driver *drv = feature_drvs;
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+   int ret;
+
+   while (drv->ops) {
+   fpga_dev_for_each_feature(pdata, feature) {
+   /* skip the feature which is not initialized. */
+   if (!feature->name)
+   continue;
+
+   if (!strcmp(drv->name, feature->name)) {
+   ret = feature_instance_init(pdev, pdata,
+   feature, drv);
+   if (ret)
+   goto exit;
+   }
+   }
+   drv++;
+   }
+
+   return 0;
+exit:
+   fpga_dev_feature_uinit(pdev);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_dev_feature_init);
+
 struct fpga_chardev_info {
const char *name;
dev_t devt;
diff --git a/drivers/fpga/fpga-dfl.h b/drivers/fpga/fpga-dfl.h
index 36e2394..e5a1094 100644
--- a/drivers/fpga/fpga-dfl.h
+++ b/drivers/fpga/fpga-dfl.h
@@ -176,12 +176,20 @@
 #define PORT_UAFU_DFH  DFH
 #define PORT_UAFU_SIZE DFH_SIZE
 
+struct feature_driver {
+   const char *name;
+   const struct feature_ops *ops;
+};
+
 struct feature {
const char *name;
int resource_index;
void __iomem *ioaddr;
+   const struct feature_ops *ops;
 };
 
+#define DEV_STATUS_IN_USE  0
+
 struct feature_platform_data {
/* list the feature dev to cci_drvdata->port_dev_list. */
struct list_head node;
@@ -189,11 +197,46 @@ struct feature_platform_data {
struct cdev cdev;
struct platform_device *dev;
unsigned int disable_count; /* count for port disable */
+   unsigned long dev_status;
+
+   void *private;  /* ptr to feature dev private data */
 
int num;/* number of features */
struct feature features[0];
 };
 
+static inline int feature_dev_use_begin(struct feature_platform_data *pdata)
+{
+   /* Test and set IN_USE flags to ensure file is exclusively used */
+   if (test_and_set_bit_lock(DEV_STATUS_IN_USE, >dev_status))
+   return -EBUSY;
+
+   return 0;
+}
+
+static inline void feature_dev_use_end(struct feature_platform_data *pdata)
+{
+   clear_bit_unlock(DEV_STATUS_IN_USE, >dev_status);
+}
+
+static inline void
+fpga_pdata_set_private(struct feature_platform_data *pdata, void *private)
+{
+   pdata->private = private;
+}
+
+static inline void *fpga_pdata_get_private(struct feature_platform_data *pdata)
+{
+   return pdata->private;
+}
+

[PATCH v3 10/21] fpga: dfl: add FPGA Management Engine driver basic framework

2017-11-26 Thread Wu Hao
From: Kang Luwei 

The FPGA Management Engine (FME) provides power, thermal management,
performance counters, partial reconfiguration and other functions. For each
function, it is packaged into a private feature linked to the FME feature
device in the 'Device Feature List'. It's a platform device created by
DFL framework.

This patch adds the basic framework of FME platform driver. It defines
sub feature drivers to handle the different sub features, including init,
uinit and ioctl. It also registers the file operations for the device file.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: rename driver from intel-fpga-fme to dfl-fme
rename Kconfig from INTEL_FPGA_FME to FPGA_DFL_FME
---
 drivers/fpga/Kconfig|  10 +++
 drivers/fpga/Makefile   |   3 +
 drivers/fpga/dfl-fme-main.c | 160 
 3 files changed, 173 insertions(+)
 create mode 100644 drivers/fpga/dfl-fme-main.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index cc35d12..57da904 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -140,6 +140,16 @@ config FPGA_DFL
  Gate Array (FPGA) solutions which implement Device Feature List.
  It provides enumeration APIs, and feature device infrastructure.
 
+config FPGA_DFL_FME
+   tristate "FPGA DFL FME Driver"
+   depends on FPGA_DFL
+   help
+ The FPGA Management Engine (FME) is a feature device implemented
+ under Device Feature List (DFL) framework. Select this option to
+ enable the platform device driver for FME which implements all
+ FPGA platform level management features. There shall be 1 FME
+ per DFL based FPGA device.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index d39a431..e5ba158 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -30,6 +30,9 @@ obj-$(CONFIG_OF_FPGA_REGION)  += of-fpga-region.o
 
 # FPGA Device Feature List Support
 obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
+obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
+
+fpga-dfl-fme-objs := dfl-fme-main.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_INTEL_FPGA_DFL_PCI)   += intel-dfl-pci.o
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
new file mode 100644
index 000..f7b5f7d
--- /dev/null
+++ b/drivers/fpga/dfl-fme-main.c
@@ -0,0 +1,160 @@
+/*
+ * Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Xiao Guangrong 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "fpga-dfl.h"
+
+static int fme_hdr_init(struct platform_device *pdev, struct feature *feature)
+{
+   dev_dbg(>dev, "FME HDR Init.\n");
+
+   return 0;
+}
+
+static void fme_hdr_uinit(struct platform_device *pdev, struct feature 
*feature)
+{
+   dev_dbg(>dev, "FME HDR UInit.\n");
+}
+
+static const struct feature_ops fme_hdr_ops = {
+   .init = fme_hdr_init,
+   .uinit = fme_hdr_uinit,
+};
+
+static struct feature_driver fme_feature_drvs[] = {
+   {
+   .name = FME_FEATURE_HEADER,
+   .ops = _hdr_ops,
+   },
+   {
+   .ops = NULL,
+   },
+};
+
+static int fme_open(struct inode *inode, struct file *filp)
+{
+   struct platform_device *fdev = fpga_inode_to_feature_dev(inode);
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+   int ret;
+
+   if (WARN_ON(!pdata))
+   return -ENODEV;
+
+   ret = feature_dev_use_begin(pdata);
+   if (ret)
+   return ret;
+
+   dev_dbg(>dev, "Device File Open\n");
+   filp->private_data = pdata;
+
+   return 0;
+}
+
+static int fme_release(struct inode *inode, struct file *filp)
+{
+   struct feature_platform_data *pdata = filp->private_data;
+   struct platform_device *pdev = pdata->dev;
+
+   dev_dbg(>dev, "Device File Release\n");
+   feature_dev_use_end(pdata);
+
+   return 0;
+}
+
+static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+   struct feature_platform_data *pdata = 

[PATCH v3 10/21] fpga: dfl: add FPGA Management Engine driver basic framework

2017-11-26 Thread Wu Hao
From: Kang Luwei 

The FPGA Management Engine (FME) provides power, thermal management,
performance counters, partial reconfiguration and other functions. For each
function, it is packaged into a private feature linked to the FME feature
device in the 'Device Feature List'. It's a platform device created by
DFL framework.

This patch adds the basic framework of FME platform driver. It defines
sub feature drivers to handle the different sub features, including init,
uinit and ioctl. It also registers the file operations for the device file.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: rename driver from intel-fpga-fme to dfl-fme
rename Kconfig from INTEL_FPGA_FME to FPGA_DFL_FME
---
 drivers/fpga/Kconfig|  10 +++
 drivers/fpga/Makefile   |   3 +
 drivers/fpga/dfl-fme-main.c | 160 
 3 files changed, 173 insertions(+)
 create mode 100644 drivers/fpga/dfl-fme-main.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index cc35d12..57da904 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -140,6 +140,16 @@ config FPGA_DFL
  Gate Array (FPGA) solutions which implement Device Feature List.
  It provides enumeration APIs, and feature device infrastructure.
 
+config FPGA_DFL_FME
+   tristate "FPGA DFL FME Driver"
+   depends on FPGA_DFL
+   help
+ The FPGA Management Engine (FME) is a feature device implemented
+ under Device Feature List (DFL) framework. Select this option to
+ enable the platform device driver for FME which implements all
+ FPGA platform level management features. There shall be 1 FME
+ per DFL based FPGA device.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index d39a431..e5ba158 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -30,6 +30,9 @@ obj-$(CONFIG_OF_FPGA_REGION)  += of-fpga-region.o
 
 # FPGA Device Feature List Support
 obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
+obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
+
+fpga-dfl-fme-objs := dfl-fme-main.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_INTEL_FPGA_DFL_PCI)   += intel-dfl-pci.o
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
new file mode 100644
index 000..f7b5f7d
--- /dev/null
+++ b/drivers/fpga/dfl-fme-main.c
@@ -0,0 +1,160 @@
+/*
+ * Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Xiao Guangrong 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "fpga-dfl.h"
+
+static int fme_hdr_init(struct platform_device *pdev, struct feature *feature)
+{
+   dev_dbg(>dev, "FME HDR Init.\n");
+
+   return 0;
+}
+
+static void fme_hdr_uinit(struct platform_device *pdev, struct feature 
*feature)
+{
+   dev_dbg(>dev, "FME HDR UInit.\n");
+}
+
+static const struct feature_ops fme_hdr_ops = {
+   .init = fme_hdr_init,
+   .uinit = fme_hdr_uinit,
+};
+
+static struct feature_driver fme_feature_drvs[] = {
+   {
+   .name = FME_FEATURE_HEADER,
+   .ops = _hdr_ops,
+   },
+   {
+   .ops = NULL,
+   },
+};
+
+static int fme_open(struct inode *inode, struct file *filp)
+{
+   struct platform_device *fdev = fpga_inode_to_feature_dev(inode);
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+   int ret;
+
+   if (WARN_ON(!pdata))
+   return -ENODEV;
+
+   ret = feature_dev_use_begin(pdata);
+   if (ret)
+   return ret;
+
+   dev_dbg(>dev, "Device File Open\n");
+   filp->private_data = pdata;
+
+   return 0;
+}
+
+static int fme_release(struct inode *inode, struct file *filp)
+{
+   struct feature_platform_data *pdata = filp->private_data;
+   struct platform_device *pdev = pdata->dev;
+
+   dev_dbg(>dev, "Device File Release\n");
+   feature_dev_use_end(pdata);
+
+   return 0;
+}
+
+static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+   struct feature_platform_data *pdata = filp->private_data;
+   struct platform_device *pdev = pdata->dev;
+   struct feature *f;
+   long ret;
+
+   dev_dbg(>dev, "%s cmd 0x%x\n", __func__, cmd);
+
+   switch (cmd) {
+   default:
+   /*
+* Let sub-feature's ioctl function to handle the cmd
+* Sub-feature's ioctl returns -ENODEV when cmd is not
+ 

[PATCH] f2fs: avoid false positive of free secs check

2017-11-26 Thread Yunlong Song
Sometimes f2fs_gc is called with no target victim (e.g. xfstest
generic/027, ndirty_node:545 ndiry_dent:1 ndirty_imeta:513 rsvd_segs:21
free_segs:27, has_not_enough_free_secs will return true). This patch
first merges pages and then converts into sections.

Signed-off-by: Yunlong Song 
---
 fs/f2fs/f2fs.h|  9 -
 fs/f2fs/segment.c | 12 +++-
 fs/f2fs/segment.h | 13 +
 3 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ca6b0c9..e89cff7 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1675,15 +1675,6 @@ static inline int get_dirty_pages(struct inode *inode)
return atomic_read(_I(inode)->dirty_pages);
 }
 
-static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
-{
-   unsigned int pages_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
-   unsigned int segs = (get_pages(sbi, block_type) + pages_per_sec - 1) >>
-   sbi->log_blocks_per_seg;
-
-   return segs / sbi->segs_per_sec;
-}
-
 static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
 {
return sbi->total_valid_block_count;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c117e09..603f805 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -171,17 +171,19 @@ static unsigned long __find_rev_next_zero_bit(const 
unsigned long *addr,
 
 bool need_SSR(struct f2fs_sb_info *sbi)
 {
-   int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
-   int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
-   int imeta_secs = get_blocktype_secs(sbi, F2FS_DIRTY_IMETA);
+   s64 node_pages = get_pages(sbi, F2FS_DIRTY_NODES);
+   s64 dent_pages = get_pages(sbi, F2FS_DIRTY_DENTS);
+   s64 imeta_pages = get_pages(sbi, F2FS_DIRTY_IMETA);
 
if (test_opt(sbi, LFS))
return false;
if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
return true;
 
-   return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
-   SM_I(sbi)->min_ssr_sections + reserved_sections(sbi));
+   return free_sections(sbi) <=
+   (PAGE2SEC(sbi, node_pages + imeta_pages) +
+   PAGE2SEC(sbi, 2 * dent_pages) +
+   SM_I(sbi)->min_ssr_sections + reserved_sections(sbi));
 }
 
 void register_inmem_page(struct inode *inode, struct page *page)
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index d1d394c..723d79e 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -115,6 +115,10 @@
 #define SECTOR_TO_BLOCK(sectors)   \
((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
 
+#define PAGE2SEC(sbi, pages)   \
+   pages) + BLKS_PER_SEC(sbi) - 1) \
+   >> sbi->log_blocks_per_seg) / sbi->segs_per_sec)
+
 /*
  * indicate a block allocation direction: RIGHT and LEFT.
  * RIGHT means allocating new sections towards the end of volume.
@@ -527,9 +531,9 @@ static inline bool has_curseg_enough_space(struct 
f2fs_sb_info *sbi)
 static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
int freed, int needed)
 {
-   int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
-   int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
-   int imeta_secs = get_blocktype_secs(sbi, F2FS_DIRTY_IMETA);
+   s64 node_pages = get_pages(sbi, F2FS_DIRTY_NODES);
+   s64 dent_pages = get_pages(sbi, F2FS_DIRTY_DENTS);
+   s64 imeta_pages = get_pages(sbi, F2FS_DIRTY_IMETA);
 
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
return false;
@@ -538,7 +542,8 @@ static inline bool has_not_enough_free_secs(struct 
f2fs_sb_info *sbi,
has_curseg_enough_space(sbi))
return false;
return (free_sections(sbi) + freed) <=
-   (node_secs + 2 * dent_secs + imeta_secs +
+   (PAGE2SEC(sbi, node_pages + imeta_pages) +
+   PAGE2SEC(sbi, 2 * dent_pages) +
reserved_sections(sbi) + needed);
 }
 
-- 
1.8.5.2



[PATCH v3 11/21] fpga: dfl: fme: add header sub feature support

2017-11-26 Thread Wu Hao
From: Kang Luwei 

The header register set is always present for FPGA Management Engine (FME),
this patch implements init and uinit function for header sub feature and
introduce several read-only sysfs interfaces for the capability and status.

Sysfs interfaces:
* /sys/class/fpga_region///ports_num
  Read-only. Number of ports implemented

* /sys/class/fpga_region///bitstream_id
  Read-only. Blue Bitstream (static FPGA region) identifier number

* /sys/class/fpga_region///bitstream_metadata
  Read-only. Blue Bitstream (static FPGA region) meta data

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: add sysfs documentation
v3: rename driver to fpga-dfl-fme.
improve sysfs doc and commit description.
replace bitfield.
---
 .../ABI/testing/sysfs-platform-fpga-dfl-fme| 21 
 drivers/fpga/dfl-fme-main.c| 60 ++
 2 files changed, 81 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme
new file mode 100644
index 000..6b32799
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme
@@ -0,0 +1,21 @@
+What:  /sys/bus/platform/devices/fpga-dfl-fme.0/ports_num
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. One DFL FPGA device may have more than 1
+   port/Accelerator Function Unit (AFU). It returns the
+   number of ports on the FPGA device when read it.
+
+What:  /sys/bus/platform/devices/fpga-dfl-fme.0/bitstream_id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns Blue Bitstream (static FPGA region)
+   identifier number.
+
+What:  /sys/bus/platform/devices/fpga-dfl-fme.0/bitstream_meta
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns Blue Bitstream (static FPGA region)
+   meta data.
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index f7b5f7d..d17c66a 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -21,9 +21,68 @@
 
 #include "fpga-dfl.h"
 
+static ssize_t ports_num_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   void __iomem *base;
+   u64 v;
+
+   base = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+
+   v = readq(base + FME_HDR_CAP);
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n",
+(unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
+}
+static DEVICE_ATTR_RO(ports_num);
+
+static ssize_t bitstream_id_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   void __iomem *base;
+   u64 v;
+
+   base = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+
+   v = readq(base + FME_HDR_BITSTREAM_ID);
+
+   return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
+}
+static DEVICE_ATTR_RO(bitstream_id);
+
+static ssize_t bitstream_metadata_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   void __iomem *base;
+   u64 v;
+
+   base = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+
+   v = readq(base + FME_HDR_BITSTREAM_MD);
+
+   return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
+}
+static DEVICE_ATTR_RO(bitstream_metadata);
+
+static const struct attribute *fme_hdr_attrs[] = {
+   _attr_ports_num.attr,
+   _attr_bitstream_id.attr,
+   _attr_bitstream_metadata.attr,
+   NULL,
+};
+
 static int fme_hdr_init(struct platform_device *pdev, struct feature *feature)
 {
+   void __iomem *base = feature->ioaddr;
+   int ret;
+
dev_dbg(>dev, "FME HDR Init.\n");
+   dev_dbg(>dev, "FME cap %llx.\n",
+   (unsigned long long)readq(base + FME_HDR_CAP));
+
+   ret = sysfs_create_files(>dev.kobj, fme_hdr_attrs);
+   if (ret)
+   return ret;
 
return 0;
 }
@@ -31,6 +90,7 @@ static int fme_hdr_init(struct platform_device *pdev, struct 
feature *feature)
 static void fme_hdr_uinit(struct platform_device *pdev, struct feature 
*feature)
 {
dev_dbg(>dev, "FME HDR UInit.\n");
+   sysfs_remove_files(>dev.kobj, fme_hdr_attrs);
 }
 
 static const struct feature_ops fme_hdr_ops = {
-- 
1.8.3.1



[PATCH] f2fs: avoid false positive of free secs check

2017-11-26 Thread Yunlong Song
Sometimes f2fs_gc is called with no target victim (e.g. xfstest
generic/027, ndirty_node:545 ndiry_dent:1 ndirty_imeta:513 rsvd_segs:21
free_segs:27, has_not_enough_free_secs will return true). This patch
first merges pages and then converts into sections.

Signed-off-by: Yunlong Song 
---
 fs/f2fs/f2fs.h|  9 -
 fs/f2fs/segment.c | 12 +++-
 fs/f2fs/segment.h | 13 +
 3 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ca6b0c9..e89cff7 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1675,15 +1675,6 @@ static inline int get_dirty_pages(struct inode *inode)
return atomic_read(_I(inode)->dirty_pages);
 }
 
-static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
-{
-   unsigned int pages_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
-   unsigned int segs = (get_pages(sbi, block_type) + pages_per_sec - 1) >>
-   sbi->log_blocks_per_seg;
-
-   return segs / sbi->segs_per_sec;
-}
-
 static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
 {
return sbi->total_valid_block_count;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c117e09..603f805 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -171,17 +171,19 @@ static unsigned long __find_rev_next_zero_bit(const 
unsigned long *addr,
 
 bool need_SSR(struct f2fs_sb_info *sbi)
 {
-   int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
-   int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
-   int imeta_secs = get_blocktype_secs(sbi, F2FS_DIRTY_IMETA);
+   s64 node_pages = get_pages(sbi, F2FS_DIRTY_NODES);
+   s64 dent_pages = get_pages(sbi, F2FS_DIRTY_DENTS);
+   s64 imeta_pages = get_pages(sbi, F2FS_DIRTY_IMETA);
 
if (test_opt(sbi, LFS))
return false;
if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
return true;
 
-   return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
-   SM_I(sbi)->min_ssr_sections + reserved_sections(sbi));
+   return free_sections(sbi) <=
+   (PAGE2SEC(sbi, node_pages + imeta_pages) +
+   PAGE2SEC(sbi, 2 * dent_pages) +
+   SM_I(sbi)->min_ssr_sections + reserved_sections(sbi));
 }
 
 void register_inmem_page(struct inode *inode, struct page *page)
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index d1d394c..723d79e 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -115,6 +115,10 @@
 #define SECTOR_TO_BLOCK(sectors)   \
((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
 
+#define PAGE2SEC(sbi, pages)   \
+   pages) + BLKS_PER_SEC(sbi) - 1) \
+   >> sbi->log_blocks_per_seg) / sbi->segs_per_sec)
+
 /*
  * indicate a block allocation direction: RIGHT and LEFT.
  * RIGHT means allocating new sections towards the end of volume.
@@ -527,9 +531,9 @@ static inline bool has_curseg_enough_space(struct 
f2fs_sb_info *sbi)
 static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
int freed, int needed)
 {
-   int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
-   int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
-   int imeta_secs = get_blocktype_secs(sbi, F2FS_DIRTY_IMETA);
+   s64 node_pages = get_pages(sbi, F2FS_DIRTY_NODES);
+   s64 dent_pages = get_pages(sbi, F2FS_DIRTY_DENTS);
+   s64 imeta_pages = get_pages(sbi, F2FS_DIRTY_IMETA);
 
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
return false;
@@ -538,7 +542,8 @@ static inline bool has_not_enough_free_secs(struct 
f2fs_sb_info *sbi,
has_curseg_enough_space(sbi))
return false;
return (free_sections(sbi) + freed) <=
-   (node_secs + 2 * dent_secs + imeta_secs +
+   (PAGE2SEC(sbi, node_pages + imeta_pages) +
+   PAGE2SEC(sbi, 2 * dent_pages) +
reserved_sections(sbi) + needed);
 }
 
-- 
1.8.5.2



[PATCH v3 11/21] fpga: dfl: fme: add header sub feature support

2017-11-26 Thread Wu Hao
From: Kang Luwei 

The header register set is always present for FPGA Management Engine (FME),
this patch implements init and uinit function for header sub feature and
introduce several read-only sysfs interfaces for the capability and status.

Sysfs interfaces:
* /sys/class/fpga_region///ports_num
  Read-only. Number of ports implemented

* /sys/class/fpga_region///bitstream_id
  Read-only. Blue Bitstream (static FPGA region) identifier number

* /sys/class/fpga_region///bitstream_metadata
  Read-only. Blue Bitstream (static FPGA region) meta data

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: add sysfs documentation
v3: rename driver to fpga-dfl-fme.
improve sysfs doc and commit description.
replace bitfield.
---
 .../ABI/testing/sysfs-platform-fpga-dfl-fme| 21 
 drivers/fpga/dfl-fme-main.c| 60 ++
 2 files changed, 81 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme
new file mode 100644
index 000..6b32799
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme
@@ -0,0 +1,21 @@
+What:  /sys/bus/platform/devices/fpga-dfl-fme.0/ports_num
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. One DFL FPGA device may have more than 1
+   port/Accelerator Function Unit (AFU). It returns the
+   number of ports on the FPGA device when read it.
+
+What:  /sys/bus/platform/devices/fpga-dfl-fme.0/bitstream_id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns Blue Bitstream (static FPGA region)
+   identifier number.
+
+What:  /sys/bus/platform/devices/fpga-dfl-fme.0/bitstream_meta
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns Blue Bitstream (static FPGA region)
+   meta data.
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index f7b5f7d..d17c66a 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -21,9 +21,68 @@
 
 #include "fpga-dfl.h"
 
+static ssize_t ports_num_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   void __iomem *base;
+   u64 v;
+
+   base = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+
+   v = readq(base + FME_HDR_CAP);
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n",
+(unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
+}
+static DEVICE_ATTR_RO(ports_num);
+
+static ssize_t bitstream_id_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   void __iomem *base;
+   u64 v;
+
+   base = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+
+   v = readq(base + FME_HDR_BITSTREAM_ID);
+
+   return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
+}
+static DEVICE_ATTR_RO(bitstream_id);
+
+static ssize_t bitstream_metadata_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   void __iomem *base;
+   u64 v;
+
+   base = get_feature_ioaddr_by_index(dev, FME_FEATURE_ID_HEADER);
+
+   v = readq(base + FME_HDR_BITSTREAM_MD);
+
+   return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
+}
+static DEVICE_ATTR_RO(bitstream_metadata);
+
+static const struct attribute *fme_hdr_attrs[] = {
+   _attr_ports_num.attr,
+   _attr_bitstream_id.attr,
+   _attr_bitstream_metadata.attr,
+   NULL,
+};
+
 static int fme_hdr_init(struct platform_device *pdev, struct feature *feature)
 {
+   void __iomem *base = feature->ioaddr;
+   int ret;
+
dev_dbg(>dev, "FME HDR Init.\n");
+   dev_dbg(>dev, "FME cap %llx.\n",
+   (unsigned long long)readq(base + FME_HDR_CAP));
+
+   ret = sysfs_create_files(>dev.kobj, fme_hdr_attrs);
+   if (ret)
+   return ret;
 
return 0;
 }
@@ -31,6 +90,7 @@ static int fme_hdr_init(struct platform_device *pdev, struct 
feature *feature)
 static void fme_hdr_uinit(struct platform_device *pdev, struct feature 
*feature)
 {
dev_dbg(>dev, "FME HDR UInit.\n");
+   sysfs_remove_files(>dev.kobj, fme_hdr_attrs);
 }
 
 static const struct feature_ops fme_hdr_ops = {
-- 
1.8.3.1



[PATCH v3 09/21] fpga: intel-dfl-pci: add enumeration for feature devices

2017-11-26 Thread Wu Hao
The Device Feature List (DFL) is implemented in MMIO, and features
are linked via the DFLs. This patch enables pcie driver to prepare
enumeration information (e.g locations of all device feature lists
in MMIO) and use common APIs provided by the Device Feature List
framework to enumerate each feature device linked.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: split from another patch
use common functions from DFL framework for enumeration.
---
 drivers/fpga/intel-dfl-pci.c | 199 ++-
 1 file changed, 197 insertions(+), 2 deletions(-)

diff --git a/drivers/fpga/intel-dfl-pci.c b/drivers/fpga/intel-dfl-pci.c
index 4774a77..1c7ba22 100644
--- a/drivers/fpga/intel-dfl-pci.c
+++ b/drivers/fpga/intel-dfl-pci.c
@@ -24,9 +24,52 @@
 #include 
 #include 
 
+#include "fpga-dfl.h"
+
 #define DRV_VERSION"0.8"
 #define DRV_NAME   "intel-dfl-pci"
 
+struct cci_drvdata {
+   struct fpga_cdev *cdev; /* container device */
+   struct list_head regions; /* list of pci bar mapping region */
+};
+
+/* pci bar mapping info */
+struct cci_region {
+   int bar;
+   void __iomem *ioaddr;   /* pointer to mapped bar region */
+   struct list_head node;
+};
+
+static void __iomem *cci_pci_ioremap_bar(struct pci_dev *pcidev, int bar)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+   struct cci_region *region;
+
+   list_for_each_entry(region, >regions, node)
+   if (region->bar == bar) {
+   dev_dbg(>dev, "BAR %d region exists\n", bar);
+   return region->ioaddr;
+   }
+
+   region = devm_kzalloc(>dev, sizeof(*region), GFP_KERNEL);
+   if (!region)
+   return NULL;
+
+   region->bar = bar;
+   region->ioaddr = pci_ioremap_bar(pcidev, bar);
+   if (!region->ioaddr) {
+   dev_err(>dev, "can't ioremap memory from BAR %d.\n",
+   bar);
+   devm_kfree(>dev, region);
+   return NULL;
+   }
+
+   list_add(>node, >regions);
+
+   return region->ioaddr;
+}
+
 /* PCI Device ID */
 #define PCIE_DEVICE_ID_PF_INT_5_X  0xBCBD
 #define PCIE_DEVICE_ID_PF_INT_6_X  0xBCC0
@@ -47,6 +90,143 @@
 };
 MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
 
+static int cci_init_drvdata(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(>regions);
+
+   pci_set_drvdata(pcidev, drvdata);
+
+   return 0;
+}
+
+static void cci_pci_release_regions(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+   struct cci_region *tmp, *region;
+
+   list_for_each_entry_safe(region, tmp, >regions, node) {
+   list_del(>node);
+   if (region->ioaddr)
+   pci_iounmap(pcidev, region->ioaddr);
+   devm_kfree(>dev, region);
+   }
+}
+
+static void cci_remove_drvdata(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+
+   cci_pci_release_regions(pcidev);
+   pci_set_drvdata(pcidev, NULL);
+   devm_kfree(>dev, drvdata);
+}
+
+static void cci_remove_feature_devs(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+
+   /* remove all children feature devices */
+   fpga_remove_feature_devs(drvdata->cdev);
+}
+
+/* enumerate feature devices under pci device */
+static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+   struct fpga_cdev *cdev;
+   struct fpga_enum_info *info;
+   resource_size_t start, len;
+   void __iomem *base;
+   int port_num, bar, i, ret = 0;
+   u32 offset;
+   u64 v;
+
+   /* allocate enumeration info via pci_dev */
+   info = fpga_enum_info_alloc(>dev);
+   if (!info)
+   return -ENOMEM;
+
+   /* start to find Device Feature List from Bar 0 */
+   base = cci_pci_ioremap_bar(pcidev, 0);
+   if (!base) {
+   ret = -ENOMEM;
+   goto enum_info_free_exit;
+   }
+
+   /*
+* PF device has FME and Ports/AFUs, and VF device only has 1 Port/AFU.
+* check them and add related "Device Feature List" info for the next
+* step enumeration.
+*/
+   if (feature_is_fme(base)) {
+   start = pci_resource_start(pcidev, 0);
+   len = pci_resource_len(pcidev, 0);
+
+   

[PATCH v3 09/21] fpga: intel-dfl-pci: add enumeration for feature devices

2017-11-26 Thread Wu Hao
The Device Feature List (DFL) is implemented in MMIO, and features
are linked via the DFLs. This patch enables pcie driver to prepare
enumeration information (e.g locations of all device feature lists
in MMIO) and use common APIs provided by the Device Feature List
framework to enumerate each feature device linked.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: split from another patch
use common functions from DFL framework for enumeration.
---
 drivers/fpga/intel-dfl-pci.c | 199 ++-
 1 file changed, 197 insertions(+), 2 deletions(-)

diff --git a/drivers/fpga/intel-dfl-pci.c b/drivers/fpga/intel-dfl-pci.c
index 4774a77..1c7ba22 100644
--- a/drivers/fpga/intel-dfl-pci.c
+++ b/drivers/fpga/intel-dfl-pci.c
@@ -24,9 +24,52 @@
 #include 
 #include 
 
+#include "fpga-dfl.h"
+
 #define DRV_VERSION"0.8"
 #define DRV_NAME   "intel-dfl-pci"
 
+struct cci_drvdata {
+   struct fpga_cdev *cdev; /* container device */
+   struct list_head regions; /* list of pci bar mapping region */
+};
+
+/* pci bar mapping info */
+struct cci_region {
+   int bar;
+   void __iomem *ioaddr;   /* pointer to mapped bar region */
+   struct list_head node;
+};
+
+static void __iomem *cci_pci_ioremap_bar(struct pci_dev *pcidev, int bar)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+   struct cci_region *region;
+
+   list_for_each_entry(region, >regions, node)
+   if (region->bar == bar) {
+   dev_dbg(>dev, "BAR %d region exists\n", bar);
+   return region->ioaddr;
+   }
+
+   region = devm_kzalloc(>dev, sizeof(*region), GFP_KERNEL);
+   if (!region)
+   return NULL;
+
+   region->bar = bar;
+   region->ioaddr = pci_ioremap_bar(pcidev, bar);
+   if (!region->ioaddr) {
+   dev_err(>dev, "can't ioremap memory from BAR %d.\n",
+   bar);
+   devm_kfree(>dev, region);
+   return NULL;
+   }
+
+   list_add(>node, >regions);
+
+   return region->ioaddr;
+}
+
 /* PCI Device ID */
 #define PCIE_DEVICE_ID_PF_INT_5_X  0xBCBD
 #define PCIE_DEVICE_ID_PF_INT_6_X  0xBCC0
@@ -47,6 +90,143 @@
 };
 MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
 
+static int cci_init_drvdata(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(>regions);
+
+   pci_set_drvdata(pcidev, drvdata);
+
+   return 0;
+}
+
+static void cci_pci_release_regions(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+   struct cci_region *tmp, *region;
+
+   list_for_each_entry_safe(region, tmp, >regions, node) {
+   list_del(>node);
+   if (region->ioaddr)
+   pci_iounmap(pcidev, region->ioaddr);
+   devm_kfree(>dev, region);
+   }
+}
+
+static void cci_remove_drvdata(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+
+   cci_pci_release_regions(pcidev);
+   pci_set_drvdata(pcidev, NULL);
+   devm_kfree(>dev, drvdata);
+}
+
+static void cci_remove_feature_devs(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+
+   /* remove all children feature devices */
+   fpga_remove_feature_devs(drvdata->cdev);
+}
+
+/* enumerate feature devices under pci device */
+static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
+{
+   struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
+   struct fpga_cdev *cdev;
+   struct fpga_enum_info *info;
+   resource_size_t start, len;
+   void __iomem *base;
+   int port_num, bar, i, ret = 0;
+   u32 offset;
+   u64 v;
+
+   /* allocate enumeration info via pci_dev */
+   info = fpga_enum_info_alloc(>dev);
+   if (!info)
+   return -ENOMEM;
+
+   /* start to find Device Feature List from Bar 0 */
+   base = cci_pci_ioremap_bar(pcidev, 0);
+   if (!base) {
+   ret = -ENOMEM;
+   goto enum_info_free_exit;
+   }
+
+   /*
+* PF device has FME and Ports/AFUs, and VF device only has 1 Port/AFU.
+* check them and add related "Device Feature List" info for the next
+* step enumeration.
+*/
+   if (feature_is_fme(base)) {
+   start = pci_resource_start(pcidev, 0);
+   len = pci_resource_len(pcidev, 0);
+
+   fpga_enum_info_add_dfl(info, start, len, base);
+
+   /*
+* find more Device Feature Lists (e.g Ports) per information
+* indicated by FME module.
+

[PATCH v3 15/21] fpga: dfl: add fpga bridge platform driver for FME

2017-11-26 Thread Wu Hao
This patch adds fpga bridge platform driver for FPGA Management Engine.
It implements the enable_set call back for fpga bridge.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Wu Hao 

v3: rename driver to fpga-dfl-fme-br
remove useless dev_dbg in probe function.
rebased due to fpga api change.
---
 drivers/fpga/Kconfig   |  6 +++
 drivers/fpga/Makefile  |  1 +
 drivers/fpga/fpga-dfl-fme-br.c | 87 ++
 3 files changed, 94 insertions(+)
 create mode 100644 drivers/fpga/fpga-dfl-fme-br.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 0171ecb..3804064 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -156,6 +156,12 @@ config FPGA_DFL_FME_MGR
help
  Say Y to enable FPGA Manager driver for FPGA Management Engine.
 
+config FPGA_DFL_FME_BRIDGE
+   tristate "FPGA DFL FME Bridge Driver"
+   depends on FPGA_DFL_FME
+   help
+ Say Y to enable FPGA Bridge driver for FPGA Management Engine.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 6378580..3c8c4c7 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_OF_FPGA_REGION)  += of-fpga-region.o
 obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
 obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
 obj-$(CONFIG_FPGA_DFL_FME_MGR) += fpga-dfl-fme-mgr.o
+obj-$(CONFIG_FPGA_DFL_FME_BRIDGE)  += fpga-dfl-fme-br.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
 
diff --git a/drivers/fpga/fpga-dfl-fme-br.c b/drivers/fpga/fpga-dfl-fme-br.c
new file mode 100644
index 000..db2603b
--- /dev/null
+++ b/drivers/fpga/fpga-dfl-fme-br.c
@@ -0,0 +1,87 @@
+/*
+ * FPGA Bridge Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Wu Hao 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "fpga-dfl.h"
+#include "dfl-fme.h"
+
+static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+   struct fme_br_pdata *pdata = bridge->priv;
+   int ret = 0;
+
+   if (enable)
+   fpga_port_enable(pdata->port);
+   else
+   ret = fpga_port_disable(pdata->port);
+
+   return ret;
+}
+
+static const struct fpga_bridge_ops fme_bridge_ops = {
+   .enable_set = fme_bridge_enable_set,
+};
+
+static int fme_br_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct fme_br_pdata *pdata = dev_get_platdata(dev);
+   struct fpga_bridge *br;
+   int ret;
+
+   br = devm_kzalloc(dev, sizeof(*br), GFP_KERNEL);
+   if (!br)
+   return -ENOMEM;
+
+   br->name = "Intel FPGA FME Bridge";
+   br->br_ops = _bridge_ops;
+   br->priv = pdata;
+   br->parent = dev;
+   platform_set_drvdata(pdev, br);
+
+   ret = fpga_bridge_register(br);
+   if (ret)
+   dev_err(dev, "unable to register FPGA Bridge\n");
+
+   return ret;
+}
+
+static int fme_br_remove(struct platform_device *pdev)
+{
+   struct fpga_bridge *br = platform_get_drvdata(pdev);
+
+   fpga_bridge_unregister(br);
+
+   return 0;
+}
+
+static struct platform_driver fme_br_driver = {
+   .driver = {
+   .name= FPGA_DFL_FME_BRIDGE,
+   },
+   .probe   = fme_br_probe,
+   .remove  = fme_br_remove,
+};
+
+module_platform_driver(fme_br_driver);
+
+MODULE_DESCRIPTION("FPGA Bridge for FPGA Management Engine");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:fpga-dfl-fme-bridge");
-- 
1.8.3.1



[PATCH v3 15/21] fpga: dfl: add fpga bridge platform driver for FME

2017-11-26 Thread Wu Hao
This patch adds fpga bridge platform driver for FPGA Management Engine.
It implements the enable_set call back for fpga bridge.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Wu Hao 

v3: rename driver to fpga-dfl-fme-br
remove useless dev_dbg in probe function.
rebased due to fpga api change.
---
 drivers/fpga/Kconfig   |  6 +++
 drivers/fpga/Makefile  |  1 +
 drivers/fpga/fpga-dfl-fme-br.c | 87 ++
 3 files changed, 94 insertions(+)
 create mode 100644 drivers/fpga/fpga-dfl-fme-br.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 0171ecb..3804064 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -156,6 +156,12 @@ config FPGA_DFL_FME_MGR
help
  Say Y to enable FPGA Manager driver for FPGA Management Engine.
 
+config FPGA_DFL_FME_BRIDGE
+   tristate "FPGA DFL FME Bridge Driver"
+   depends on FPGA_DFL_FME
+   help
+ Say Y to enable FPGA Bridge driver for FPGA Management Engine.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 6378580..3c8c4c7 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_OF_FPGA_REGION)  += of-fpga-region.o
 obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
 obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
 obj-$(CONFIG_FPGA_DFL_FME_MGR) += fpga-dfl-fme-mgr.o
+obj-$(CONFIG_FPGA_DFL_FME_BRIDGE)  += fpga-dfl-fme-br.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
 
diff --git a/drivers/fpga/fpga-dfl-fme-br.c b/drivers/fpga/fpga-dfl-fme-br.c
new file mode 100644
index 000..db2603b
--- /dev/null
+++ b/drivers/fpga/fpga-dfl-fme-br.c
@@ -0,0 +1,87 @@
+/*
+ * FPGA Bridge Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Wu Hao 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "fpga-dfl.h"
+#include "dfl-fme.h"
+
+static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+   struct fme_br_pdata *pdata = bridge->priv;
+   int ret = 0;
+
+   if (enable)
+   fpga_port_enable(pdata->port);
+   else
+   ret = fpga_port_disable(pdata->port);
+
+   return ret;
+}
+
+static const struct fpga_bridge_ops fme_bridge_ops = {
+   .enable_set = fme_bridge_enable_set,
+};
+
+static int fme_br_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct fme_br_pdata *pdata = dev_get_platdata(dev);
+   struct fpga_bridge *br;
+   int ret;
+
+   br = devm_kzalloc(dev, sizeof(*br), GFP_KERNEL);
+   if (!br)
+   return -ENOMEM;
+
+   br->name = "Intel FPGA FME Bridge";
+   br->br_ops = _bridge_ops;
+   br->priv = pdata;
+   br->parent = dev;
+   platform_set_drvdata(pdev, br);
+
+   ret = fpga_bridge_register(br);
+   if (ret)
+   dev_err(dev, "unable to register FPGA Bridge\n");
+
+   return ret;
+}
+
+static int fme_br_remove(struct platform_device *pdev)
+{
+   struct fpga_bridge *br = platform_get_drvdata(pdev);
+
+   fpga_bridge_unregister(br);
+
+   return 0;
+}
+
+static struct platform_driver fme_br_driver = {
+   .driver = {
+   .name= FPGA_DFL_FME_BRIDGE,
+   },
+   .probe   = fme_br_probe,
+   .remove  = fme_br_remove,
+};
+
+module_platform_driver(fme_br_driver);
+
+MODULE_DESCRIPTION("FPGA Bridge for FPGA Management Engine");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:fpga-dfl-fme-bridge");
-- 
1.8.3.1



[PATCH v3 18/21] fpga: dfl: afu: add header sub feature support

2017-11-26 Thread Wu Hao
The port header register set is always present for port, it is mainly
for capability, control and status of the ports that AFU connected to.

This patch implements header sub feature support. Below user interfaces
are created by this patch.

Sysfs interface:
* /sys/class/fpga_region///id
  Read-only. Port ID.

Ioctl interface:
* FPGA_PORT_RESET
  Reset the FPGA Port and its AFU.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: rename driver name to fpga-dfl-afu
add more description for reset ioctl.
fix some checkpatch issues.
---
 .../ABI/testing/sysfs-platform-fpga-dfl-afu|  7 
 drivers/fpga/dfl-afu-main.c| 44 +-
 include/uapi/linux/fpga-dfl.h  | 17 +
 3 files changed, 67 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
new file mode 100644
index 000..f4bcd94
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
@@ -0,0 +1,7 @@
+What:  /sys/bus/platform/devices/fpga-dfl-port.0/id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns id of this port. One DFL FPGA device
+   may have more than one port. Userspace could use this id to
+   distinguish different ports under same FPGA device.
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index d9f4b81..b01376c 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -18,25 +18,66 @@
 
 #include 
 #include 
+#include 
 
 #include "fpga-dfl.h"
 
+static ssize_t
+id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int id = fpga_port_id(to_platform_device(dev));
+
+   return scnprintf(buf, PAGE_SIZE, "%d\n", id);
+}
+static DEVICE_ATTR_RO(id);
+
+static const struct attribute *port_hdr_attrs[] = {
+   _attr_id.attr,
+   NULL,
+};
+
 static int port_hdr_init(struct platform_device *pdev, struct feature *feature)
 {
dev_dbg(>dev, "PORT HDR Init.\n");
 
-   return 0;
+   fpga_port_reset(pdev);
+
+   return sysfs_create_files(>dev.kobj, port_hdr_attrs);
 }
 
 static void port_hdr_uinit(struct platform_device *pdev,
   struct feature *feature)
 {
dev_dbg(>dev, "PORT HDR UInit.\n");
+
+   sysfs_remove_files(>dev.kobj, port_hdr_attrs);
+}
+
+static long
+port_hdr_ioctl(struct platform_device *pdev, struct feature *feature,
+  unsigned int cmd, unsigned long arg)
+{
+   long ret;
+
+   switch (cmd) {
+   case FPGA_PORT_RESET:
+   if (!arg)
+   ret = fpga_port_reset(pdev);
+   else
+   ret = -EINVAL;
+   break;
+   default:
+   dev_dbg(>dev, "%x cmd not handled", cmd);
+   ret = -ENODEV;
+   }
+
+   return ret;
 }
 
 static const struct feature_ops port_hdr_ops = {
.init = port_hdr_init,
.uinit = port_hdr_uinit,
+   .ioctl = port_hdr_ioctl,
 };
 
 static struct feature_driver port_feature_drvs[] = {
@@ -76,6 +117,7 @@ static int afu_release(struct inode *inode, struct file 
*filp)
 
dev_dbg(>dev, "Device File Release\n");
 
+   fpga_port_reset(pdev);
feature_dev_use_end(pdata);
 
return 0;
diff --git a/include/uapi/linux/fpga-dfl.h b/include/uapi/linux/fpga-dfl.h
index 75bdf88..9bf273d 100644
--- a/include/uapi/linux/fpga-dfl.h
+++ b/include/uapi/linux/fpga-dfl.h
@@ -30,8 +30,11 @@
 #define FPGA_MAGIC 0xB6
 
 #define FPGA_BASE 0
+#define PORT_BASE 0x40
 #define FME_BASE 0x80
 
+/* Common IOCTLs for both FME and AFU file descriptor */
+
 /**
  * FPGA_GET_API_VERSION - _IO(FPGA_MAGIC, FPGA_BASE + 0)
  *
@@ -50,6 +53,20 @@
 
 #define FPGA_CHECK_EXTENSION   _IO(FPGA_MAGIC, FPGA_BASE + 1)
 
+/* IOCTLs for AFU file descriptor */
+
+/**
+ * FPGA_PORT_RESET - _IO(FPGA_MAGIC, PORT_BASE + 0)
+ *
+ * Reset the FPGA Port and its AFU. No parameters are supported.
+ * Userspace can do Port reset at any time, e.g during DMA or PR. But
+ * it should never cause any system level issue, only functional failure
+ * (e.g DMA or PR operation failure) and be recoverable from the failure.
+ * Return: 0 on success, -errno of failure
+ */
+
+#define FPGA_PORT_RESET_IO(FPGA_MAGIC, PORT_BASE + 0)
+
 /* IOCTLs for FME file descriptor */
 
 /**
-- 
1.8.3.1



[PATCH v3 16/21] fpga: dfl: add fpga region platform driver for FME

2017-11-26 Thread Wu Hao
This patch adds fpga region platform driver for FPGA Management Engine.
It register an fpga region with given fpga manager / bridge device.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Wu Hao 

v3: rename driver to fpga-dfl-fme-region
fix fpga_mgr_put order problem in remove function.
rebased due to fpga api changes.
---
 drivers/fpga/Kconfig   |  6 +++
 drivers/fpga/Makefile  |  1 +
 drivers/fpga/fpga-dfl-fme-region.c | 92 ++
 3 files changed, 99 insertions(+)
 create mode 100644 drivers/fpga/fpga-dfl-fme-region.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 3804064..2df9dfd 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -162,6 +162,12 @@ config FPGA_DFL_FME_BRIDGE
help
  Say Y to enable FPGA Bridge driver for FPGA Management Engine.
 
+config FPGA_DFL_FME_REGION
+   tristate "FPGA DFL FME Region Driver"
+   depends on FPGA_DFL_FME
+   help
+ Say Y to enable FPGA Region driver for FPGA Management Engine.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 3c8c4c7..11777d3 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_FPGA_DFL)+= fpga-dfl.o
 obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
 obj-$(CONFIG_FPGA_DFL_FME_MGR) += fpga-dfl-fme-mgr.o
 obj-$(CONFIG_FPGA_DFL_FME_BRIDGE)  += fpga-dfl-fme-br.o
+obj-$(CONFIG_FPGA_DFL_FME_REGION)  += fpga-dfl-fme-region.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
 
diff --git a/drivers/fpga/fpga-dfl-fme-region.c 
b/drivers/fpga/fpga-dfl-fme-region.c
new file mode 100644
index 000..0b988ab
--- /dev/null
+++ b/drivers/fpga/fpga-dfl-fme-region.c
@@ -0,0 +1,92 @@
+/*
+ * FPGA Region Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Wu Hao 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "fpga-dfl.h"
+#include "dfl-fme.h"
+
+static int fme_region_get_bridges(struct fpga_region *region)
+{
+   struct fme_region_pdata *pdata = region->priv;
+   struct device *dev = >br->dev;
+
+   return fpga_bridge_get_to_list(dev, region->info, >bridge_list);
+}
+
+static int fme_region_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct fme_region_pdata *pdata = dev_get_platdata(dev);
+   struct fpga_region *region;
+   struct fpga_manager *mgr;
+   int ret;
+
+   mgr = fpga_mgr_get(>mgr->dev);
+   if (IS_ERR(mgr))
+   return -EPROBE_DEFER;
+
+   region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
+   if (!region) {
+   ret = -ENOMEM;
+   goto eprobe_mgr_put;
+   }
+
+   region->mgr = mgr;
+   region->get_bridges = fme_region_get_bridges;
+   region->priv = pdata;
+   region->parent = dev;
+   platform_set_drvdata(pdev, region);
+
+   ret = fpga_region_register(region);
+   if (ret)
+   goto eprobe_mgr_put;
+
+   dev_dbg(dev, "DFL FME FPGA Region probed\n");
+
+   return 0;
+
+eprobe_mgr_put:
+   fpga_mgr_put(mgr);
+   return ret;
+}
+
+static int fme_region_remove(struct platform_device *pdev)
+{
+   struct fpga_region *region = dev_get_drvdata(>dev);
+
+   fpga_region_unregister(region);
+   fpga_mgr_put(region->mgr);
+
+   return 0;
+}
+
+static struct platform_driver fme_region_driver = {
+   .driver = {
+   .name= FPGA_DFL_FME_REGION,
+   },
+   .probe   = fme_region_probe,
+   .remove  = fme_region_remove,
+};
+
+module_platform_driver(fme_region_driver);
+
+MODULE_DESCRIPTION("FPGA Region for FPGA Management Engine");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:fpga-dfl-fme-region");
-- 
1.8.3.1



[PATCH v3 12/21] fpga: dfl: fme: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls support

2017-11-26 Thread Wu Hao
FPGA_GET_API_VERSION and FPGA_CHECK_EXTENSION ioctls are common ones which
need to be supported by all feature devices drivers including FME and AFU.
Userspace application can use these ioctl interfaces to get the API info
and check if specific extension is supported or not in current driver.

This patch implements above 2 ioctls in FPGA Management Engine (FME)
driver.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: switched to GPLv2 license.
v3: rename intel-fpga.h to fpga-dfl.h and rebased.
---
 Documentation/ioctl/ioctl-number.txt |  1 +
 drivers/fpga/dfl-fme-main.c  | 12 +
 include/uapi/linux/fpga-dfl.h| 50 
 3 files changed, 63 insertions(+)
 create mode 100644 include/uapi/linux/fpga-dfl.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 3e3fdae..91ad573 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -324,6 +324,7 @@ Code  Seq#(hex) Include FileComments
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h
 0xB5   00-0F   uapi/linux/rpmsg.h  

+0xB6   all linux/fpga-dfl.h
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-BF   uapi/scsi/cxlflash_ioctl.h
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index d17c66a..b4e0b54 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -18,6 +18,7 @@
 
 #include 
 #include 
+#include 
 
 #include "fpga-dfl.h"
 
@@ -108,6 +109,13 @@ static void fme_hdr_uinit(struct platform_device *pdev, 
struct feature *feature)
},
 };
 
+static long fme_ioctl_check_extension(struct feature_platform_data *pdata,
+ unsigned long arg)
+{
+   /* No extension support for now */
+   return 0;
+}
+
 static int fme_open(struct inode *inode, struct file *filp)
 {
struct platform_device *fdev = fpga_inode_to_feature_dev(inode);
@@ -148,6 +156,10 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, 
unsigned long arg)
dev_dbg(>dev, "%s cmd 0x%x\n", __func__, cmd);
 
switch (cmd) {
+   case FPGA_GET_API_VERSION:
+   return FPGA_API_VERSION;
+   case FPGA_CHECK_EXTENSION:
+   return fme_ioctl_check_extension(pdata, arg);
default:
/*
 * Let sub-feature's ioctl function to handle the cmd
diff --git a/include/uapi/linux/fpga-dfl.h b/include/uapi/linux/fpga-dfl.h
new file mode 100644
index 000..b46d124
--- /dev/null
+++ b/include/uapi/linux/fpga-dfl.h
@@ -0,0 +1,50 @@
+/*
+ * Header File for FPGA DFL User API
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Zhang Yi 
+ *   Wu Hao 
+ *   Xiao Guangrong 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _UAPI_LINUX_FPGA_DFL_H
+#define _UAPI_LINUX_FPGA_DFL_H
+
+#define FPGA_API_VERSION 0
+
+/*
+ * The IOCTL interface for DFL based FPGA is designed for extensibility by
+ * embedding the structure length (argsz) and flags into structures passed
+ * between kernel and userspace. This design referenced the VFIO IOCTL
+ * interface (include/uapi/linux/vfio.h).
+ */
+
+#define FPGA_MAGIC 0xB6
+
+#define FPGA_BASE 0
+
+/**
+ * FPGA_GET_API_VERSION - _IO(FPGA_MAGIC, FPGA_BASE + 0)
+ *
+ * Report the version of the driver API.
+ * Return: Driver API Version.
+ */
+
+#define FPGA_GET_API_VERSION   _IO(FPGA_MAGIC, FPGA_BASE + 0)
+
+/**
+ * FPGA_CHECK_EXTENSION - _IO(FPGA_MAGIC, FPGA_BASE + 1)
+ *
+ * Check whether an extension is supported.
+ * Return: 0 if not supported, otherwise the extension is supported.
+ */
+
+#define FPGA_CHECK_EXTENSION   _IO(FPGA_MAGIC, FPGA_BASE + 1)
+
+#endif /* _UAPI_LINUX_FPGA_DFL_H */
-- 
1.8.3.1



[PATCH v3 16/21] fpga: dfl: add fpga region platform driver for FME

2017-11-26 Thread Wu Hao
This patch adds fpga region platform driver for FPGA Management Engine.
It register an fpga region with given fpga manager / bridge device.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Wu Hao 

v3: rename driver to fpga-dfl-fme-region
fix fpga_mgr_put order problem in remove function.
rebased due to fpga api changes.
---
 drivers/fpga/Kconfig   |  6 +++
 drivers/fpga/Makefile  |  1 +
 drivers/fpga/fpga-dfl-fme-region.c | 92 ++
 3 files changed, 99 insertions(+)
 create mode 100644 drivers/fpga/fpga-dfl-fme-region.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 3804064..2df9dfd 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -162,6 +162,12 @@ config FPGA_DFL_FME_BRIDGE
help
  Say Y to enable FPGA Bridge driver for FPGA Management Engine.
 
+config FPGA_DFL_FME_REGION
+   tristate "FPGA DFL FME Region Driver"
+   depends on FPGA_DFL_FME
+   help
+ Say Y to enable FPGA Region driver for FPGA Management Engine.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 3c8c4c7..11777d3 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_FPGA_DFL)+= fpga-dfl.o
 obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
 obj-$(CONFIG_FPGA_DFL_FME_MGR) += fpga-dfl-fme-mgr.o
 obj-$(CONFIG_FPGA_DFL_FME_BRIDGE)  += fpga-dfl-fme-br.o
+obj-$(CONFIG_FPGA_DFL_FME_REGION)  += fpga-dfl-fme-region.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
 
diff --git a/drivers/fpga/fpga-dfl-fme-region.c 
b/drivers/fpga/fpga-dfl-fme-region.c
new file mode 100644
index 000..0b988ab
--- /dev/null
+++ b/drivers/fpga/fpga-dfl-fme-region.c
@@ -0,0 +1,92 @@
+/*
+ * FPGA Region Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Wu Hao 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "fpga-dfl.h"
+#include "dfl-fme.h"
+
+static int fme_region_get_bridges(struct fpga_region *region)
+{
+   struct fme_region_pdata *pdata = region->priv;
+   struct device *dev = >br->dev;
+
+   return fpga_bridge_get_to_list(dev, region->info, >bridge_list);
+}
+
+static int fme_region_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct fme_region_pdata *pdata = dev_get_platdata(dev);
+   struct fpga_region *region;
+   struct fpga_manager *mgr;
+   int ret;
+
+   mgr = fpga_mgr_get(>mgr->dev);
+   if (IS_ERR(mgr))
+   return -EPROBE_DEFER;
+
+   region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
+   if (!region) {
+   ret = -ENOMEM;
+   goto eprobe_mgr_put;
+   }
+
+   region->mgr = mgr;
+   region->get_bridges = fme_region_get_bridges;
+   region->priv = pdata;
+   region->parent = dev;
+   platform_set_drvdata(pdev, region);
+
+   ret = fpga_region_register(region);
+   if (ret)
+   goto eprobe_mgr_put;
+
+   dev_dbg(dev, "DFL FME FPGA Region probed\n");
+
+   return 0;
+
+eprobe_mgr_put:
+   fpga_mgr_put(mgr);
+   return ret;
+}
+
+static int fme_region_remove(struct platform_device *pdev)
+{
+   struct fpga_region *region = dev_get_drvdata(>dev);
+
+   fpga_region_unregister(region);
+   fpga_mgr_put(region->mgr);
+
+   return 0;
+}
+
+static struct platform_driver fme_region_driver = {
+   .driver = {
+   .name= FPGA_DFL_FME_REGION,
+   },
+   .probe   = fme_region_probe,
+   .remove  = fme_region_remove,
+};
+
+module_platform_driver(fme_region_driver);
+
+MODULE_DESCRIPTION("FPGA Region for FPGA Management Engine");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:fpga-dfl-fme-region");
-- 
1.8.3.1



[PATCH v3 12/21] fpga: dfl: fme: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls support

2017-11-26 Thread Wu Hao
FPGA_GET_API_VERSION and FPGA_CHECK_EXTENSION ioctls are common ones which
need to be supported by all feature devices drivers including FME and AFU.
Userspace application can use these ioctl interfaces to get the API info
and check if specific extension is supported or not in current driver.

This patch implements above 2 ioctls in FPGA Management Engine (FME)
driver.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: switched to GPLv2 license.
v3: rename intel-fpga.h to fpga-dfl.h and rebased.
---
 Documentation/ioctl/ioctl-number.txt |  1 +
 drivers/fpga/dfl-fme-main.c  | 12 +
 include/uapi/linux/fpga-dfl.h| 50 
 3 files changed, 63 insertions(+)
 create mode 100644 include/uapi/linux/fpga-dfl.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 3e3fdae..91ad573 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -324,6 +324,7 @@ Code  Seq#(hex) Include FileComments
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h
 0xB5   00-0F   uapi/linux/rpmsg.h  

+0xB6   all linux/fpga-dfl.h
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-BF   uapi/scsi/cxlflash_ioctl.h
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index d17c66a..b4e0b54 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -18,6 +18,7 @@
 
 #include 
 #include 
+#include 
 
 #include "fpga-dfl.h"
 
@@ -108,6 +109,13 @@ static void fme_hdr_uinit(struct platform_device *pdev, 
struct feature *feature)
},
 };
 
+static long fme_ioctl_check_extension(struct feature_platform_data *pdata,
+ unsigned long arg)
+{
+   /* No extension support for now */
+   return 0;
+}
+
 static int fme_open(struct inode *inode, struct file *filp)
 {
struct platform_device *fdev = fpga_inode_to_feature_dev(inode);
@@ -148,6 +156,10 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, 
unsigned long arg)
dev_dbg(>dev, "%s cmd 0x%x\n", __func__, cmd);
 
switch (cmd) {
+   case FPGA_GET_API_VERSION:
+   return FPGA_API_VERSION;
+   case FPGA_CHECK_EXTENSION:
+   return fme_ioctl_check_extension(pdata, arg);
default:
/*
 * Let sub-feature's ioctl function to handle the cmd
diff --git a/include/uapi/linux/fpga-dfl.h b/include/uapi/linux/fpga-dfl.h
new file mode 100644
index 000..b46d124
--- /dev/null
+++ b/include/uapi/linux/fpga-dfl.h
@@ -0,0 +1,50 @@
+/*
+ * Header File for FPGA DFL User API
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Zhang Yi 
+ *   Wu Hao 
+ *   Xiao Guangrong 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _UAPI_LINUX_FPGA_DFL_H
+#define _UAPI_LINUX_FPGA_DFL_H
+
+#define FPGA_API_VERSION 0
+
+/*
+ * The IOCTL interface for DFL based FPGA is designed for extensibility by
+ * embedding the structure length (argsz) and flags into structures passed
+ * between kernel and userspace. This design referenced the VFIO IOCTL
+ * interface (include/uapi/linux/vfio.h).
+ */
+
+#define FPGA_MAGIC 0xB6
+
+#define FPGA_BASE 0
+
+/**
+ * FPGA_GET_API_VERSION - _IO(FPGA_MAGIC, FPGA_BASE + 0)
+ *
+ * Report the version of the driver API.
+ * Return: Driver API Version.
+ */
+
+#define FPGA_GET_API_VERSION   _IO(FPGA_MAGIC, FPGA_BASE + 0)
+
+/**
+ * FPGA_CHECK_EXTENSION - _IO(FPGA_MAGIC, FPGA_BASE + 1)
+ *
+ * Check whether an extension is supported.
+ * Return: 0 if not supported, otherwise the extension is supported.
+ */
+
+#define FPGA_CHECK_EXTENSION   _IO(FPGA_MAGIC, FPGA_BASE + 1)
+
+#endif /* _UAPI_LINUX_FPGA_DFL_H */
-- 
1.8.3.1



[PATCH v3 18/21] fpga: dfl: afu: add header sub feature support

2017-11-26 Thread Wu Hao
The port header register set is always present for port, it is mainly
for capability, control and status of the ports that AFU connected to.

This patch implements header sub feature support. Below user interfaces
are created by this patch.

Sysfs interface:
* /sys/class/fpga_region///id
  Read-only. Port ID.

Ioctl interface:
* FPGA_PORT_RESET
  Reset the FPGA Port and its AFU.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: rename driver name to fpga-dfl-afu
add more description for reset ioctl.
fix some checkpatch issues.
---
 .../ABI/testing/sysfs-platform-fpga-dfl-afu|  7 
 drivers/fpga/dfl-afu-main.c| 44 +-
 include/uapi/linux/fpga-dfl.h  | 17 +
 3 files changed, 67 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
new file mode 100644
index 000..f4bcd94
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
@@ -0,0 +1,7 @@
+What:  /sys/bus/platform/devices/fpga-dfl-port.0/id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns id of this port. One DFL FPGA device
+   may have more than one port. Userspace could use this id to
+   distinguish different ports under same FPGA device.
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index d9f4b81..b01376c 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -18,25 +18,66 @@
 
 #include 
 #include 
+#include 
 
 #include "fpga-dfl.h"
 
+static ssize_t
+id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int id = fpga_port_id(to_platform_device(dev));
+
+   return scnprintf(buf, PAGE_SIZE, "%d\n", id);
+}
+static DEVICE_ATTR_RO(id);
+
+static const struct attribute *port_hdr_attrs[] = {
+   _attr_id.attr,
+   NULL,
+};
+
 static int port_hdr_init(struct platform_device *pdev, struct feature *feature)
 {
dev_dbg(>dev, "PORT HDR Init.\n");
 
-   return 0;
+   fpga_port_reset(pdev);
+
+   return sysfs_create_files(>dev.kobj, port_hdr_attrs);
 }
 
 static void port_hdr_uinit(struct platform_device *pdev,
   struct feature *feature)
 {
dev_dbg(>dev, "PORT HDR UInit.\n");
+
+   sysfs_remove_files(>dev.kobj, port_hdr_attrs);
+}
+
+static long
+port_hdr_ioctl(struct platform_device *pdev, struct feature *feature,
+  unsigned int cmd, unsigned long arg)
+{
+   long ret;
+
+   switch (cmd) {
+   case FPGA_PORT_RESET:
+   if (!arg)
+   ret = fpga_port_reset(pdev);
+   else
+   ret = -EINVAL;
+   break;
+   default:
+   dev_dbg(>dev, "%x cmd not handled", cmd);
+   ret = -ENODEV;
+   }
+
+   return ret;
 }
 
 static const struct feature_ops port_hdr_ops = {
.init = port_hdr_init,
.uinit = port_hdr_uinit,
+   .ioctl = port_hdr_ioctl,
 };
 
 static struct feature_driver port_feature_drvs[] = {
@@ -76,6 +117,7 @@ static int afu_release(struct inode *inode, struct file 
*filp)
 
dev_dbg(>dev, "Device File Release\n");
 
+   fpga_port_reset(pdev);
feature_dev_use_end(pdata);
 
return 0;
diff --git a/include/uapi/linux/fpga-dfl.h b/include/uapi/linux/fpga-dfl.h
index 75bdf88..9bf273d 100644
--- a/include/uapi/linux/fpga-dfl.h
+++ b/include/uapi/linux/fpga-dfl.h
@@ -30,8 +30,11 @@
 #define FPGA_MAGIC 0xB6
 
 #define FPGA_BASE 0
+#define PORT_BASE 0x40
 #define FME_BASE 0x80
 
+/* Common IOCTLs for both FME and AFU file descriptor */
+
 /**
  * FPGA_GET_API_VERSION - _IO(FPGA_MAGIC, FPGA_BASE + 0)
  *
@@ -50,6 +53,20 @@
 
 #define FPGA_CHECK_EXTENSION   _IO(FPGA_MAGIC, FPGA_BASE + 1)
 
+/* IOCTLs for AFU file descriptor */
+
+/**
+ * FPGA_PORT_RESET - _IO(FPGA_MAGIC, PORT_BASE + 0)
+ *
+ * Reset the FPGA Port and its AFU. No parameters are supported.
+ * Userspace can do Port reset at any time, e.g during DMA or PR. But
+ * it should never cause any system level issue, only functional failure
+ * (e.g DMA or PR operation failure) and be recoverable from the failure.
+ * Return: 0 on success, -errno of failure
+ */
+
+#define FPGA_PORT_RESET_IO(FPGA_MAGIC, PORT_BASE + 0)
+
 /* IOCTLs for FME file descriptor */
 
 /**
-- 
1.8.3.1



[PATCH v3 20/21] fpga: dfl: afu: add user afu sub feature support

2017-11-26 Thread Wu Hao
From: Xiao Guangrong 

User Accelerated Function Unit sub feature exposes the MMIO region of
the AFU. After valid green bitstream (GBS) is programmed and port is
enabled, then this MMIO region could be accessed.

This patch adds support to enumerate the AFU MMIO region and expose it
to userspace via mmap file operation. Below interfaces are exposed to user:

Sysfs interface:
* /sys/class/fpga_region///afu_id
  Read-only. Indicate which green bitstream is programmed to this AFU.

Ioctl interfaces:
* FPGA_PORT_GET_INFO
  Provide info to userspace on the number of supported region.
  Only UAFU region is supported now.

* FPGA_PORT_GET_REGION_INFO
  Provide region information, including access permission, region size,
  offset from the start of device fd.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 
--
v2: moved the code to drivers/fpga folder as suggested by Alan Tull.
add sysfs documentation.
switched to GPLv2 license.
v3: rename driver to fpga-dfl-afu
fix coding style and checkpatch issue.
only allow afu_id to be read when port isn't in reset.
---
 .../ABI/testing/sysfs-platform-fpga-dfl-afu|   9 +
 drivers/fpga/Makefile  |   2 +-
 drivers/fpga/dfl-afu-main.c| 211 -
 drivers/fpga/dfl-afu-region.c  | 127 +
 drivers/fpga/dfl-afu.h |  54 ++
 include/uapi/linux/fpga-dfl.h  |  47 +
 6 files changed, 446 insertions(+), 4 deletions(-)
 create mode 100644 drivers/fpga/dfl-afu-region.c
 create mode 100644 drivers/fpga/dfl-afu.h

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
index f4bcd94..54bcfad 100644
--- a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
@@ -5,3 +5,12 @@ Contact:   Wu Hao 
 Description:   Read-only. It returns id of this port. One DFL FPGA device
may have more than one port. Userspace could use this id to
distinguish different ports under same FPGA device.
+
+What:  /sys/bus/platform/devices/fpga-dfl-port.0/afu_id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. User can program different green bitstreams (GBS) to
+   FPGA Accelerator Function Unit (AFU) for different functions.
+   It returns uuid which could be used to identify which GBS is
+   programmed in this AFU.
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index e234fa8..f0dd09f 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_FPGA_DFL_FME_REGION) += fpga-dfl-fme-region.o
 obj-$(CONFIG_FPGA_DFL_AFU) += fpga-dfl-afu.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
-fpga-dfl-afu-objs := dfl-afu-main.o
+fpga-dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_INTEL_FPGA_DFL_PCI)   += intel-dfl-pci.o
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index d3d534c..ca37a51 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -18,9 +18,10 @@
 
 #include 
 #include 
+#include 
 #include 
 
-#include "fpga-dfl.h"
+#include "dfl-afu.h"
 
 static ssize_t
 id_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -80,12 +81,74 @@ static void port_hdr_uinit(struct platform_device *pdev,
.ioctl = port_hdr_ioctl,
 };
 
+static ssize_t
+afu_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct feature_platform_data *pdata = dev_get_platdata(dev);
+   void __iomem *base;
+   u64 guidl, guidh;
+
+   base = get_feature_ioaddr_by_index(dev, PORT_FEATURE_ID_UAFU);
+
+   mutex_lock(>lock);
+   if (pdata->disable_count) {
+   mutex_unlock(>lock);
+   return -EBUSY;
+   }
+
+   guidl = readq(base + GUID_L);
+   guidh = readq(base + GUID_H);
+   mutex_unlock(>lock);
+
+   return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n", guidh, guidl);
+}
+static DEVICE_ATTR_RO(afu_id);
+
+static const struct attribute *port_uafu_attrs[] = {
+   _attr_afu_id.attr,
+   NULL
+};
+
+static int port_uafu_init(struct platform_device *pdev, struct feature 
*feature)
+{
+   struct resource *res = >resource[feature->resource_index];
+   u32 flags = FPGA_REGION_READ | FPGA_REGION_WRITE | FPGA_REGION_MMAP;
+   int ret;
+
+   dev_dbg(>dev, "PORT AFU Init.\n");
+
+

[PATCH v3 20/21] fpga: dfl: afu: add user afu sub feature support

2017-11-26 Thread Wu Hao
From: Xiao Guangrong 

User Accelerated Function Unit sub feature exposes the MMIO region of
the AFU. After valid green bitstream (GBS) is programmed and port is
enabled, then this MMIO region could be accessed.

This patch adds support to enumerate the AFU MMIO region and expose it
to userspace via mmap file operation. Below interfaces are exposed to user:

Sysfs interface:
* /sys/class/fpga_region///afu_id
  Read-only. Indicate which green bitstream is programmed to this AFU.

Ioctl interfaces:
* FPGA_PORT_GET_INFO
  Provide info to userspace on the number of supported region.
  Only UAFU region is supported now.

* FPGA_PORT_GET_REGION_INFO
  Provide region information, including access permission, region size,
  offset from the start of device fd.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 
--
v2: moved the code to drivers/fpga folder as suggested by Alan Tull.
add sysfs documentation.
switched to GPLv2 license.
v3: rename driver to fpga-dfl-afu
fix coding style and checkpatch issue.
only allow afu_id to be read when port isn't in reset.
---
 .../ABI/testing/sysfs-platform-fpga-dfl-afu|   9 +
 drivers/fpga/Makefile  |   2 +-
 drivers/fpga/dfl-afu-main.c| 211 -
 drivers/fpga/dfl-afu-region.c  | 127 +
 drivers/fpga/dfl-afu.h |  54 ++
 include/uapi/linux/fpga-dfl.h  |  47 +
 6 files changed, 446 insertions(+), 4 deletions(-)
 create mode 100644 drivers/fpga/dfl-afu-region.c
 create mode 100644 drivers/fpga/dfl-afu.h

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
index f4bcd94..54bcfad 100644
--- a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-afu
@@ -5,3 +5,12 @@ Contact:   Wu Hao 
 Description:   Read-only. It returns id of this port. One DFL FPGA device
may have more than one port. Userspace could use this id to
distinguish different ports under same FPGA device.
+
+What:  /sys/bus/platform/devices/fpga-dfl-port.0/afu_id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. User can program different green bitstreams (GBS) to
+   FPGA Accelerator Function Unit (AFU) for different functions.
+   It returns uuid which could be used to identify which GBS is
+   programmed in this AFU.
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index e234fa8..f0dd09f 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_FPGA_DFL_FME_REGION) += fpga-dfl-fme-region.o
 obj-$(CONFIG_FPGA_DFL_AFU) += fpga-dfl-afu.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
-fpga-dfl-afu-objs := dfl-afu-main.o
+fpga-dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_INTEL_FPGA_DFL_PCI)   += intel-dfl-pci.o
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index d3d534c..ca37a51 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -18,9 +18,10 @@
 
 #include 
 #include 
+#include 
 #include 
 
-#include "fpga-dfl.h"
+#include "dfl-afu.h"
 
 static ssize_t
 id_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -80,12 +81,74 @@ static void port_hdr_uinit(struct platform_device *pdev,
.ioctl = port_hdr_ioctl,
 };
 
+static ssize_t
+afu_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct feature_platform_data *pdata = dev_get_platdata(dev);
+   void __iomem *base;
+   u64 guidl, guidh;
+
+   base = get_feature_ioaddr_by_index(dev, PORT_FEATURE_ID_UAFU);
+
+   mutex_lock(>lock);
+   if (pdata->disable_count) {
+   mutex_unlock(>lock);
+   return -EBUSY;
+   }
+
+   guidl = readq(base + GUID_L);
+   guidh = readq(base + GUID_H);
+   mutex_unlock(>lock);
+
+   return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n", guidh, guidl);
+}
+static DEVICE_ATTR_RO(afu_id);
+
+static const struct attribute *port_uafu_attrs[] = {
+   _attr_afu_id.attr,
+   NULL
+};
+
+static int port_uafu_init(struct platform_device *pdev, struct feature 
*feature)
+{
+   struct resource *res = >resource[feature->resource_index];
+   u32 flags = FPGA_REGION_READ | FPGA_REGION_WRITE | FPGA_REGION_MMAP;
+   int ret;
+
+   dev_dbg(>dev, "PORT AFU Init.\n");
+
+   ret = afu_region_add(dev_get_platdata(>dev),
+FPGA_PORT_INDEX_UAFU, resource_size(res),
+res->start, flags);
+   if (ret)
+   return ret;
+
+  

Re: [PATCH v2] checkpatch: Add a warning for log messages that don't end in a new line

2017-11-26 Thread Logan Gunthorpe


On 26/11/17 11:42 PM, Julia Lawall wrote:
> Although I guess that in that case the whole exercise is pointless?
> Because every print will at runtime be followed by another print, which
> will add either the newline or a continuation.

Yes, in practice the '\n' at the end of every log line is optional based
on what the code actually does. Nothing bad happens if you omit one. But
reviewers still point out that they are required. (That's what started
me on this mess -- because I'd rather know what the correct thing is
before I commit the code for the first time, and not months after the
code reached mainline.)

The reviewers have a really good point though: if a significant fraction
of the log calls have no new line and a majority have them, then making
any kind of change in this area could break things. Not to mention the
ugliness of the inconsistencies everywhere. Also, the more cases that
are "wrong" that get into the kernel the more it confuses people trying
to learn what the "right" thing is.

Honestly, though, I have no dog in this race. I just thought it would be
useful.

Logan



Re: [PATCH v2] checkpatch: Add a warning for log messages that don't end in a new line

2017-11-26 Thread Logan Gunthorpe


On 26/11/17 11:42 PM, Julia Lawall wrote:
> Although I guess that in that case the whole exercise is pointless?
> Because every print will at runtime be followed by another print, which
> will add either the newline or a continuation.

Yes, in practice the '\n' at the end of every log line is optional based
on what the code actually does. Nothing bad happens if you omit one. But
reviewers still point out that they are required. (That's what started
me on this mess -- because I'd rather know what the correct thing is
before I commit the code for the first time, and not months after the
code reached mainline.)

The reviewers have a really good point though: if a significant fraction
of the log calls have no new line and a majority have them, then making
any kind of change in this area could break things. Not to mention the
ugliness of the inconsistencies everywhere. Also, the more cases that
are "wrong" that get into the kernel the more it confuses people trying
to learn what the "right" thing is.

Honestly, though, I have no dog in this race. I just thought it would be
useful.

Logan



[PATCH v3 19/21] fpga: dfl: afu: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls support

2017-11-26 Thread Wu Hao
FPGA_GET_API_VERSION and FPGA_CHECK_EXTENSION ioctls are common ones which
need to be supported by all feature devices drivers including FME and AFU.
This patch implements above 2 ioctls in FPGA Accelerated Function Unit
(AFU) driver.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: rebased
v3: rebased as driver renamed to fpga-dfl-afu
fix one checkpatch issue
---
 drivers/fpga/dfl-afu-main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index b01376c..d3d534c 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -123,6 +123,13 @@ static int afu_release(struct inode *inode, struct file 
*filp)
return 0;
 }
 
+static long afu_ioctl_check_extension(struct feature_platform_data *pdata,
+ unsigned long arg)
+{
+   /* No extension support for now */
+   return 0;
+}
+
 static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
struct platform_device *pdev = filp->private_data;
@@ -133,6 +140,10 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, 
unsigned long arg)
dev_dbg(>dev, "%s cmd 0x%x\n", __func__, cmd);
 
switch (cmd) {
+   case FPGA_GET_API_VERSION:
+   return FPGA_API_VERSION;
+   case FPGA_CHECK_EXTENSION:
+   return afu_ioctl_check_extension(pdata, arg);
default:
/*
 * Let sub-feature's ioctl function to handle the cmd
-- 
1.8.3.1



[PATCH v3 14/21] fpga: dfl: add fpga manager platform driver for FME

2017-11-26 Thread Wu Hao
This patch adds fpga manager driver for FPGA Management Engine (FME). It
implements fpga_manager_ops for FPGA Partial Reconfiguration function.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: rename driver to dfl-fpga-fme-mgr
implemented status callback for fpga manager
rebased due to fpga api changes
---
 .../ABI/testing/sysfs-platform-fpga-dfl-fme-mgr|   8 +
 drivers/fpga/Kconfig   |   6 +
 drivers/fpga/Makefile  |   1 +
 drivers/fpga/fpga-dfl-fme-mgr.c| 318 +
 drivers/fpga/fpga-dfl.h|  39 ++-
 5 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr
 create mode 100644 drivers/fpga/fpga-dfl-fme-mgr.c

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr
new file mode 100644
index 000..2d4f917
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr
@@ -0,0 +1,8 @@
+What:  /sys/bus/platform/devices/fpga-dfl-fme-mgr.0/interface_id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns interface id of partial reconfiguration
+   hardware. Userspace could use this information to check if
+   current hardware is compatible with given image before FPGA
+   programming.
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 57da904..0171ecb 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -150,6 +150,12 @@ config FPGA_DFL_FME
  FPGA platform level management features. There shall be 1 FME
  per DFL based FPGA device.
 
+config FPGA_DFL_FME_MGR
+   tristate "FPGA DFL FME Manager Driver"
+   depends on FPGA_DFL_FME
+   help
+ Say Y to enable FPGA Manager driver for FPGA Management Engine.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index cc75bb3..6378580 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_OF_FPGA_REGION)  += of-fpga-region.o
 # FPGA Device Feature List Support
 obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
 obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
+obj-$(CONFIG_FPGA_DFL_FME_MGR) += fpga-dfl-fme-mgr.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
 
diff --git a/drivers/fpga/fpga-dfl-fme-mgr.c b/drivers/fpga/fpga-dfl-fme-mgr.c
new file mode 100644
index 000..70356ce
--- /dev/null
+++ b/drivers/fpga/fpga-dfl-fme-mgr.c
@@ -0,0 +1,318 @@
+/*
+ * FPGA Manager Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Xiao Guangrong 
+ *   Wu Hao 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Christopher Rauer 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+
+#include "fpga-dfl.h"
+#include "dfl-fme.h"
+
+#define PR_WAIT_TIMEOUT   800
+#define PR_HOST_STATUS_IDLE0
+
+struct fme_mgr_priv {
+   void __iomem *ioaddr;
+   u64 pr_error;
+};
+
+static ssize_t interface_id_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct fpga_manager *mgr = dev_get_drvdata(dev);
+   struct fme_mgr_priv *priv = mgr->priv;
+   u64 intfc_id_l, intfc_id_h;
+
+   intfc_id_l = readq(priv->ioaddr + FME_PR_INTFC_ID_L);
+   intfc_id_h = readq(priv->ioaddr + FME_PR_INTFC_ID_H);
+
+   return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n",
+   (unsigned long long)intfc_id_h,
+   (unsigned long long)intfc_id_l);
+}
+static DEVICE_ATTR_RO(interface_id);
+
+static const struct attribute *fme_mgr_attrs[] = {
+   _attr_interface_id.attr,
+   NULL,
+};
+
+static u64 pr_error_to_mgr_status(u64 err)
+{
+   u64 status = 0;
+
+   if (err & FME_PR_ERR_OPERATION_ERR)
+   status |= FPGA_MGR_STATUS_OPERATION_ERR;
+   if (err & FME_PR_ERR_CRC_ERR)
+   status |= 

[PATCH v3 19/21] fpga: dfl: afu: add FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls support

2017-11-26 Thread Wu Hao
FPGA_GET_API_VERSION and FPGA_CHECK_EXTENSION ioctls are common ones which
need to be supported by all feature devices drivers including FME and AFU.
This patch implements above 2 ioctls in FPGA Accelerated Function Unit
(AFU) driver.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: rebased
v3: rebased as driver renamed to fpga-dfl-afu
fix one checkpatch issue
---
 drivers/fpga/dfl-afu-main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index b01376c..d3d534c 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -123,6 +123,13 @@ static int afu_release(struct inode *inode, struct file 
*filp)
return 0;
 }
 
+static long afu_ioctl_check_extension(struct feature_platform_data *pdata,
+ unsigned long arg)
+{
+   /* No extension support for now */
+   return 0;
+}
+
 static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
struct platform_device *pdev = filp->private_data;
@@ -133,6 +140,10 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, 
unsigned long arg)
dev_dbg(>dev, "%s cmd 0x%x\n", __func__, cmd);
 
switch (cmd) {
+   case FPGA_GET_API_VERSION:
+   return FPGA_API_VERSION;
+   case FPGA_CHECK_EXTENSION:
+   return afu_ioctl_check_extension(pdata, arg);
default:
/*
 * Let sub-feature's ioctl function to handle the cmd
-- 
1.8.3.1



[PATCH v3 14/21] fpga: dfl: add fpga manager platform driver for FME

2017-11-26 Thread Wu Hao
This patch adds fpga manager driver for FPGA Management Engine (FME). It
implements fpga_manager_ops for FPGA Partial Reconfiguration function.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Kang Luwei 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v3: rename driver to dfl-fpga-fme-mgr
implemented status callback for fpga manager
rebased due to fpga api changes
---
 .../ABI/testing/sysfs-platform-fpga-dfl-fme-mgr|   8 +
 drivers/fpga/Kconfig   |   6 +
 drivers/fpga/Makefile  |   1 +
 drivers/fpga/fpga-dfl-fme-mgr.c| 318 +
 drivers/fpga/fpga-dfl.h|  39 ++-
 5 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr
 create mode 100644 drivers/fpga/fpga-dfl-fme-mgr.c

diff --git a/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr 
b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr
new file mode 100644
index 000..2d4f917
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-fpga-dfl-fme-mgr
@@ -0,0 +1,8 @@
+What:  /sys/bus/platform/devices/fpga-dfl-fme-mgr.0/interface_id
+Date:  November 2017
+KernelVersion:  4.15
+Contact:   Wu Hao 
+Description:   Read-only. It returns interface id of partial reconfiguration
+   hardware. Userspace could use this information to check if
+   current hardware is compatible with given image before FPGA
+   programming.
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 57da904..0171ecb 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -150,6 +150,12 @@ config FPGA_DFL_FME
  FPGA platform level management features. There shall be 1 FME
  per DFL based FPGA device.
 
+config FPGA_DFL_FME_MGR
+   tristate "FPGA DFL FME Manager Driver"
+   depends on FPGA_DFL_FME
+   help
+ Say Y to enable FPGA Manager driver for FPGA Management Engine.
+
 config INTEL_FPGA_DFL_PCI
tristate "Intel FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index cc75bb3..6378580 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_OF_FPGA_REGION)  += of-fpga-region.o
 # FPGA Device Feature List Support
 obj-$(CONFIG_FPGA_DFL) += fpga-dfl.o
 obj-$(CONFIG_FPGA_DFL_FME) += fpga-dfl-fme.o
+obj-$(CONFIG_FPGA_DFL_FME_MGR) += fpga-dfl-fme-mgr.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
 
diff --git a/drivers/fpga/fpga-dfl-fme-mgr.c b/drivers/fpga/fpga-dfl-fme-mgr.c
new file mode 100644
index 000..70356ce
--- /dev/null
+++ b/drivers/fpga/fpga-dfl-fme-mgr.c
@@ -0,0 +1,318 @@
+/*
+ * FPGA Manager Driver for FPGA Management Engine (FME)
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Kang Luwei 
+ *   Xiao Guangrong 
+ *   Wu Hao 
+ *   Joseph Grecco 
+ *   Enno Luebbers 
+ *   Tim Whisonant 
+ *   Ananda Ravuri 
+ *   Christopher Rauer 
+ *   Henry Mitchel 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+
+#include "fpga-dfl.h"
+#include "dfl-fme.h"
+
+#define PR_WAIT_TIMEOUT   800
+#define PR_HOST_STATUS_IDLE0
+
+struct fme_mgr_priv {
+   void __iomem *ioaddr;
+   u64 pr_error;
+};
+
+static ssize_t interface_id_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct fpga_manager *mgr = dev_get_drvdata(dev);
+   struct fme_mgr_priv *priv = mgr->priv;
+   u64 intfc_id_l, intfc_id_h;
+
+   intfc_id_l = readq(priv->ioaddr + FME_PR_INTFC_ID_L);
+   intfc_id_h = readq(priv->ioaddr + FME_PR_INTFC_ID_H);
+
+   return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n",
+   (unsigned long long)intfc_id_h,
+   (unsigned long long)intfc_id_l);
+}
+static DEVICE_ATTR_RO(interface_id);
+
+static const struct attribute *fme_mgr_attrs[] = {
+   _attr_interface_id.attr,
+   NULL,
+};
+
+static u64 pr_error_to_mgr_status(u64 err)
+{
+   u64 status = 0;
+
+   if (err & FME_PR_ERR_OPERATION_ERR)
+   status |= FPGA_MGR_STATUS_OPERATION_ERR;
+   if (err & FME_PR_ERR_CRC_ERR)
+   status |= FPGA_MGR_STATUS_CRC_ERR;
+   if (err & FME_PR_ERR_INCOMPATIBLE_BS)
+   status |= FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR;
+   if (err & FME_PR_ERR_PROTOCOL_ERR)
+   status |= FPGA_MGR_STATUS_IP_PROTOCOL_ERR;
+   if (err & FME_PR_ERR_FIFO_OVERFLOW)
+   status |= FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR;
+
+   return status;
+}
+
+static u64 fme_mgr_pr_error_handle(void __iomem *fme_pr)
+{
+ 

[PATCH v3 21/21] fpga: dfl: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support

2017-11-26 Thread Wu Hao
DMA memory regions are required for Accelerated Function Unit (AFU) usage.
These two ioctls allow user space applications to map user memory regions
for dma, and unmap them after use. Iova is returned from driver to user
space application via FPGA_PORT_DMA_MAP ioctl. Application needs to unmap
it after use, otherwise, driver will unmap them in device file release
operation.

Each AFU has its own rb tree to keep track of its mapped DMA regions.

Ioctl interfaces:
* FPGA_PORT_DMA_MAP
  Do the dma mapping per user_addr and length which provided by user.
  Return iova in provided struct afu_port_dma_map.

* FPGA_PORT_DMA_UNMAP
  Unmap the dma region per iova provided by user.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 
-
v2: moved the code to drivers/fpga folder as suggested by Alan Tull.
switched to GPLv2 license.
fixed kbuild warnings.
v3: improved commit description and fixed coding style issues.
replaced fpga_pdata_to_pcidev with fpga_pdata_to_fpga_cdev
---
 drivers/fpga/Makefile |   2 +-
 drivers/fpga/dfl-afu-dma-region.c | 465 ++
 drivers/fpga/dfl-afu-main.c   |  61 -
 drivers/fpga/dfl-afu.h|  18 ++
 include/uapi/linux/fpga-dfl.h |  37 +++
 5 files changed, 581 insertions(+), 2 deletions(-)
 create mode 100644 drivers/fpga/dfl-afu-dma-region.c

diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index f0dd09f..5715a78 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_FPGA_DFL_FME_REGION) += fpga-dfl-fme-region.o
 obj-$(CONFIG_FPGA_DFL_AFU) += fpga-dfl-afu.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
-fpga-dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o
+fpga-dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_INTEL_FPGA_DFL_PCI)   += intel-dfl-pci.o
diff --git a/drivers/fpga/dfl-afu-dma-region.c 
b/drivers/fpga/dfl-afu-dma-region.c
new file mode 100644
index 000..7b246bb
--- /dev/null
+++ b/drivers/fpga/dfl-afu-dma-region.c
@@ -0,0 +1,465 @@
+/*
+ * Driver for FPGA Accelerated Function Unit (AFU) DMA Region Management
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Wu Hao 
+ *   Xiao Guangrong 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+
+#include "dfl-afu.h"
+
+static void put_all_pages(struct page **pages, int npages)
+{
+   int i;
+
+   for (i = 0; i < npages; i++)
+   if (pages[i])
+   put_page(pages[i]);
+}
+
+void afu_dma_region_init(struct feature_platform_data *pdata)
+{
+   struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+
+   afu->dma_regions = RB_ROOT;
+}
+
+/**
+ * afu_dma_adjust_locked_vm - adjust locked memory
+ * @dev: port device
+ * @npages: number of pages
+ * @incr: increase or decrease locked memory
+ *
+ * Increase or decrease the locked memory size with npages input.
+ *
+ * Return 0 on success.
+ * Return -ENOMEM if locked memory size is over the limit and no CAP_IPC_LOCK.
+ */
+static int afu_dma_adjust_locked_vm(struct device *dev, long npages, bool incr)
+{
+   unsigned long locked, lock_limit;
+   int ret = 0;
+
+   /* the task is exiting. */
+   if (!current->mm)
+   return 0;
+
+   down_write(>mm->mmap_sem);
+
+   if (incr) {
+   locked = current->mm->locked_vm + npages;
+   lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+   if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+   ret = -ENOMEM;
+   else
+   current->mm->locked_vm += npages;
+   } else {
+   if (WARN_ON_ONCE(npages > current->mm->locked_vm))
+   npages = current->mm->locked_vm;
+   current->mm->locked_vm -= npages;
+   }
+
+   dev_dbg(dev, "[%d] RLIMIT_MEMLOCK %c%ld %ld/%ld%s\n", current->pid,
+   incr ? '+' : '-', npages << PAGE_SHIFT,
+   current->mm->locked_vm << PAGE_SHIFT, rlimit(RLIMIT_MEMLOCK),
+   ret ? "- execeeded" : "");
+
+   up_write(>mm->mmap_sem);
+
+   return ret;
+}
+
+/**
+ * afu_dma_pin_pages - pin pages of given dma memory region
+ * @pdata: feature device platform data
+ * @region: dma memory region to be pinned
+ *
+ * Pin all the pages of given fpga_afu_dma_region.
+ * Return 0 for success or negative error code.
+ */
+static int afu_dma_pin_pages(struct feature_platform_data *pdata,
+

[PATCH v3 21/21] fpga: dfl: afu: add FPGA_PORT_DMA_MAP/UNMAP ioctls support

2017-11-26 Thread Wu Hao
DMA memory regions are required for Accelerated Function Unit (AFU) usage.
These two ioctls allow user space applications to map user memory regions
for dma, and unmap them after use. Iova is returned from driver to user
space application via FPGA_PORT_DMA_MAP ioctl. Application needs to unmap
it after use, otherwise, driver will unmap them in device file release
operation.

Each AFU has its own rb tree to keep track of its mapped DMA regions.

Ioctl interfaces:
* FPGA_PORT_DMA_MAP
  Do the dma mapping per user_addr and length which provided by user.
  Return iova in provided struct afu_port_dma_map.

* FPGA_PORT_DMA_UNMAP
  Unmap the dma region per iova provided by user.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 
-
v2: moved the code to drivers/fpga folder as suggested by Alan Tull.
switched to GPLv2 license.
fixed kbuild warnings.
v3: improved commit description and fixed coding style issues.
replaced fpga_pdata_to_pcidev with fpga_pdata_to_fpga_cdev
---
 drivers/fpga/Makefile |   2 +-
 drivers/fpga/dfl-afu-dma-region.c | 465 ++
 drivers/fpga/dfl-afu-main.c   |  61 -
 drivers/fpga/dfl-afu.h|  18 ++
 include/uapi/linux/fpga-dfl.h |  37 +++
 5 files changed, 581 insertions(+), 2 deletions(-)
 create mode 100644 drivers/fpga/dfl-afu-dma-region.c

diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index f0dd09f..5715a78 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_FPGA_DFL_FME_REGION) += fpga-dfl-fme-region.o
 obj-$(CONFIG_FPGA_DFL_AFU) += fpga-dfl-afu.o
 
 fpga-dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
-fpga-dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o
+fpga-dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_INTEL_FPGA_DFL_PCI)   += intel-dfl-pci.o
diff --git a/drivers/fpga/dfl-afu-dma-region.c 
b/drivers/fpga/dfl-afu-dma-region.c
new file mode 100644
index 000..7b246bb
--- /dev/null
+++ b/drivers/fpga/dfl-afu-dma-region.c
@@ -0,0 +1,465 @@
+/*
+ * Driver for FPGA Accelerated Function Unit (AFU) DMA Region Management
+ *
+ * Copyright (C) 2017 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Wu Hao 
+ *   Xiao Guangrong 
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+
+#include "dfl-afu.h"
+
+static void put_all_pages(struct page **pages, int npages)
+{
+   int i;
+
+   for (i = 0; i < npages; i++)
+   if (pages[i])
+   put_page(pages[i]);
+}
+
+void afu_dma_region_init(struct feature_platform_data *pdata)
+{
+   struct fpga_afu *afu = fpga_pdata_get_private(pdata);
+
+   afu->dma_regions = RB_ROOT;
+}
+
+/**
+ * afu_dma_adjust_locked_vm - adjust locked memory
+ * @dev: port device
+ * @npages: number of pages
+ * @incr: increase or decrease locked memory
+ *
+ * Increase or decrease the locked memory size with npages input.
+ *
+ * Return 0 on success.
+ * Return -ENOMEM if locked memory size is over the limit and no CAP_IPC_LOCK.
+ */
+static int afu_dma_adjust_locked_vm(struct device *dev, long npages, bool incr)
+{
+   unsigned long locked, lock_limit;
+   int ret = 0;
+
+   /* the task is exiting. */
+   if (!current->mm)
+   return 0;
+
+   down_write(>mm->mmap_sem);
+
+   if (incr) {
+   locked = current->mm->locked_vm + npages;
+   lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+   if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+   ret = -ENOMEM;
+   else
+   current->mm->locked_vm += npages;
+   } else {
+   if (WARN_ON_ONCE(npages > current->mm->locked_vm))
+   npages = current->mm->locked_vm;
+   current->mm->locked_vm -= npages;
+   }
+
+   dev_dbg(dev, "[%d] RLIMIT_MEMLOCK %c%ld %ld/%ld%s\n", current->pid,
+   incr ? '+' : '-', npages << PAGE_SHIFT,
+   current->mm->locked_vm << PAGE_SHIFT, rlimit(RLIMIT_MEMLOCK),
+   ret ? "- execeeded" : "");
+
+   up_write(>mm->mmap_sem);
+
+   return ret;
+}
+
+/**
+ * afu_dma_pin_pages - pin pages of given dma memory region
+ * @pdata: feature device platform data
+ * @region: dma memory region to be pinned
+ *
+ * Pin all the pages of given fpga_afu_dma_region.
+ * Return 0 for success or negative error code.
+ */
+static int afu_dma_pin_pages(struct feature_platform_data *pdata,
+struct fpga_afu_dma_region *region)
+{
+   int npages = region->length >> PAGE_SHIFT;
+   struct device *dev = >dev->dev;
+   int ret, pinned;
+
+   ret = afu_dma_adjust_locked_vm(dev, 

[PATCH v3 03/21] fpga: mgr: add status for fpga-manager

2017-11-26 Thread Wu Hao
This patch adds status to fpga-manager data structure, to allow
driver to store full/partial reconfiguration errors and other
status information, and adds one status callback to fpga_manager_ops
to allow fpga_manager to collect latest status when failures are
detected.

The following sysfs file is created:
* /sys/class/fpga_manager//status
  Return status of fpga manager, including reconfiguration errors.

Signed-off-by: Wu Hao 

v3: add one line description for status
add status callback function to fpga_manager_ops
update fpga-mgr status if any failure or during initialization
s/INCOMPATIBLE_BS_ERR/INCOMPATIBLE_IMAGE_ERR/
---
 Documentation/ABI/testing/sysfs-class-fpga-manager | 10 
 drivers/fpga/fpga-mgr.c| 28 ++
 include/linux/fpga/fpga-mgr.h  | 17 +
 3 files changed, 55 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-manager 
b/Documentation/ABI/testing/sysfs-class-fpga-manager
index 23056c5..01db14d 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-manager
+++ b/Documentation/ABI/testing/sysfs-class-fpga-manager
@@ -35,3 +35,13 @@ Description: Read fpga manager state as a string.
* write complete= Doing post programming steps
* write complete error  = Error while doing post programming
* operating = FPGA is programmed and operating
+
+What:  /sys/class/fpga_manager//status
+Date:  November 2017
+KernelVersion: 4.15
+Contact:   Wu Hao 
+Description:   Read fpga manager status as a string.
+   If FPGA programming operation fails, it could be due to crc
+   error or incompatible bitstream image. The intent of this
+   interface is to provide more detailed information for FPGA
+   programming errors to userspace.
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index 1fd5494..8b583ba 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -88,6 +88,7 @@ static int fpga_mgr_write_init_buf(struct fpga_manager *mgr,
if (ret) {
dev_err(>dev, "Error preparing FPGA for writing\n");
mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+   fpga_mgr_update_status(mgr);
return ret;
}
 
@@ -148,6 +149,7 @@ static int fpga_mgr_write_complete(struct fpga_manager *mgr,
if (ret) {
dev_err(>dev, "Error after writing image data to FPGA\n");
mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+   fpga_mgr_update_status(mgr);
return ret;
}
mgr->state = FPGA_MGR_STATE_OPERATING;
@@ -225,6 +227,7 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager 
*mgr,
if (ret) {
dev_err(>dev, "Error while writing image data to FPGA\n");
mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+   fpga_mgr_update_status(mgr);
return ret;
}
 
@@ -397,12 +400,36 @@ static ssize_t state_show(struct device *dev,
return sprintf(buf, "%s\n", state_str[mgr->state]);
 }
 
+static ssize_t status_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct fpga_manager *mgr = to_fpga_manager(dev);
+   int len = 0;
+
+   if (mgr->status & FPGA_MGR_STATUS_OPERATION_ERR)
+   len += sprintf(buf + len, "reconfig operation error\n");
+   if (mgr->status & FPGA_MGR_STATUS_CRC_ERR)
+   len += sprintf(buf + len, "reconfig CRC error\n");
+   if (mgr->status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR)
+   len += sprintf(buf + len, "reconfig incompatible image\n");
+   if (mgr->status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR)
+   len += sprintf(buf + len, "reconfig IP protocol error\n");
+   if (mgr->status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR)
+   len += sprintf(buf + len, "reconfig fifo overflow error\n");
+   if (mgr->status & FPGA_MGR_STATUS_SECURE_LOAD_ERR)
+   len += sprintf(buf + len, "reconfig secure load error\n");
+
+   return len;
+}
+
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(state);
+static DEVICE_ATTR_RO(status);
 
 static struct attribute *fpga_mgr_attrs[] = {
_attr_name.attr,
_attr_state.attr,
+   _attr_status.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(fpga_mgr);
@@ -561,6 +588,7 @@ int fpga_mgr_register(struct fpga_manager *mgr)
 * by bootloader or EEPROM.
 */
mgr->state = mgr->mops->state(mgr);
+   fpga_mgr_update_status(mgr);
 
device_initialize(>dev);
mgr->dev.class = fpga_mgr_class;
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 6e98b66..d4faf3d 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -112,6 +112,7 @@ struct 

[PATCH v3 05/21] fpga: dfl: add chardev support for feature devices

2017-11-26 Thread Wu Hao
For feature devices drivers, both the FPGA Management Engine (FME) and
Accelerated Function Unit (AFU) driver need to expose user interfaces via
the device file, for example, mmap and ioctls.

This patch adds chardev support in the fpga-dfl driver for feature devices,
FME and AFU. It reserves the chardev regions for FME and AFU, and provide
interfaces for FME and AFU driver to register their device file operations.

Signed-off-by: Tim Whisonant 
Signed-off-by: Enno Luebbers 
Signed-off-by: Shiva Rao 
Signed-off-by: Christopher Rauer 
Signed-off-by: Zhang Yi 
Signed-off-by: Xiao Guangrong 
Signed-off-by: Wu Hao 

v2: rebased
v3: move chardev support to fpga-dfl framework
---
 drivers/fpga/fpga-dfl.c | 91 -
 drivers/fpga/fpga-dfl.h | 13 +++
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/fpga-dfl.c b/drivers/fpga/fpga-dfl.c
index 6609828..9294c0a 100644
--- a/drivers/fpga/fpga-dfl.c
+++ b/drivers/fpga/fpga-dfl.c
@@ -76,6 +76,83 @@ static enum fpga_id_type feature_dev_id_type(struct 
platform_device *pdev)
return FPGA_ID_MAX;
 }
 
+struct fpga_chardev_info {
+   const char *name;
+   dev_t devt;
+};
+
+/* indexed by enum fpga_devt_type */
+struct fpga_chardev_info fpga_chrdevs[] = {
+   {.name = FPGA_FEATURE_DEV_FME}, /* FPGA_DEVT_FME */
+   {.name = FPGA_FEATURE_DEV_PORT},/* FPGA_DEVT_AFU */
+};
+
+static void fpga_chardev_uinit(void)
+{
+   int i;
+
+   for (i = 0; i < FPGA_DEVT_MAX; i++)
+   if (MAJOR(fpga_chrdevs[i].devt)) {
+   unregister_chrdev_region(fpga_chrdevs[i].devt,
+MINORMASK);
+   fpga_chrdevs[i].devt = MKDEV(0, 0);
+   }
+}
+
+static int fpga_chardev_init(void)
+{
+   int i, ret;
+
+   for (i = 0; i < FPGA_DEVT_MAX; i++) {
+   ret = alloc_chrdev_region(_chrdevs[i].devt, 0, MINORMASK,
+ fpga_chrdevs[i].name);
+   if (ret)
+   goto exit;
+   }
+
+   return 0;
+
+exit:
+   fpga_chardev_uinit();
+   return ret;
+}
+
+static dev_t fpga_get_devt(enum fpga_devt_type type, int id)
+{
+   WARN_ON(type >= FPGA_DEVT_MAX);
+
+   return MKDEV(MAJOR(fpga_chrdevs[type].devt), id);
+}
+
+int fpga_register_dev_ops(struct platform_device *pdev,
+ const struct file_operations *fops,
+ struct module *owner)
+{
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+
+   cdev_init(>cdev, fops);
+   pdata->cdev.owner = owner;
+
+   /*
+* set parent to the feature device so that its refcount is
+* decreased after the last refcount of cdev is gone, that
+* makes sure the feature device is valid during device
+* file's life-cycle.
+*/
+   pdata->cdev.kobj.parent = >dev.kobj;
+
+   return cdev_add(>cdev, pdev->dev.devt, 1);
+}
+EXPORT_SYMBOL_GPL(fpga_register_dev_ops);
+
+void fpga_unregister_dev_ops(struct platform_device *pdev)
+{
+   struct feature_platform_data *pdata = dev_get_platdata(>dev);
+
+   cdev_del(>cdev);
+}
+EXPORT_SYMBOL_GPL(fpga_unregister_dev_ops);
+
 /**
  * build_feature_devs_info - info collected during feature dev build.
  *
@@ -139,8 +216,12 @@ static int build_info_commit_dev(struct 
build_feature_devs_info *binfo)
struct platform_device *fdev;
struct resource *res;
struct feature_platform_data *pdata;
+   enum fpga_devt_type devt_type = FPGA_DEVT_FME;
int ret;
 
+   if (type == PORT_ID)
+   devt_type = FPGA_DEVT_PORT;
+
/* we will create a new device, commit current device first */
ret = build_info_commit_dev(binfo);
if (ret)
@@ -161,6 +242,7 @@ static int build_info_commit_dev(struct 
build_feature_devs_info *binfo)
return fdev->id;
 
fdev->dev.parent = >cdev->region.dev;
+   fdev->dev.devt = fpga_get_devt(devt_type, fdev->id);
 
/*
 * we do not need to care for the memory which is associated with
@@ -866,13 +948,20 @@ int __fpga_port_disable(struct platform_device *pdev)
 
 static int __init dfl_fpga_init(void)
 {
+   int ret;
+
fpga_ids_init();
 
-   return 0;
+   ret = fpga_chardev_init();
+   if (ret)
+   fpga_ids_destroy();
+
+   return ret;
 }
 
 static void __exit dfl_fpga_exit(void)
 {
+   fpga_chardev_uinit();
fpga_ids_destroy();
 }
 
diff --git a/drivers/fpga/fpga-dfl.h b/drivers/fpga/fpga-dfl.h
index abcbe57..e569a13 100644
--- a/drivers/fpga/fpga-dfl.h
+++ b/drivers/fpga/fpga-dfl.h
@@ -17,6 +17,7 @@
 #define __DFL_FPGA_H
 
 #include 
+#include 
 #include 
 

  1   2   3   4   5   6   7   >