Re: [PATCH 3.2 042/164] vfs: fix data corruption when blocksize < pagesize for mmaped data

2014-12-23 Thread Zefan Li
On 2014/12/12 16:48, Jan Kara wrote:
> On Fri 12-12-14 06:14:25, Ben Hutchings wrote:
>> 3.2.65-rc1 review patch.  If anyone has any objections, please let me know.
>>
>> --
>>
>> From: Jan Kara 
>>
>> commit 90a8020278c1598fafd071736a0846b38510309c upstream.
>   This patch needs also commit f55fefd1a5a339b1bd08c120b93312d6eb64a9fb,
> otherwise XFS will spew lots of false warnings...
> 

I've also applied this to 3.4. Thanks!

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 0/3] usb: chipidea: add one errata for revision 2.40a

2014-12-23 Thread Sanchayan Maity

On 12/23/2014 05:39 AM, Peter Chen wrote:
> On Mon, Dec 22, 2014 at 06:39:42PM +0530, Sanchayan Maity wrote:
>> On 12/22/2014 06:48 AM, Peter Chen wrote:
>>> On Fri, Dec 19, 2014 at 03:25:26PM +0530, Sanchayan Maity wrote:
 The first two patches add identification register API's. These can
 be used to get controller's revision. 

 The third patch implements an errata for revision 2.40a. Not sure
 which other SOCs implement this version of the Chipidea core but
 this fixes the usb client issue observed on Vybrids. The patch was
 tested on a Toradex Colibri VF61 module with the 3.18 kernel. iperf
 tests ran for three hours plus, with these patches applied have found
 the USB client connection to be now reliable.
>>>
>>> Would you help do a overnight test? It is passed, I will queue them,
>>> thanks.
>>
>> Yes definitely I can help with the testing. Are you looking for iperf
>> tests only or something else? iperf tests running for 12 or 24 hours 
>> will do? I will need a bit of time to set things up here, as I am away
>> from work, but, ya I will do them. 
>>
> 
> iperf for g_ncm or g_ether and bonnie++ for g_mass_storage if you can
> run, thanks.

The tests were run on a Toradex Colibri Vybrid VF61 module having 256MB RAM
with the 3.18 kernel.

The iperf tests ran for around 19 hours before I stopped it. A snip of 
the iperf tests is below. Used the Ethernet Gadget class for this.

[  4] 70453.0-70453.5 sec  6.89 MBytes   116 Mbits/sec
[  4] 70453.5-70454.0 sec  6.83 MBytes   115 Mbits/sec
[  4] 70454.0-70454.5 sec  6.84 MBytes   115 Mbits/sec
[  4] 70454.5-70455.0 sec  6.89 MBytes   116 Mbits/sec
[  4] 70455.0-70455.5 sec  6.90 MBytes   116 Mbits/sec
[  4] 70455.5-70456.0 sec  6.90 MBytes   116 Mbits/sec
[  4] 70456.0-70456.5 sec  6.82 MBytes   114 Mbits/sec
[  4] 70456.5-70457.0 sec  6.80 MBytes   114 Mbits/sec
[  4] 70457.0-70457.5 sec  6.89 MBytes   116 Mbits/sec
[  4] 70457.5-70458.0 sec  6.85 MBytes   115 Mbits/sec
[  4] 70458.0-70458.5 sec  6.82 MBytes   114 Mbits/sec
[  4] 70458.5-70459.0 sec  6.82 MBytes   114 Mbits/sec
[  4]  0.0-70459.2 sec   946 GBytes   115 Mbits/sec

Ran bonnie++ on gadget mass storage. CPU usage around the time of running
this test was mostly around the 90% mark with the minimum at 60% plus.
The storage directory was formatted with ext4. bonnie++ version used is
1.97 and was installed from the Arch repositories with pacman.

The size of the file being specified for "lun" storage is 512MB. I have 
specified
128MB RAM in the below run with the size of file for IO performance as 256MB.
Without this bonnie++ was giving me an error around the "Writing intelligently"
point. I assume this has to do with the file size bonnie++ uses for testing.

[sanchayan@Sanchayan-Arch ~]$ sudo /usr/bin/bonnie++ -m Vybrid -r 128 -d 
/var/run/media/sanchayan/Vybrid/ -x 5 -u root -n 0 -s 256
Using uid:0, gid:0.
format_version,bonnie_version,name,concurrency,seed,file_size,io_chunk_size,putc,putc_cpu,put_block,put_block_cpu,rewrite,rewrite_cpu,getc,getc_cpu,get_block,get_block_cpu,seeks,seeks_cpu,num_files,max_size,min_size,num_dirs,file_chunk_size,seq_create,seq_create_cpu,seq_stat,seq_stat_cpu,seq_del,seq_del_cpu,ran_create,ran_create_cpu,ran_stat,ran_stat_cpu,ran_del,ran_del_cpu,putc_latency,put_block_latency,rewrite_latency,getc_latency,get_block_latency,seeks_latency,seq_create_latency,seq_stat_latency,seq_del_latency,ran_create_latency,ran_stat_latency,ran_del_latency
Writing a byte at a time...done
Writing intelligently...done
Rewriting...done
Reading a byte at a time...done
Reading intelligently...done
start 'em...done...done...done...done...done...
1.97,1.97,Vybrid,1,1419409300,256M,,659,87,8341,1,9401,0,4222,98,+,+++,3539,19,,23042us,66us,59us,4482us,79us,475us,,
Writing a byte at a time...done
Writing intelligently...done
Rewriting...done
Reading a byte at a time...done
Reading intelligently...done
start 'em...done...done...done...done...done...
1.97,1.97,Vybrid,1,1419409300,256M,,661,90,7689,1,9071,0,4011,99,+,+++,3426,20,,15406us,64us,62us,4667us,23us,10030us,,
Writing a byte at a time...done
Writing intelligently...done
Rewriting...done
Reading a byte at a time...done
Reading intelligently...done
start 'em...done...done...done...done...done...
1.97,1.97,Vybrid,1,1419409300,256M,,673,89,8117,1,9451,0,3879,98,+,+++,3355,22,,14210us,45us,69us,5069us,21us,10052us,,
Writing a byte at a time...done
Writing intelligently...done
Rewriting...done
Reading a byte at a time...done
Reading intelligently...done
start 'em...done...done...done...done...done...
1.97,1.97,Vybrid,1,1419409300,256M,,668,89,7801,1,9343,0,4099,98,+,+++,3336,16,,17019us,44us,75us,4920us,20us,10234us,,
Writing a byte at a time...done
Writing intelligently...done
Rewriting...done
Reading a byte at a time...done
Reading intelligently...done
start 'em...done...done...done...done...done...

Re: [PATCH 1/7] input: alps: Set correct name of psmouse device in alps_init()

2014-12-23 Thread Pali Rohár
On Saturday 20 December 2014 09:53:38 Pali Rohár wrote:
> On Tuesday 16 December 2014 12:58:20 Pali Rohár wrote:
> > On Tuesday 16 December 2014 06:02:34 Dmitry Torokhov wrote:
> > > Hi Pali,
> > > 
> > > On Fri, Nov 14, 2014 at 08:38:20PM +0100, Pali Rohár wrote:
> > > > On some laptops after starting them from off state (not
> > > > after reboot), function alps_probe_trackstick_v3()
> > > > (called from function alps_identify()) does not detect
> > > > trackstick. To fix this problem we need to reset
> > > > device. But function alps_identify() is called also
> > > > from alps_detect() and we do not want to reset device
> > > > in detect function because it will slow down
> > > > initialization of all other non alps devices.
> > > > 
> > > > This patch moves code for setting correct device name &
> > > > protocol from function alps_detect() to alps_init()
> > > > which already doing full device reset.
> > > > 
> > > > So this patch removes need to do trackstick detection in
> > > > alps_detect() function.
> > > > 
> > > > Signed-off-by: Pali Rohár 
> > > > ---
> > > > 
> > > >  drivers/input/mouse/alps.c |   17 ++---
> > > >  1 file changed, 14 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/input/mouse/alps.c
> > > > b/drivers/input/mouse/alps.c index 8d85c79..9ffa98d
> > > > 100644 --- a/drivers/input/mouse/alps.c
> > > > +++ b/drivers/input/mouse/alps.c
> > > > @@ -2392,6 +2392,10 @@ int alps_init(struct psmouse
> > > > *psmouse)
> > > > 
> > > > if (input_register_device(priv->dev2))
> > > > 
> > > > goto init_fail;
> > > > 
> > > > +   if (!(priv->flags & ALPS_DUALPOINT))
> > > > +   psmouse->name = "GlidePoint TouchPad";
> > > > +   psmouse->model = priv->proto_version;
> > > > +
> > > > 
> > > > psmouse->protocol_handler = alps_process_byte;
> > > > psmouse->poll = alps_poll;
> > > > psmouse->disconnect = alps_disconnect;
> > > > 
> > > > @@ -2422,11 +2426,18 @@ int alps_detect(struct psmouse
> > > > *psmouse, bool set_properties)
> > > > 
> > > > return -1;
> > > > 
> > > > if (set_properties) {
> > > > 
> > > > +   /*
> > > > +* NOTE: To detect model and trackstick presence we
> > 
> > need
> > 
> > > > to do +  *   full device reset. To speed up
> > 
> > detection
> > 
> > > > and prevent +*   calling duplicate
> 
> initialization
> 
> > > > sequence (both in +  *   alps_detect() and
> > > > alps_init()) we set model/protocol + *   version
> 
> and
> 
> > > > correct name in alps_init() (which will +*   
do
> > 
> > full
> > 
> > > > device reset). For now set name to DualPoint. +  */
> > > > 
> > > > psmouse->vendor = "ALPS";
> > > > 
> > > > -   psmouse->name = dummy.flags & ALPS_DUALPOINT ?
> > > > -   "DualPoint TouchPad" : "GlidePoint";
> > > > -   psmouse->model = dummy.proto_version << 8;
> > > > +   psmouse->name = "DualPoint TouchPad";
> > > > 
> > > > }
> > > > 
> > > > +
> > > 
> > > I do not quite like the way we change the device
> > > description back and forth. Do you think we could
> > > allocate the "real" priv structure in alps_detect() and
> > > have alps_init() expect to find it (and free it if
> > > set_properties is false). This way we'd go through
> > > initialization once in detect, it will be authoritative,
> > > and we would set the name of the device properly from the
> > > beginning.
> > > 
> > > Thanks.
> > 
> > No without introducing another psmouse_reset call. I want to
> > reduce time of loading driver, so I think this is better.
> 
> Also psmouse-base.c call psmouse_reset between alps_detect()
> and alps_init(). We must do trackstick detection after
> psmouse_reset, but intorducing another psmouse_reset in
> alps_detect() will slow down initialization for ALPS devices.
> Also do not remember that psmouse_reset will lock both
> keyboard & mouse for one second (sometimes for two) on my
> laptop. I played with this and I think my patch is good
> approach how to do trackstick detection without slowdown or
> other side effects.
> 
> Also we do not need to know if ALPS touchpad has trackstick
> device in alps_detect() phase. In alps_detect() we just need
> to know if PS/2 device is ALPS or not. From psmouse/serio
> point of view there is only one ALPS device on PS/2/i8042
> bus. Just alps.ko driver parse PS/2 packets and detect which
> packet has touchpad header and which trackpoint. So we really
> do not need to know if trackstick is there or not in
> alps_detect() function.

Dmitry ping, can you finally review this patch series? I it there 
for more then month...

-- 
Pali Rohár
pali.ro...@gmail.com


signature.asc
Description: This is a digitally signed message part.


[PATCH 03/37] perf tools: Use perf_data_file__fd() consistently

2014-12-23 Thread Namhyung Kim
Do not reference file->fd directly since we want hide the
implementation details from outside to support multi-file store.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-inject.c |  9 ++---
 tools/perf/builtin-record.c | 14 --
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 84df2deed988..d8b13407594d 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -375,8 +375,10 @@ static int __cmd_inject(struct perf_inject *inject)
}
}
 
-   if (!file_out->is_pipe)
-   lseek(file_out->fd, session->header.data_offset, SEEK_SET);
+   if (!file_out->is_pipe) {
+   lseek(perf_data_file__fd(file_out), session->header.data_offset,
+ SEEK_SET);
+   }
 
ret = perf_session__process_events(session, >tool);
 
@@ -385,7 +387,8 @@ static int __cmd_inject(struct perf_inject *inject)
perf_header__set_feat(>header,
  HEADER_BUILD_ID);
session->header.data_size = inject->bytes_written;
-   perf_session__write_header(session, session->evlist, 
file_out->fd, true);
+   perf_session__write_header(session, session->evlist,
+  perf_data_file__fd(file_out), true);
}
 
return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index aa5fa6aabb31..054c6e57d3b9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -196,7 +196,7 @@ static int process_buildids(struct record *rec)
struct perf_session *session = rec->session;
u64 start = session->header.data_offset;
 
-   u64 size = lseek(file->fd, 0, SEEK_CUR);
+   u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
if (size == 0)
return 0;
 
@@ -360,12 +360,12 @@ static int __cmd_record(struct record *rec, int argc, 
const char **argv)
perf_header__clear_feat(>header, HEADER_GROUP_DESC);
 
if (file->is_pipe) {
-   err = perf_header__write_pipe(file->fd);
+   err = perf_header__write_pipe(perf_data_file__fd(file));
if (err < 0)
goto out_child;
} else {
err = perf_session__write_header(session, rec->evlist,
-file->fd, false);
+perf_data_file__fd(file), 
false);
if (err < 0)
goto out_child;
}
@@ -397,8 +397,10 @@ static int __cmd_record(struct record *rec, int argc, 
const char **argv)
 * return this more properly and also
 * propagate errors that now are calling die()
 */
-   err = perf_event__synthesize_tracing_data(tool, 
file->fd, rec->evlist,
- 
process_synthesized_event);
+   err = perf_event__synthesize_tracing_data(tool,
+   perf_data_file__fd(file),
+   rec->evlist,
+   process_synthesized_event);
if (err <= 0) {
pr_err("Couldn't record tracing data.\n");
goto out_child;
@@ -541,7 +543,7 @@ static int __cmd_record(struct record *rec, int argc, const 
char **argv)
if (!rec->no_buildid)
process_buildids(rec);
perf_session__write_header(rec->session, rec->evlist,
-  file->fd, true);
+  perf_data_file__fd(>file), 
true);
}
 
 out_delete_session:
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 04/37] perf tools: Add multi file interface to perf_data_file

2014-12-23 Thread Namhyung Kim
When multi file storage is enabled, the perf data files will be saved
in a directory (default: perf.data.dir) and it'll have a single header
file for metadata (task/comm/mmap events and file header) and multiple
data files (sample events) like below:

  $ tree perf.data.dir
  perf.data.dir
  |-- perf.data.0
  |-- perf.data.1
  |-- perf.data.2
  |-- perf.data.3
  `-- perf.header

  0 directories, 5 files

Existing data file interface supports multi files internally and add
new perf_data_file__prepare_write() and perf_data_file__write_multi()
functions in order to support multi-file record.  Note that multi read
interface is not needed since they're accessed via mmap.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/data.c | 149 +++--
 tools/perf/util/data.h |  14 +
 tools/perf/util/util.c |  43 ++
 tools/perf/util/util.h |   1 +
 4 files changed, 201 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1921942fc2e0..8dacd34659cc 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "data.h"
 #include "util.h"
@@ -39,26 +40,97 @@ static int check_backup(struct perf_data_file *file)
char oldname[PATH_MAX];
snprintf(oldname, sizeof(oldname), "%s.old",
 file->path);
-   unlink(oldname);
+
+   if (S_ISDIR(st.st_mode))
+   rm_rf(oldname);
+   else
+   unlink(oldname);
+
rename(file->path, oldname);
}
 
return 0;
 }
 
+static int scandir_filter(const struct dirent *d)
+{
+   return !prefixcmp(d->d_name, "perf.data.");
+}
+
+static int open_file_read_multi(struct perf_data_file *file)
+{
+   int i, n;
+   int ret;
+   struct dirent **list;
+
+   n = scandir(file->path, , scandir_filter, versionsort);
+   if (n <= 0) {
+   ret = -errno;
+   pr_err("cannot find multi-data file\n");
+   return ret;
+   }
+
+   file->multi_fd = malloc(n * sizeof(int));
+   if (file->multi_fd == NULL) {
+   free(list);
+   return -ENOMEM;
+   }
+
+   for (i = 0; i < n; i++) {
+   char path[PATH_MAX];
+
+   scnprintf(path, sizeof(path), "%s/%s",
+ file->path, list[i]->d_name);
+
+   ret = open(path, O_RDONLY);
+   if (ret < 0)
+   goto out_err;
+
+   file->multi_fd[i] = ret;
+   }
+
+   file->nr_multi = n;
+
+   free(list);
+   return 0;
+
+out_err:
+   while (--i >= 0)
+   close(file->multi_fd[i]);
+
+   zfree(>multi_fd);
+   free(list);
+   return ret;
+}
+
+static const char *default_data_path(struct perf_data_file *file)
+{
+   return file->is_multi ? "perf.data.dir" : "perf.data";
+}
+
 static int open_file_read(struct perf_data_file *file)
 {
struct stat st;
+   char path[PATH_MAX];
int fd;
char sbuf[STRERR_BUFSIZE];
 
-   fd = open(file->path, O_RDONLY);
+   strcpy(path, file->path);
+   if (file->is_multi) {
+   if (open_file_read_multi(file) < 0)
+   return -1;
+
+   if (path__join(path, sizeof(path), file->path, "perf.header") < 
0)
+   return -1;
+   }
+
+   fd = open(path, O_RDONLY);
if (fd < 0) {
int err = errno;
 
-   pr_err("failed to open %s: %s", file->path,
+   pr_err("failed to open %s: %s", path,
strerror_r(err, sbuf, sizeof(sbuf)));
-   if (err == ENOENT && !strcmp(file->path, "perf.data"))
+   if (err == ENOENT && !strcmp(path, default_data_path(file)))
pr_err("  (try 'perf record' first)");
pr_err("\n");
return -err;
@@ -90,12 +162,26 @@ static int open_file_read(struct perf_data_file *file)
 static int open_file_write(struct perf_data_file *file)
 {
int fd;
+   char path[PATH_MAX];
char sbuf[STRERR_BUFSIZE];
 
if (check_backup(file))
return -1;
 
-   fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
+   strcpy(path, file->path);
+
+   if (file->is_multi) {
+   if (mkdir(file->path, S_IRWXU) < 0) {
+   pr_err("cannot create data directory `%s': %s\n",
+  file->path, strerror_r(errno, sbuf, 
sizeof(sbuf)));
+   return -1;
+   }
+
+   if (path__join(path, sizeof(path), file->path, "perf.header") < 
0)
+   return -1;
+   }
+
+   fd = open(path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
 
if (fd < 0)
pr_err("failed to open %s : %s\n", 

[RFC/PATCHSET 00/37] perf tools: Speed-up perf report by using multi thread (v1)

2014-12-23 Thread Namhyung Kim
Hello,

This patchset converts perf report to use multiple threads in order to
speed up the processing on large data files.  I can see a minimum 40%
of speedup with this change.  The code is still experimental, little
bit outdated and contains many rough edges.  But I'd like to share and
give some feedbacks.

The perf report processes (sample) events like below:

  1. preprocess sample to get matching thread/dso/symbol info
  2. insert it to hists rbtree (with callchain tree) based on the info
  3. optionally collapse hist entries that match given sort key(s)
  4. resort hist entries (by overhead) for output
  5. display the hist entries

The stage 1 is a preprocessing and mostly act like a read-only
operation during the sample processing.  Meta events like fork, comm
and mmap can change the machine/thread state but symbols can be loaded
during the processing (stage 2).

The stage 2 consumes most of the time especially with callchains and
 --children option is enabled.  And this work can be easily patitioned
as each sample is independent to others.  But the resulting hists must
be combined/collapsed to a single global hists before going to further
steps.

The stage 3 is optional and only needed by certain sort keys - but
with stage 2 paralellized, it needs to be done anyway.

The stage 4 and 5 works on whole hists so must be done serially.

So my approach is like this:

Partially do stage 1 first - but only for meta events that changes
machine state.  To do this I add a dummy tracking event to perf record
and make it collect such meta events only.  They are saved in a
separate file (perf.header) and processed before sample events at perf
report time.

This also requires to handle multiple files and to find a
corresponding machine state when processing samples.  On a large
profiling session, many tasks were created and exited so pid might be
recycled (even more than once!).  To deal with it, I managed to have
thread, map_groups and comm in time sorted.  The only remaining thing
is symbol loading as it's done lazily when sample requires it.

With that being done, the stage 2 can be done by multiple threads.  I
also save each sample data (per-cpu or per-thread) in separate files
during record.  On perf report time, each file will be processed by
each thread.  And symbol loading is protected by a mutex lock.

For DWARF post-unwinding, dso cache data also needs to be protected by
a lock and this causes a huge contention.  I just added a front cache
that can be accessed without the lock but this should be improved IMHO.

The patch 1-10 are to support multi-file data recording.  With
 -M/--multi option, perf record will create a directory (named
'perf.data.dir' by default - but maybe renamed 'perf.data' for
transparent conversion later) and save meta events to perf.header file
and sample events to perf.data. file).  It'd be better considering
file format change Jiri suggested [1].

The patch 11-20 are to manage machine and thread state using timestamp
so that it can be searched when processing samples.  The patch 21-35
are to implement parallel report.  And finally I implemented 'perf
data split' command to convert a single data file into a multi-file
format.

This patchset didn't change perf record to use multi-thread.  But I
think it can be easily done later if needed.

Note that output has a slight difference to original version when
compared using splitted data file.  But they're mostly unresolved
symbols for callchains.

Here is the result:

This is just elapsed (real) time measured by shell 'time' function.

The data file was recorded during kernel build with fp callchain and
size is 2.1GB.  The machine has 6 core with hyper-threading enabled
and I got a similar result on my laptop too.

 time perf report  --children  --no-children  + --call-graph none
   --  -  ---
 current4m43.260s  1m32.779s0m35.866s
 patched4m43.710s  1m29.695s0m33.995s
 --multi-thread 2m46.265s  0m45.486s 0m7.570s


This result is with 7.7GB data file using libunwind for callchain.

 time perf report  --children  --no-children  + --call-graph none
   --  -  ---
 current3m51.762s  3m10.451s 0m4.695s
 patched2m26.030s  1m49.846s 0m4.105s
 --multi-thread 0m49.217s  0m35.106s 0m1.457s

Note that the single thread performance improvement in patched version
is due to changes in the patch 33-35.


This result is with same file but using libdw for callchain unwind.

 time perf report  --children  --no-children  + --call-graph none
   --  -  ---
 current   10m22.472s 11m42.290s 0m4.758s
 patched   10m10.625s 11m45.480s 0m4.162s
 --multi-thread 3m47.332s   

[PATCH 07/37] perf tools: Do not use __perf_session__process_events() directly

2014-12-23 Thread Namhyung Kim
It's only used for perf record to process build-id because its file
size it's not fixed at this time due to remaining header features.
However data offset and size is available so that we can use the
perf_session__process_events() once we set the file size as the
current offset like for now.

It turns out that we can staticize the function again as it's the only
user and add multi file support in a single place.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-record.c | 7 +++
 tools/perf/util/session.c   | 6 +++---
 tools/perf/util/session.h   | 3 ---
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8c91f25b81f6..4f97657f14e7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -196,12 +196,13 @@ static int process_buildids(struct record *rec)
 {
struct perf_data_file *file  = >file;
struct perf_session *session = rec->session;
-   u64 start = session->header.data_offset;
 
u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
if (size == 0)
return 0;
 
+   file->size = size;
+
/*
 * During this process, it'll load kernel map and replace the
 * dso->long_name to a real pathname it found.  In this case
@@ -213,9 +214,7 @@ static int process_buildids(struct record *rec)
 */
symbol_conf.ignore_vmlinux_buildid = true;
 
-   return __perf_session__process_events(session, start,
- size - start,
- size, 
_id__mark_dso_hit_ops);
+   return perf_session__process_events(session, 
_id__mark_dso_hit_ops);
 }
 
 static void perf_event__synthesize_guest_os(struct machine *machine, void 
*data)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6ac62ae6b8fa..88aa2f09df93 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1252,9 +1252,9 @@ fetch_mmaped_event(struct perf_session *session,
 #define NUM_MMAPS 128
 #endif
 
-int __perf_session__process_events(struct perf_session *session,
-  u64 data_offset, u64 data_size,
-  u64 file_size, struct perf_tool *tool)
+static int __perf_session__process_events(struct perf_session *session,
+ u64 data_offset, u64 data_size,
+ u64 file_size, struct perf_tool *tool)
 {
int fd = perf_data_file__fd(session->file);
u64 head, page_offset, file_offset, file_pos, size;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index dc26ebf60fe4..6d663dc76404 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -49,9 +49,6 @@ int perf_session__peek_event(struct perf_session *session, 
off_t file_offset,
 union perf_event **event_ptr,
 struct perf_sample *sample);
 
-int __perf_session__process_events(struct perf_session *session,
-  u64 data_offset, u64 data_size, u64 size,
-  struct perf_tool *tool);
 int perf_session__process_events(struct perf_session *session,
 struct perf_tool *tool);
 
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 08/37] perf tools: Handle multi-file session properly

2014-12-23 Thread Namhyung Kim
When perf detects multi-file data directory, process header file first
and then rest data files in a row.  Note that the multi-file data is
recorded for each cpu/thread separately, it's already ordered with
respect to themselves so no need to use the ordered event queue
interface.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/data.c| 17 +
 tools/perf/util/session.c | 41 +++--
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 8dacd34659cc..b6f7cdc4a39f 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -52,6 +52,21 @@ static int check_backup(struct perf_data_file *file)
return 0;
 }
 
+static void check_multi(struct perf_data_file *file)
+{
+   struct stat st;
+
+   /*
+* For write, it'll be determined by user (perf record -M)
+* whether to enable multi file data storage.
+*/
+   if (perf_data_file__is_write(file))
+   return;
+
+   if (!stat(file->path, ) && S_ISDIR(st.st_mode))
+   file->is_multi = true;
+}
+
 static int scandir_filter(const struct dirent *d)
 {
return !prefixcmp(d->d_name, "perf.data.");
@@ -206,6 +221,8 @@ int perf_data_file__open(struct perf_data_file *file)
if (check_pipe(file))
return 0;
 
+   check_multi(file);
+
if (!file->path)
file->path = default_data_path(file);
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 88aa2f09df93..4f0fcd2d3901 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1252,11 +1252,10 @@ fetch_mmaped_event(struct perf_session *session,
 #define NUM_MMAPS 128
 #endif
 
-static int __perf_session__process_events(struct perf_session *session,
+static int __perf_session__process_events(struct perf_session *session, int fd,
  u64 data_offset, u64 data_size,
  u64 file_size, struct perf_tool *tool)
 {
-   int fd = perf_data_file__fd(session->file);
u64 head, page_offset, file_offset, file_pos, size;
int err, mmap_prot, mmap_flags, map_idx = 0;
size_t  mmap_size;
@@ -1362,18 +1361,40 @@ int perf_session__process_events(struct perf_session 
*session,
 struct perf_tool *tool)
 {
u64 size = perf_data_file__size(session->file);
-   int err;
+   int err, i;
 
if (perf_session__register_idle_thread(session) == NULL)
return -ENOMEM;
 
-   if (!perf_data_file__is_pipe(session->file))
-   err = __perf_session__process_events(session,
-
session->header.data_offset,
-session->header.data_size,
-size, tool);
-   else
-   err = __perf_session__process_pipe_events(session, tool);
+   if (perf_data_file__is_pipe(session->file))
+   return __perf_session__process_pipe_events(session, tool);
+
+   err = __perf_session__process_events(session,
+perf_data_file__fd(session->file),
+session->header.data_offset,
+session->header.data_size,
+size, tool);
+   if (!session->file->is_multi || err)
+   return err;
+
+   /*
+* For multi-file data storage, events are processed for each
+* cpu/thread so it's already ordered.
+*/
+   tool->ordered_events = false;
+
+   for (i = 0; i < session->file->nr_multi; i++) {
+   int fd = perf_data_file__multi_fd(session->file, i);
+
+   size = lseek(fd, 0, SEEK_END);
+   if (size == 0)
+   continue;
+
+   err = __perf_session__process_events(session, fd,
+0, size, size, tool);
+   if (err < 0)
+   break;
+   }
 
return err;
 }
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 05/37] perf tools: Create separate mmap for dummy tracking event

2014-12-23 Thread Namhyung Kim
When multi file support is enabled, a dummy tracking event will be
used to track metadata (like task, comm and mmap events) for a session
and actual samples will be recorded in separate files.

Provide separate mmap to the dummy tracking event.  The size is fixed
to 128KiB (+ 1 page) as the event rate will be lower than samples.  I
originally wanted to use a single mmap for this but cross-cpu sharing
is prohibited so it's per-cpu (or per-task) like normal mmaps.

Cc: Adrian Hunter 
Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-record.c |   9 +++-
 tools/perf/util/evlist.c| 104 +++-
 tools/perf/util/evlist.h|  11 -
 3 files changed, 102 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 054c6e57d3b9..129fab35fdc5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -69,7 +69,7 @@ static int process_synthesized_event(struct perf_tool *tool,
 
 static int record__mmap_read(struct record *rec, int idx)
 {
-   struct perf_mmap *md = >evlist->mmap[idx];
+   struct perf_mmap *md = perf_evlist__mmap_desc(rec->evlist, idx);
unsigned int head = perf_mmap__read_head(md);
unsigned int old = md->prev;
unsigned char *data = md->base + page_size;
@@ -105,6 +105,7 @@ static int record__mmap_read(struct record *rec, int idx)
}
 
md->prev = old;
+
perf_evlist__mmap_consume(rec->evlist, idx);
 out:
return rc;
@@ -263,6 +264,12 @@ static int record__mmap_read_all(struct record *rec)
goto out;
}
}
+   if (rec->evlist->track_mmap) {
+   if (record__mmap_read(rec, track_mmap_idx(i)) != 0) {
+   rc = -1;
+   goto out;
+   }
+   }
}
 
/*
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 72dff295237e..d99343b988fe 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -27,6 +27,7 @@
 
 static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
 static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
+static void __perf_evlist__munmap_track(struct perf_evlist *evlist, int idx);
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
@@ -735,22 +736,39 @@ static bool perf_mmap__empty(struct perf_mmap *md)
return perf_mmap__read_head(md) != md->prev;
 }
 
+struct perf_mmap *perf_evlist__mmap_desc(struct perf_evlist *evlist, int idx)
+{
+   if (idx >= 0)
+   return >mmap[idx];
+   else
+   return >track_mmap[track_mmap_idx(idx)];
+}
+
 static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
 {
-   ++evlist->mmap[idx].refcnt;
+   struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
+
+   ++md->refcnt;
 }
 
 static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
 {
-   BUG_ON(evlist->mmap[idx].refcnt == 0);
+   struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
+
+   BUG_ON(md->refcnt == 0);
+
+   if (--md->refcnt != 0)
+   return;
 
-   if (--evlist->mmap[idx].refcnt == 0)
+   if (idx >= 0)
__perf_evlist__munmap(evlist, idx);
+   else
+   __perf_evlist__munmap_track(evlist, track_mmap_idx(idx));
 }
 
 void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
 {
-   struct perf_mmap *md = >mmap[idx];
+   struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
 
if (!evlist->overwrite) {
unsigned int old = md->prev;
@@ -771,6 +789,15 @@ static void __perf_evlist__munmap(struct perf_evlist 
*evlist, int idx)
}
 }
 
+static void __perf_evlist__munmap_track(struct perf_evlist *evlist, int idx)
+{
+   if (evlist->track_mmap[idx].base != NULL) {
+   munmap(evlist->track_mmap[idx].base, TRACK_MMAP_SIZE);
+   evlist->track_mmap[idx].base = NULL;
+   evlist->track_mmap[idx].refcnt = 0;
+   }
+}
+
 void perf_evlist__munmap(struct perf_evlist *evlist)
 {
int i;
@@ -782,23 +809,43 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
__perf_evlist__munmap(evlist, i);
 
zfree(>mmap);
+
+   if (evlist->track_mmap == NULL)
+   return;
+
+   for (i = 0; i < evlist->nr_mmaps; i++)
+   __perf_evlist__munmap_track(evlist, i);
+
+   zfree(>track_mmap);
 }
 
-static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
+static int perf_evlist__alloc_mmap(struct perf_evlist *evlist, bool track_mmap)
 {
evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
if (cpu_map__empty(evlist->cpus))
evlist->nr_mmaps = thread_map__nr(evlist->threads);
evlist->mmap = 

[PATCH 06/37] perf tools: Introduce perf_evlist__mmap_multi()

2014-12-23 Thread Namhyung Kim
The perf_evlist__mmap_multi function creates data mmaps and optionally
tracking mmaps for events.  It'll be used for perf record to save
tracking events in a separate files.  Checking dummy tracking event in
perf_evlist__mmap() alone is not enough as users can specify the dummy
event at first (like in keep tracking testcase) without the multi-file
option.

Cc: Adrian Hunter 
Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-record.c |  3 ++-
 tools/perf/util/evlist.c| 11 +++
 tools/perf/util/evlist.h| 10 --
 3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 129fab35fdc5..8c91f25b81f6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -169,7 +169,8 @@ static int record__open(struct record *rec)
goto out;
}
 
-   if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
+   if (perf_evlist__mmap_multi(evlist, opts->mmap_pages, false,
+   opts->multi_file) < 0) {
if (errno == EPERM) {
pr_err("Permission error mapping pages.\n"
   "Consider increasing "
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d99343b988fe..010188939104 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -841,6 +841,7 @@ static int perf_evlist__alloc_mmap(struct perf_evlist 
*evlist, bool track_mmap)
 
 struct mmap_params {
int prot;
+   booltrack;
size_t  len;
 };
 
@@ -889,7 +890,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist 
*evlist, int idx,
 
fd = FD(evsel, cpu, thread);
 
-   if (perf_evsel__is_dummy_tracking(evsel)) {
+   if (mp->track && perf_evsel__is_dummy_tracking(evsel)) {
struct mmap_params track_mp = {
.prot   = mp->prot,
.len= TRACK_MMAP_SIZE,
@@ -1068,10 +1069,11 @@ int perf_evlist__parse_mmap_pages(const struct option 
*opt, const char *str,
 }
 
 /**
- * perf_evlist__mmap - Create mmaps to receive events.
+ * perf_evlist__mmap_multi - Create mmaps to receive events.
  * @evlist: list of events
  * @pages: map length in pages
  * @overwrite: overwrite older events?
+ * @use_track_mmap: use another mmaps to track meta events
  *
  * If @overwrite is %false the user needs to signal event consumption using
  * perf_mmap__write_tail().  Using perf_evlist__mmap_read() does this
@@ -1079,14 +1081,15 @@ int perf_evlist__parse_mmap_pages(const struct option 
*opt, const char *str,
  *
  * Return: %0 on success, negative error code otherwise.
  */
-int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
- bool overwrite)
+int perf_evlist__mmap_multi(struct perf_evlist *evlist, unsigned int pages,
+   bool overwrite, bool use_track_mmap)
 {
struct perf_evsel *evsel;
const struct cpu_map *cpus = evlist->cpus;
const struct thread_map *threads = evlist->threads;
struct mmap_params mp = {
.prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
+   .track = use_track_mmap,
};
 
if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist, 
use_track_mmap) < 0)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b7f54b8577f7..65c1aea6a3a4 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -127,10 +127,16 @@ int perf_evlist__parse_mmap_pages(const struct option 
*opt,
  const char *str,
  int unset);
 
-int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
- bool overwrite);
+int perf_evlist__mmap_multi(struct perf_evlist *evlist, unsigned int pages,
+   bool overwrite, bool use_track_mmap);
 void perf_evlist__munmap(struct perf_evlist *evlist);
 
+static inline int perf_evlist__mmap(struct perf_evlist *evlist,
+   unsigned int pages, bool overwrite)
+{
+   return perf_evlist__mmap_multi(evlist, pages, overwrite, false);
+}
+
 void perf_evlist__disable(struct perf_evlist *evlist);
 void perf_evlist__enable(struct perf_evlist *evlist);
 
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 11/37] perf tools: Introduce thread__comm_time() helpers

2014-12-23 Thread Namhyung Kim
When multi-file data storage is enabled, it processes all task, comm
and mmap events first and then goes to the sample events.  So all it
sees is the last comm of a thread although it has information at the
time of sample.

Sort thread's comm by time so that it can find appropriate comm at the
sample time.  The thread__comm_time() will mostly work even if
PERF_SAMPLE_TIME bit is off since in that case, sample->time will be
-1 so it'll take the last comm anyway.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/util/thread.c | 34 +-
 tools/perf/util/thread.h |  2 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9ebc8b1f9be5..083fa0fcf316 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -103,6 +103,22 @@ struct comm *thread__exec_comm(const struct thread *thread)
return last;
 }
 
+struct comm *thread__comm_time(const struct thread *thread, u64 timestamp)
+{
+   struct comm *comm;
+
+   list_for_each_entry(comm, >comm_list, list) {
+   if (timestamp >= comm->start)
+   return comm;
+   }
+
+   if (list_empty(>comm_list))
+   return NULL;
+
+   return list_last_entry(>comm_list, struct comm, list);
+}
+
+/* CHECKME: time should always be 0 if event aren't ordered */
 int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
   bool exec)
 {
@@ -118,7 +134,13 @@ int __thread__set_comm(struct thread *thread, const char 
*str, u64 timestamp,
new = comm__new(str, timestamp, exec);
if (!new)
return -ENOMEM;
-   list_add(>list, >comm_list);
+
+   /* sort by time */
+   list_for_each_entry(curr, >comm_list, list) {
+   if (timestamp >= curr->start)
+   break;
+   }
+   list_add_tail(>list, >list);
 
if (exec)
unwind__flush_access(thread);
@@ -139,6 +161,16 @@ const char *thread__comm_str(const struct thread *thread)
return comm__str(comm);
 }
 
+const char *thread__comm_time_str(const struct thread *thread, u64 timestamp)
+{
+   const struct comm *comm = thread__comm_time(thread, timestamp);
+
+   if (!comm)
+   return NULL;
+
+   return comm__str(comm);
+}
+
 /* CHECKME: it should probably better return the max comm len from its comm 
list */
 int thread__comm_len(struct thread *thread)
 {
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 160fd066a7d1..0b6dcd70bc8b 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -53,7 +53,9 @@ static inline int thread__set_comm(struct thread *thread, 
const char *comm,
 int thread__comm_len(struct thread *thread);
 struct comm *thread__comm(const struct thread *thread);
 struct comm *thread__exec_comm(const struct thread *thread);
+struct comm *thread__comm_time(const struct thread *thread, u64 timestamp);
 const char *thread__comm_str(const struct thread *thread);
+const char *thread__comm_time_str(const struct thread *thread, u64 timestamp);
 void thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 02/37] perf record: Use a software dummy event to track task/mmap events

2014-12-23 Thread Namhyung Kim
Prepend a software dummy event into evlist to track task/comm/mmap
events separately.  This is a preparation of multi-file/thread support
which will come later.

Cc: Adrian Hunter 
Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-record.c |  3 +++
 tools/perf/perf.h   |  1 +
 tools/perf/util/evlist.c| 38 ++
 tools/perf/util/evlist.h|  1 +
 tools/perf/util/evsel.h | 15 +++
 5 files changed, 58 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8648c6d3003d..aa5fa6aabb31 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -862,6 +862,9 @@ int cmd_record(int argc, const char **argv, const char 
*prefix __maybe_unused)
goto out_symbol_exit;
}
 
+   if (rec->opts.multi_file)
+   perf_evlist__prepend_dummy(rec->evlist);
+
if (rec->opts.target.tid && !rec->opts.no_inherit_set)
rec->opts.no_inherit = true;
 
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 1dabb8553499..37284eb47b56 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -53,6 +53,7 @@ struct record_opts {
bool sample_time;
bool period;
bool sample_intr_regs;
+   bool multi_file;
unsigned int freq;
unsigned int mmap_pages;
unsigned int user_freq;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index cfbe2b99b9aa..72dff295237e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -193,6 +193,44 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
return -ENOMEM;
 }
 
+int perf_evlist__prepend_dummy(struct perf_evlist *evlist)
+{
+   struct perf_event_attr attr = {
+   .type = PERF_TYPE_SOFTWARE,
+   .config = PERF_COUNT_SW_DUMMY,
+   };
+   struct perf_evsel *evsel, *pos;
+
+   event_attr_init();
+
+   evsel = perf_evsel__new();
+   if (evsel == NULL)
+   goto error;
+
+   /* use strdup() because free(evsel) assumes name is allocated */
+   evsel->name = strdup("dummy");
+   if (!evsel->name)
+   goto error_free;
+
+   list_for_each_entry(pos, >entries, node) {
+   pos->idx += 1;
+   pos->tracking = false;
+   }
+
+   list_add(>node, >entries);
+   evsel->idx = 0;
+   evsel->tracking = true;
+
+   if (!evlist->nr_entries++)
+   perf_evlist__set_id_pos(evlist);
+
+   return 0;
+error_free:
+   perf_evsel__delete(evsel);
+error:
+   return -ENOMEM;
+}
+
 static int perf_evlist__add_attrs(struct perf_evlist *evlist,
  struct perf_event_attr *attrs, size_t 
nr_attrs)
 {
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 649b0c597283..b974bddf6b8b 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -67,6 +67,7 @@ void perf_evlist__delete(struct perf_evlist *evlist);
 
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
+int perf_evlist__prepend_dummy(struct perf_evlist *evlist);
 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 struct perf_event_attr *attrs, size_t 
nr_attrs);
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 38622747d130..5b45eea63043 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -331,6 +331,21 @@ static inline bool perf_evsel__is_function_event(struct 
perf_evsel *evsel)
 #undef FUNCTION_EVENT
 }
 
+/**
+ * perf_evsel__is_dummy_tracking - Return whether given evsel is a dummy
+ * event for tracking meta events only
+ *
+ * @evsel - evsel selector to be tested
+ *
+ * Return %true if event is a dummy tracking event
+ */
+static inline bool perf_evsel__is_dummy_tracking(struct perf_evsel *evsel)
+{
+   return evsel->attr.type == PERF_TYPE_SOFTWARE &&
+   evsel->attr.config == PERF_COUNT_SW_DUMMY &&
+   evsel->attr.task == 1 && evsel->idx == 0;
+}
+
 struct perf_attr_details {
bool freq;
bool verbose;
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/37] perf report: Skip dummy tracking event

2014-12-23 Thread Namhyung Kim
The dummy tracking event is only for tracking task/comom/mmap events
and has no sample data for itself.  So no need to report, just skip it.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-report.c|  3 +++
 tools/perf/ui/browsers/hists.c | 10 --
 tools/perf/ui/gtk/hists.c  |  3 +++
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2f91094e228b..4cac79ad3085 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -318,6 +318,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist 
*evlist,
struct hists *hists = evsel__hists(pos);
const char *evname = perf_evsel__name(pos);
 
+   if (perf_evsel__is_dummy_tracking(pos))
+   continue;
+
if (symbol_conf.event_group &&
!perf_evsel__is_group_leader(pos))
continue;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index e6bb04b5b09b..be594e1d6a99 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1998,11 +1998,15 @@ int perf_evlist__tui_browse_hists(struct perf_evlist 
*evlist, const char *help,
  struct perf_session_env *env)
 {
int nr_entries = evlist->nr_entries;
+   struct perf_evsel *first = perf_evlist__first(evlist);
+
+   if (perf_evsel__is_dummy_tracking(first)) {
+   first = perf_evsel__next(first);
+   nr_entries--;
+   }
 
 single_entry:
if (nr_entries == 1) {
-   struct perf_evsel *first = perf_evlist__first(evlist);
-
return perf_evsel__hists_browse(first, nr_entries, help,
false, hbt, min_pcnt,
env);
@@ -2013,6 +2017,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist 
*evlist, const char *help,
 
nr_entries = 0;
evlist__for_each(evlist, pos) {
+   if (perf_evsel__is_dummy_tracking(pos))
+   continue;
if (perf_evsel__is_group_leader(pos))
nr_entries++;
}
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 4b3585eed1e8..83a7ecd5cda8 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -317,6 +317,9 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist 
*evlist,
char buf[512];
size_t size = sizeof(buf);
 
+   if (perf_evsel__is_dummy_tracking(pos))
+   continue;
+
if (symbol_conf.event_group) {
if (!perf_evsel__is_group_leader(pos))
continue;
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/37] perf record: Add -M/--multi option for multi file recording

2014-12-23 Thread Namhyung Kim
The new -M/--multi option enables multi file storage recording.  Now
sample data in separate mmap are saved in different files and other
events will be recorded in the perf.header file.

Signed-off-by: Namhyung Kim 
---
 tools/perf/Documentation/perf-record.txt |  5 +
 tools/perf/builtin-record.c  | 27 ---
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt 
b/tools/perf/Documentation/perf-record.txt
index af9a54ece024..14247ccd7965 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -220,6 +220,11 @@ Capture machine state (registers) at interrupt, i.e., on 
counter overflows for
 each sample. List of captured registers depends on the architecture. This 
option
 is off by default.
 
+-M::
+--multi::
+Record data in multi-file storage instead of a single data file (perf.data).
+This will speed up perf report by parallel processing.
+
 SEE ALSO
 
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4f97657f14e7..7f7a4725d080 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -58,6 +58,19 @@ static int record__write(struct record *rec, void *bf, 
size_t size)
return 0;
 }
 
+static int record__write_multi(struct record *rec, void *bf, size_t size, int 
idx)
+{
+   if (rec->file.is_multi && idx >= 0) {
+   int ret = perf_data_file__write_multi(rec->session->file,
+ bf, size, idx);
+   if (ret < 0)
+   pr_err("failed to write perf data, error: %m\n");
+
+   return ret;
+   }
+   return record__write(rec, bf, size);
+}
+
 static int process_synthesized_event(struct perf_tool *tool,
 union perf_event *event,
 struct perf_sample *sample __maybe_unused,
@@ -89,7 +102,7 @@ static int record__mmap_read(struct record *rec, int idx)
size = md->mask + 1 - (old & md->mask);
old += size;
 
-   if (record__write(rec, buf, size) < 0) {
+   if (record__write_multi(rec, buf, size, idx) < 0) {
rc = -1;
goto out;
}
@@ -99,7 +112,7 @@ static int record__mmap_read(struct record *rec, int idx)
size = head - old;
old += size;
 
-   if (record__write(rec, buf, size) < 0) {
+   if (record__write_multi(rec, buf, size, idx) < 0) {
rc = -1;
goto out;
}
@@ -186,6 +199,10 @@ static int record__open(struct record *rec)
goto out;
}
 
+   rc = perf_data_file__prepare_write(session->file, evlist->nr_mmaps);
+   if (rc < 0)
+   goto out;
+
session->evlist = evlist;
perf_session__set_id_hdr_size(session);
 out:
@@ -822,6 +839,8 @@ struct option __record_options[] = {
"use per-thread mmaps"),
OPT_BOOLEAN('I', "intr-regs", _intr_regs,
"Sample machine registers on interrupt"),
+   OPT_BOOLEAN('M', "multi", _file,
+   "use multi-file storage"),
OPT_END()
 };
 
@@ -871,8 +890,10 @@ int cmd_record(int argc, const char **argv, const char 
*prefix __maybe_unused)
goto out_symbol_exit;
}
 
-   if (rec->opts.multi_file)
+   if (rec->opts.multi_file) {
+   rec->file.is_multi = true;
perf_evlist__prepend_dummy(rec->evlist);
+   }
 
if (rec->opts.target.tid && !rec->opts.no_inherit_set)
rec->opts.no_inherit = true;
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 15/37] perf tools: Introduce machine__find*_thread_time()

2014-12-23 Thread Namhyung Kim
With multi-file data storage is enabled, it needs to search thread
based on sample time since sample processing is done after other
(task, comm and mmap) events are processed.  This can be a problem if
a session is very long and pid is recycled - in that case it'll only
see the last one.

So keep thread start time in it, and search thread based on the time.
This patch introduces machine__find{,new}_thread_time() function for
this.  It'll first search current thread rbtree and then dead thread
tree and list.  If it couldn't find anyone, it'll create a new thread.

The sample timestamp of 0 means that this is called from synthesized
event so just use current rbtree.  The timestamp will be -1 if sample
didn't record the timestamp so will see current threads automatically.

Dead threads are managed in a rbtree, and if there's more than one
thread has sample tid/pid, it'll be saved in a list.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-script.c |   5 +-
 tools/perf/tests/dwarf-unwind.c |  10 ++--
 tools/perf/tests/hists_common.c |   3 +-
 tools/perf/tests/hists_link.c   |   2 +-
 tools/perf/util/event.c |   4 +-
 tools/perf/util/machine.c   | 109 +++-
 tools/perf/util/machine.h   |   8 ++-
 tools/perf/util/thread.c|   4 ++
 tools/perf/util/thread.h|   1 +
 9 files changed, 132 insertions(+), 14 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ce304dfd962a..85122b388d8e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -549,8 +549,9 @@ static int process_sample_event(struct perf_tool *tool 
__maybe_unused,
struct machine *machine)
 {
struct addr_location al;
-   struct thread *thread = machine__findnew_thread(machine, sample->pid,
-   sample->tid);
+   struct thread *thread = machine__findnew_thread_time(machine, 
sample->pid,
+sample->tid,
+sample->time);
 
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index ab28cca2cb97..dfecd49fef90 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -13,10 +13,10 @@
 
 static int mmap_handler(struct perf_tool *tool __maybe_unused,
union perf_event *event,
-   struct perf_sample *sample __maybe_unused,
+   struct perf_sample *sample,
struct machine *machine)
 {
-   return machine__process_mmap2_event(machine, event, NULL);
+   return machine__process_mmap2_event(machine, event, sample);
 }
 
 static int init_live_machine(struct machine *machine)
@@ -61,12 +61,12 @@ static int unwind_entry(struct unwind_entry *entry, void 
*arg)
 __attribute__ ((noinline))
 static int unwind_thread(struct thread *thread)
 {
-   struct perf_sample sample;
+   struct perf_sample sample = {
+   .time = -1ULL,
+   };
unsigned long cnt = 0;
int err = -1;
 
-   memset(, 0, sizeof(sample));
-
if (test__arch_unwind_sample(, thread)) {
pr_debug("failed to get unwind sample\n");
goto out;
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index a62c09134516..86a8fdb41804 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -80,6 +80,7 @@ static struct {
 struct machine *setup_fake_machine(struct machines *machines)
 {
struct machine *machine = machines__find(machines, HOST_KERNEL_ID);
+   struct perf_sample sample = { .time = -1ULL, };
size_t i;
 
if (machine == NULL) {
@@ -113,7 +114,7 @@ struct machine *setup_fake_machine(struct machines 
*machines)
strcpy(fake_mmap_event.mmap.filename,
   fake_mmap_info[i].filename);
 
-   machine__process_mmap_event(machine, _mmap_event, NULL);
+   machine__process_mmap_event(machine, _mmap_event, );
}
 
for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index fe7cb886c23e..07f1d19b88b5 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -64,7 +64,7 @@ static int add_hist_entries(struct perf_evlist *evlist, 
struct machine *machine)
struct perf_evsel *evsel;
struct addr_location al;
struct hist_entry *he;
-   struct perf_sample sample = { .period = 1, };
+   struct perf_sample sample = { .period = 1, .time = -1ULL, };
size_t i = 0, k;
 
/*
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 

[PATCH 14/37] perf tools: Convert dead thread list into rbtree

2014-12-23 Thread Namhyung Kim
Currently perf maintains dead threads in a linked list but this can be
a problem if someone needs to search from it.  Convert it to a rbtree
like normal threads and it'll be used later with multi-file changes.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/util/machine.c | 59 +++
 tools/perf/util/machine.h |  2 +-
 tools/perf/util/thread.c  |  1 +
 tools/perf/util/thread.h  | 11 -
 4 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 15dd0a9691ce..582e011adc92 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -28,7 +28,7 @@ int machine__init(struct machine *machine, const char 
*root_dir, pid_t pid)
dsos__init(>kernel_dsos);
 
machine->threads = RB_ROOT;
-   INIT_LIST_HEAD(>dead_threads);
+   machine->dead_threads = RB_ROOT;
machine->last_match = NULL;
 
machine->vdso_info = NULL;
@@ -91,10 +91,21 @@ static void dsos__delete(struct dsos *dsos)
 
 void machine__delete_dead_threads(struct machine *machine)
 {
-   struct thread *n, *t;
+   struct rb_node *nd = rb_first(>dead_threads);
+
+   while (nd) {
+   struct thread *t = rb_entry(nd, struct thread, rb_node);
+   struct thread *pos;
+
+   nd = rb_next(nd);
+   rb_erase(>rb_node, >dead_threads);
+
+   while (!list_empty(>node)) {
+   pos = list_first_entry(>node, struct thread, node);
+   list_del(>node);
+   thread__delete(pos);
+   }
 
-   list_for_each_entry_safe(t, n, >dead_threads, node) {
-   list_del(>node);
thread__delete(t);
}
 }
@@ -106,8 +117,8 @@ void machine__delete_threads(struct machine *machine)
while (nd) {
struct thread *t = rb_entry(nd, struct thread, rb_node);
 
-   rb_erase(>rb_node, >threads);
nd = rb_next(nd);
+   rb_erase(>rb_node, >threads);
thread__delete(t);
}
 }
@@ -1236,13 +1247,36 @@ int machine__process_mmap_event(struct machine 
*machine, union perf_event *event
 
 static void machine__remove_thread(struct machine *machine, struct thread *th)
 {
+   struct rb_node **p = >dead_threads.rb_node;
+   struct rb_node *parent = NULL;
+   struct thread *pos;
+
machine->last_match = NULL;
rb_erase(>rb_node, >threads);
+
+   th->dead = true;
+
/*
 * We may have references to this thread, for instance in some 
hist_entry
-* instances, so just move them to a separate list.
+* instances, so just move them to a separate list in rbtree.
 */
-   list_add_tail(>node, >dead_threads);
+   while (*p != NULL) {
+   parent = *p;
+   pos = rb_entry(parent, struct thread, rb_node);
+
+   if (pos->tid == th->tid) {
+   list_add_tail(>node, >node);
+   return;
+   }
+
+   if (th->tid < pos->tid)
+   p = &(*p)->rb_left;
+   else
+   p = &(*p)->rb_right;
+   }
+
+   rb_link_node(>rb_node, parent, p);
+   rb_insert_color(>rb_node, >dead_threads);
 }
 
 int machine__process_fork_event(struct machine *machine, union perf_event 
*event,
@@ -1649,7 +1683,7 @@ int machine__for_each_thread(struct machine *machine,
 void *priv)
 {
struct rb_node *nd;
-   struct thread *thread;
+   struct thread *thread, *pos;
int rc = 0;
 
for (nd = rb_first(>threads); nd; nd = rb_next(nd)) {
@@ -1659,10 +1693,17 @@ int machine__for_each_thread(struct machine *machine,
return rc;
}
 
-   list_for_each_entry(thread, >dead_threads, node) {
+   for (nd = rb_first(>dead_threads); nd; nd = rb_next(nd)) {
+   thread = rb_entry(nd, struct thread, rb_node);
rc = fn(thread, priv);
if (rc != 0)
return rc;
+
+   list_for_each_entry(pos, >node, node) {
+   rc = fn(pos, priv);
+   if (rc != 0)
+   return rc;
+   }
}
return rc;
 }
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index e8b7779a0a3f..4349946a38ff 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -30,7 +30,7 @@ struct machine {
bool  comm_exec;
char  *root_dir;
struct rb_rootthreads;
-   struct list_head  dead_threads;
+   struct rb_rootdead_threads;
struct thread *last_match;
struct vdso_info  *vdso_info;
struct dsos   user_dsos;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 

[PATCH 13/37] perf tools: Use thread__comm_time() when adding hist entries

2014-12-23 Thread Namhyung Kim
Now thread->comm can be handled with time properly, use it to find
correct comm when adding hist entries.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-annotate.c |  5 +++--
 tools/perf/builtin-diff.c |  8 
 tools/perf/tests/hists_link.c |  4 ++--
 tools/perf/util/hist.c| 19 ++-
 tools/perf/util/hist.h|  2 +-
 5 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 747f86103599..a3b6d9d14925 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -47,7 +47,7 @@ struct perf_annotate {
 };
 
 static int perf_evsel__add_sample(struct perf_evsel *evsel,
- struct perf_sample *sample __maybe_unused,
+ struct perf_sample *sample,
  struct addr_location *al,
  struct perf_annotate *ann)
 {
@@ -67,7 +67,8 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
return 0;
}
 
-   he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true);
+   he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0,
+   sample->time, true);
if (he == NULL)
return -ENOMEM;
 
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 260b10c19ad6..2b86607a8571 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -312,10 +312,10 @@ static int formula_fprintf(struct hist_entry *he, struct 
hist_entry *pair,
 
 static int hists__add_entry(struct hists *hists,
struct addr_location *al, u64 period,
-   u64 weight, u64 transaction)
+   u64 weight, u64 transaction, u64 timestamp)
 {
if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
-  transaction, true) != NULL)
+  transaction, timestamp, true) != NULL)
return 0;
return -ENOMEM;
 }
@@ -335,8 +335,8 @@ static int diff__process_sample_event(struct perf_tool 
*tool __maybe_unused,
return -1;
}
 
-   if (hists__add_entry(hists, , sample->period,
-sample->weight, sample->transaction)) {
+   if (hists__add_entry(hists, , sample->period, sample->weight,
+sample->transaction, sample->time)) {
pr_warning("problem incrementing symbol period, skipping 
event\n");
return -1;
}
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 278ba8344c23..fe7cb886c23e 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -90,7 +90,7 @@ static int add_hist_entries(struct perf_evlist *evlist, 
struct machine *machine)
goto out;
 
he = __hists__add_entry(hists, , NULL,
-   NULL, NULL, 1, 1, 0, true);
+   NULL, NULL, 1, 1, 0, -1, true);
if (he == NULL)
goto out;
 
@@ -114,7 +114,7 @@ static int add_hist_entries(struct perf_evlist *evlist, 
struct machine *machine)
goto out;
 
he = __hists__add_entry(hists, , NULL,
-   NULL, NULL, 1, 1, 0, true);
+   NULL, NULL, 1, 1, 0, -1, true);
if (he == NULL)
goto out;
 
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9314286ed25c..d322264bac22 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -451,11 +451,11 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
  struct branch_info *bi,
  struct mem_info *mi,
  u64 period, u64 weight, u64 transaction,
- bool sample_self)
+ u64 timestamp, bool sample_self)
 {
struct hist_entry entry = {
.thread = al->thread,
-   .comm = thread__comm(al->thread),
+   .comm = thread__comm_time(al->thread, timestamp),
.ms = {
.map= al->map,
.sym= al->sym,
@@ -513,13 +513,14 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, 
struct addr_location *al
 {
u64 cost;
struct mem_info *mi = iter->priv;
+   struct perf_sample *sample = iter->sample;
struct hists *hists = evsel__hists(iter->evsel);
struct hist_entry *he;
 
if (mi == NULL)
return -EINVAL;
 
-   

Re: [PATCH] Drivers: bcma: Fix three coding style issues, more than 80 characters per line.

2014-12-23 Thread Kalle Valo
Oscar Forner Martinez  writes:

> Three lines with more than 80 characters per line have been split in several 
> lines.
>
> Signed-off-by: Oscar Forner Martinez 
> ---
>  drivers/bcma/driver_chipcommon.c | 10 +++---
>  1 file changed, 7 insertions(+), 3 deletions(-)

Just to handle the bureaucracy before v2 is submitted:

To which tree should this go to? I see that earlier John has applied
patches to drivers/bcma/, but what about now? Should I take these? John,
any suggestions?

Oscar, the patchwork entry for this patch looked odd. I'm guessing it
was because your time (or timezone) is wrong:

https://patchwork.kernel.org/patch/5535751/

-- 
Kalle Valo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 12/37] perf tools: Add a test case for thread comm handling

2014-12-23 Thread Namhyung Kim
The new test case checks various thread comm handling like overridding
and time sorting.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/Makefile.perf|  1 +
 tools/perf/tests/builtin-test.c |  4 
 tools/perf/tests/tests.h|  1 +
 tools/perf/tests/thread-comm.c  | 47 +
 4 files changed, 53 insertions(+)
 create mode 100644 tools/perf/tests/thread-comm.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 763e68fb5767..e4528a4a3a8c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -447,6 +447,7 @@ endif
 LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
 LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
 LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
+LIB_OBJS += $(OUTPUT)tests/thread-comm.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4b7d9ab0f049..1b463d82a71a 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -167,6 +167,10 @@ static struct test {
.func = test__fdarray__add,
},
{
+   .desc = "Test thread comm handling",
+   .func = test__thread_comm,
+   },
+   {
.func = NULL,
},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 00e776a87a9c..43ac17780629 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -51,6 +51,7 @@ int test__hists_cumulate(void);
 int test__switch_tracking(void);
 int test__fdarray__filter(void);
 int test__fdarray__add(void);
+int test__thread_comm(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-comm.c b/tools/perf/tests/thread-comm.c
new file mode 100644
index ..b81a429a6305
--- /dev/null
+++ b/tools/perf/tests/thread-comm.c
@@ -0,0 +1,47 @@
+#include "tests.h"
+#include "machine.h"
+#include "thread.h"
+#include "debug.h"
+
+int test__thread_comm(void)
+{
+   struct machines machines;
+   struct machine *machine;
+   struct thread *t;
+
+   /*
+* This test is to check whether it can retrieve a correct
+* comm for a given time.  When multi-file data storage is
+* enabled, those task/comm events are processed first so the
+* later sample should find a matching comm properly.
+*/
+   machines__init();
+   machine = 
+
+   t = machine__findnew_thread(machine, 100, 100);
+   TEST_ASSERT_VAL("wrong init thread comm",
+   !strcmp(thread__comm_str(t), ":100"));
+
+   thread__set_comm(t, "perf-test1", 1);
+   TEST_ASSERT_VAL("failed to override thread comm",
+   !strcmp(thread__comm_str(t), "perf-test1"));
+
+   thread__set_comm(t, "perf-test2", 2);
+   thread__set_comm(t, "perf-test3", 3);
+   thread__set_comm(t, "perf-test4", 4);
+
+   TEST_ASSERT_VAL("failed to find timed comm",
+   !strcmp(thread__comm_time_str(t, 2), "perf-test2"));
+   TEST_ASSERT_VAL("failed to find timed comm",
+   !strcmp(thread__comm_time_str(t, 35000), "perf-test3"));
+   TEST_ASSERT_VAL("failed to find timed comm",
+   !strcmp(thread__comm_time_str(t, 5), "perf-test4"));
+
+   thread__set_comm(t, "perf-test1.5", 15000);
+   TEST_ASSERT_VAL("failed to sort timed comm",
+   !strcmp(thread__comm_time_str(t, 15000), 
"perf-test1.5"));
+
+   machine__delete_threads(machine);
+   machines__exit();
+   return 0;
+}
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 20/37] perf tools: Add a test case for timed map groups handling

2014-12-23 Thread Namhyung Kim
A test case for verifying thread->mg and ->mg_list handling during
time change and new thread__find_addr_map_time() and friends.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/Makefile.perf  |  1 +
 tools/perf/tests/builtin-test.c   |  4 ++
 tools/perf/tests/tests.h  |  1 +
 tools/perf/tests/thread-mg-time.c | 88 +++
 4 files changed, 94 insertions(+)
 create mode 100644 tools/perf/tests/thread-mg-time.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 6094f0a10d8b..47d933454492 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -449,6 +449,7 @@ LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
 LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
 LIB_OBJS += $(OUTPUT)tests/thread-comm.o
 LIB_OBJS += $(OUTPUT)tests/thread-lookup-time.o
+LIB_OBJS += $(OUTPUT)tests/thread-mg-time.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index e4d335de19ea..8f61a7e291ee 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -175,6 +175,10 @@ static struct test {
.func = test__thread_lookup_time,
},
{
+   .desc = "Test thread map group handling with time",
+   .func = test__thread_mg_time,
+   },
+   {
.func = NULL,
},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 1090337f63e5..03557563f31d 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -53,6 +53,7 @@ int test__fdarray__filter(void);
 int test__fdarray__add(void);
 int test__thread_comm(void);
 int test__thread_lookup_time(void);
+int test__thread_mg_time(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-mg-time.c 
b/tools/perf/tests/thread-mg-time.c
new file mode 100644
index ..69fd13752c1d
--- /dev/null
+++ b/tools/perf/tests/thread-mg-time.c
@@ -0,0 +1,88 @@
+#include "tests.h"
+#include "machine.h"
+#include "thread.h"
+#include "map.h"
+#include "debug.h"
+
+#define PERF_MAP_START  0x4
+
+int test__thread_mg_time(void)
+{
+   struct machines machines;
+   struct machine *machine;
+   struct thread *t;
+   struct map_groups *mg;
+   struct map *map;
+   struct addr_location al = { .map = NULL, };
+
+   /*
+* This test is to check whether it can retrieve a correct map
+* for a given time.  When multi-file data storage is enabled,
+* those task/comm/mmap events are processed first so the
+* later sample should find a matching comm properly.
+*/
+   machines__init();
+   machine = 
+
+   t = machine__findnew_thread(machine, 0, 0);
+   mg = t->mg;
+
+   map = dso__new_map("/usr/bin/perf");
+   map->start = PERF_MAP_START;
+   map->end = PERF_MAP_START + 0x1000;
+
+   thread__insert_map(t, map);
+
+   if (verbose > 1)
+   map_groups__fprintf(t->mg, stderr);
+
+   thread__find_addr_map(t, PERF_RECORD_MISC_USER, MAP__FUNCTION,
+ PERF_MAP_START, );
+
+   TEST_ASSERT_VAL("cannot find mapping for perf", al.map != NULL);
+   TEST_ASSERT_VAL("non matched mapping found", al.map == map);
+   TEST_ASSERT_VAL("incorrect map groups", al.map->groups == mg);
+   TEST_ASSERT_VAL("incorrect map groups", al.map->groups == t->mg);
+
+   thread__find_addr_map_time(t, PERF_RECORD_MISC_USER,
+  MAP__FUNCTION, PERF_MAP_START, , -1ULL);
+
+   TEST_ASSERT_VAL("cannot find timed mapping for perf", al.map != NULL);
+   TEST_ASSERT_VAL("non matched timed mapping", al.map == map);
+   TEST_ASSERT_VAL("incorrect timed map groups", al.map->groups == mg);
+   TEST_ASSERT_VAL("incorrect map groups", al.map->groups == t->mg);
+
+
+   pr_debug("simulate EXEC event (generate new mg)\n");
+   __thread__set_comm(t, "perf-test", 1, true);
+
+   map = dso__new_map("/usr/bin/perf-test");
+   map->start = PERF_MAP_START;
+   map->end = PERF_MAP_START + 0x2000;
+
+   thread__insert_map(t, map);
+
+   if (verbose > 1)
+   map_groups__fprintf(t->mg, stderr);
+
+   thread__find_addr_map(t, PERF_RECORD_MISC_USER, MAP__FUNCTION,
+ PERF_MAP_START + 4, );
+
+   TEST_ASSERT_VAL("cannot find mapping for perf-test", al.map != NULL);
+   TEST_ASSERT_VAL("invalid mapping found", al.map == map);
+   TEST_ASSERT_VAL("incorrect map groups", al.map->groups != mg);
+   TEST_ASSERT_VAL("incorrect map groups", al.map->groups == t->mg);
+
+   pr_debug("searching map in the old mag groups\n");
+   thread__find_addr_map_time(t, PERF_RECORD_MISC_USER,
+  MAP__FUNCTION, PERF_MAP_START, , 

[PATCH 21/37] perf tools: Protect dso symbol loading using a mutex

2014-12-23 Thread Namhyung Kim
When multi-thread support for perf report is enabled, it's possible to
access a dso concurrently.  Add a new pthread_mutex to protect it from
concurrent dso__load().

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/dso.c|  2 ++
 tools/perf/util/dso.h|  1 +
 tools/perf/util/symbol.c | 34 --
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 45be944d450a..3da75816b8f8 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -888,6 +888,7 @@ struct dso *dso__new(const char *name)
RB_CLEAR_NODE(>rb_node);
INIT_LIST_HEAD(>node);
INIT_LIST_HEAD(>data.open_entry);
+   pthread_mutex_init(>lock, NULL);
}
 
return dso;
@@ -917,6 +918,7 @@ void dso__delete(struct dso *dso)
dso_cache__free(>data.cache);
dso__free_a2l(dso);
zfree(>symsrc_filename);
+   pthread_mutex_destroy(>lock);
free(dso);
 }
 
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 3782c82c6e44..ac753594a469 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -102,6 +102,7 @@ struct dsos {
 };
 
 struct dso {
+   pthread_mutex_t  lock;
struct list_head node;
struct rb_node   rb_node;   /* rbtree node sorted by long name */
struct rb_root   symbols[MAP__NR_TYPES];
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c24c5b83156c..6c764a5b3464 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1332,12 +1332,22 @@ int dso__load(struct dso *dso, struct map *map, 
symbol_filter_t filter)
struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
bool kmod;
 
-   dso__set_loaded(dso, map->type);
+   pthread_mutex_lock(>lock);
+
+   /* check again under the dso->lock */
+   if (dso__loaded(dso, map->type)) {
+   ret = 1;
+   goto out;
+   }
+
+   if (dso->kernel) {
+   if (dso->kernel == DSO_TYPE_KERNEL)
+   ret = dso__load_kernel_sym(dso, map, filter);
+   else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
+   ret = dso__load_guest_kernel_sym(dso, map, filter);
 
-   if (dso->kernel == DSO_TYPE_KERNEL)
-   return dso__load_kernel_sym(dso, map, filter);
-   else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
-   return dso__load_guest_kernel_sym(dso, map, filter);
+   goto out;
+   }
 
if (map->groups && map->groups->machine)
machine = map->groups->machine;
@@ -1350,18 +1360,18 @@ int dso__load(struct dso *dso, struct map *map, 
symbol_filter_t filter)
struct stat st;
 
if (lstat(dso->name, ) < 0)
-   return -1;
+   goto out;
 
if (st.st_uid && (st.st_uid != geteuid())) {
pr_warning("File %s not owned by current user or root, "
"ignoring it.\n", dso->name);
-   return -1;
+   goto out;
}
 
ret = dso__load_perf_map(dso, map, filter);
dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
 DSO_BINARY_TYPE__NOT_FOUND;
-   return ret;
+   goto out;
}
 
if (machine)
@@ -1369,7 +1379,7 @@ int dso__load(struct dso *dso, struct map *map, 
symbol_filter_t filter)
 
name = malloc(PATH_MAX);
if (!name)
-   return -1;
+   goto out;
 
kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
@@ -1450,7 +1460,11 @@ int dso__load(struct dso *dso, struct map *map, 
symbol_filter_t filter)
 out_free:
free(name);
if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
-   return 0;
+   ret = 0;
+out:
+   dso__set_loaded(dso, map->type);
+   pthread_mutex_unlock(>lock);
+
return ret;
 }
 
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 22/37] perf tools: Protect dso cache tree using dso->lock

2014-12-23 Thread Namhyung Kim
The dso cache is accessed during dwarf callchain unwind and it might
be processed concurrently when multi-thread report is enabled.
Protect it under dso->lock.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/dso.c | 41 -
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 3da75816b8f8..9555b1772fb5 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -443,10 +443,12 @@ bool dso__data_status_seen(struct dso *dso, enum 
dso_data_status_seen by)
 }
 
 static void
-dso_cache__free(struct rb_root *root)
+dso_cache__free(struct dso *dso)
 {
+   struct rb_root *root = >data.cache;
struct rb_node *next = rb_first(root);
 
+   pthread_mutex_lock(>lock);
while (next) {
struct dso_cache *cache;
 
@@ -455,14 +457,17 @@ dso_cache__free(struct rb_root *root)
rb_erase(>rb_node, root);
free(cache);
}
+   pthread_mutex_unlock(>lock);
 }
 
-static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 
offset)
+static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset)
 {
+   const struct rb_root *root = >data.cache;
struct rb_node * const *p = >rb_node;
const struct rb_node *parent = NULL;
struct dso_cache *cache;
 
+   pthread_mutex_lock(>lock);
while (*p != NULL) {
u64 end;
 
@@ -475,19 +480,24 @@ static struct dso_cache *dso_cache__find(const struct 
rb_root *root, u64 offset)
else if (offset >= end)
p = &(*p)->rb_right;
else
-   return cache;
+   goto out;
}
-   return NULL;
+   cache = NULL;
+out:
+   pthread_mutex_unlock(>lock);
+   return cache;
 }
 
-static void
-dso_cache__insert(struct rb_root *root, struct dso_cache *new)
+static struct dso_cache *
+dso_cache__insert(struct dso *dso, struct dso_cache *new)
 {
+   struct rb_root *root = >data.cache;
struct rb_node **p = >rb_node;
struct rb_node *parent = NULL;
struct dso_cache *cache;
u64 offset = new->offset;
 
+   pthread_mutex_lock(>lock);
while (*p != NULL) {
u64 end;
 
@@ -499,10 +509,17 @@ dso_cache__insert(struct rb_root *root, struct dso_cache 
*new)
p = &(*p)->rb_left;
else if (offset >= end)
p = &(*p)->rb_right;
+   else
+   goto out;
}
 
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, root);
+
+   cache = NULL;
+out:
+   pthread_mutex_unlock(>lock);
+   return cache;
 }
 
 static ssize_t
@@ -520,6 +537,7 @@ static ssize_t
 dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
 {
struct dso_cache *cache;
+   struct dso_cache *old;
ssize_t ret;
 
do {
@@ -543,7 +561,12 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, 
ssize_t size)
 
cache->offset = cache_offset;
cache->size   = ret;
-   dso_cache__insert(>data.cache, cache);
+   old = dso_cache__insert(dso, cache);
+   if (old) {
+   /* we lose the race */
+   free(cache);
+   cache = old;
+   }
 
ret = dso_cache__memcpy(cache, offset, data, size);
 
@@ -560,7 +583,7 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset,
 {
struct dso_cache *cache;
 
-   cache = dso_cache__find(>data.cache, offset);
+   cache = dso_cache__find(dso, offset);
if (cache)
return dso_cache__memcpy(cache, offset, data, size);
else
@@ -915,7 +938,7 @@ void dso__delete(struct dso *dso)
}
 
dso__data_close(dso);
-   dso_cache__free(>data.cache);
+   dso_cache__free(dso);
dso__free_a2l(dso);
zfree(>symsrc_filename);
pthread_mutex_destroy(>lock);
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 29/37] perf top: Always creates thread in the current task tree.

2014-12-23 Thread Namhyung Kim
When machine__findnew_thread_time() creates a new thread, it puts the
thread in the missing_threads tree assuming it's rare case that missed
related task/mmap events during the recorded header file.

However this is not the case of live profiling - so it should be
treated differently.  This patch fixes NULL thread->mg reference in
case of missing threads in live profiling.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-top.c |  5 -
 tools/perf/util/event.c  | 24 ++--
 tools/perf/util/event.h  |  5 +
 3 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 818ae35cbd7b..2d75a7fab470 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -699,6 +699,7 @@ static void perf_event__process_sample(struct perf_tool 
*tool,
 {
struct perf_top *top = container_of(tool, struct perf_top, tool);
struct addr_location al;
+   struct thread *thread;
int err;
 
if (!machine && perf_guest) {
@@ -724,7 +725,9 @@ static void perf_event__process_sample(struct perf_tool 
*tool,
if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
top->exact_samples++;
 
-   if (perf_event__preprocess_sample(event, machine, , sample) < 0)
+   /* Always use current thread tree for live profiling */
+   thread = machine__findnew_thread(machine, sample->pid, sample->tid);
+   if (__perf_event__preprocess_sample(event, machine, thread, , 
sample) < 0)
return;
 
if (!top->kptr_restrict_warned &&
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 3bb186a26314..452af8f4b0f3 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -863,14 +863,13 @@ void thread__find_addr_location_time(struct thread 
*thread, u8 cpumode,
al->sym = NULL;
 }
 
-int perf_event__preprocess_sample(const union perf_event *event,
- struct machine *machine,
- struct addr_location *al,
- struct perf_sample *sample)
+int __perf_event__preprocess_sample(const union perf_event *event,
+   struct machine *machine,
+   struct thread *thread,
+   struct addr_location *al,
+   struct perf_sample *sample)
 {
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-   struct thread *thread = machine__findnew_thread_time(machine, 
sample->pid,
-sample->tid, 
sample->time);
 
if (thread == NULL)
return -1;
@@ -928,6 +927,19 @@ int perf_event__preprocess_sample(const union perf_event 
*event,
return 0;
 }
 
+int perf_event__preprocess_sample(const union perf_event *event,
+ struct machine *machine,
+ struct addr_location *al,
+ struct perf_sample *sample)
+{
+   struct thread *thread;
+
+   thread = machine__findnew_thread_time(machine, sample->pid,
+ sample->tid, sample->time);
+   return __perf_event__preprocess_sample(event, machine, thread,
+  al, sample);
+}
+
 bool is_bts_event(struct perf_event_attr *attr)
 {
return attr->type == PERF_TYPE_HARDWARE &&
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 5f66abfa61ca..1fbd37864241 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -352,6 +352,11 @@ int perf_event__process(struct perf_tool *tool,
 
 struct addr_location;
 
+int __perf_event__preprocess_sample(const union perf_event *event,
+   struct machine *machine,
+   struct thread *thread,
+   struct addr_location *al,
+   struct perf_sample *sample);
 int perf_event__preprocess_sample(const union perf_event *event,
  struct machine *machine,
  struct addr_location *al,
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 27/37] perf report: Parallelize perf report using multi-thread

2014-12-23 Thread Namhyung Kim
Introduce perf_session__process_events_mt() to enable multi-thread
sample processing.  It allocates a struct perf_tool_mt and fills
needed info in it.  The init and fini callbacks are provided so that
we can pass additional data structure if needed.

The session and hists event stats are counted for each thread and
summed after finishing the processing.  Similarly hist entries are
added to per-thread hists first and then move to the original hists
using hists__multi_resort().  This function reuses hists__collapse_
resort() code so makes sort__need_collapse force to true and skips
the collapsing function.

Note that most of preprocessing stage is already done by processing
meta events in dummy tracking evsel first.  We can find corresponding
thread and map based on the sample time and symbol loading and dso
cache access is protected by pthread mutex.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-report.c |  90 +--
 tools/perf/util/hist.c  |  75 +++
 tools/perf/util/hist.h  |   3 +
 tools/perf/util/session.c   | 146 
 tools/perf/util/session.h   |   4 ++
 tools/perf/util/tool.h  |  14 +
 6 files changed, 302 insertions(+), 30 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index aabcfc24afd1..796db514db31 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -128,18 +128,16 @@ static int hist_iter__report_callback(struct 
hist_entry_iter *iter,
return err;
 }
 
-static int process_sample_event(struct perf_tool *tool,
-   union perf_event *event,
-   struct perf_sample *sample,
-   struct perf_evsel *evsel,
-   struct machine *machine)
+static int __process_sample_event(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine,
+ struct hist_entry_iter *iter,
+ struct hists *hists,
+ struct report *rep)
 {
-   struct report *rep = container_of(tool, struct report, tool);
struct addr_location al;
-   struct hist_entry_iter iter = {
-   .hide_unresolved = rep->hide_unresolved,
-   .add_entry_cb = hist_iter__report_callback,
-   };
int ret;
 
if (perf_event__preprocess_sample(event, machine, , sample) < 0) {
@@ -155,18 +153,18 @@ static int process_sample_event(struct perf_tool *tool,
return 0;
 
if (sort__mode == SORT_MODE__BRANCH)
-   iter.ops = _iter_branch;
+   iter->ops = _iter_branch;
else if (rep->mem_mode)
-   iter.ops = _iter_mem;
+   iter->ops = _iter_mem;
else if (symbol_conf.cumulate_callchain)
-   iter.ops = _iter_cumulative;
+   iter->ops = _iter_cumulative;
else
-   iter.ops = _iter_normal;
+   iter->ops = _iter_normal;
 
if (al.map != NULL)
al.map->dso->hit = 1;
 
-   ret = hist_entry_iter__add(, evsel__hists(evsel), evsel, ,
+   ret = hist_entry_iter__add(iter, hists, evsel, ,
   sample, rep->max_stack, rep);
if (ret < 0)
pr_debug("problem adding hist entry, skipping event\n");
@@ -174,6 +172,52 @@ static int process_sample_event(struct perf_tool *tool,
return ret;
 }
 
+static int process_sample_event(struct perf_tool *tool,
+   union perf_event *event,
+   struct perf_sample *sample,
+   struct perf_evsel *evsel,
+   struct machine *machine)
+{
+   struct report *rep = container_of(tool, struct report, tool);
+   struct hist_entry_iter iter = {
+   .hide_unresolved = rep->hide_unresolved,
+   .add_entry_cb = hist_iter__report_callback,
+   };
+
+   return __process_sample_event(tool, event, sample, evsel, machine,
+ , evsel__hists(evsel), rep);
+}
+
+static int process_sample_event_multi(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine)
+{
+   struct perf_tool_mt *mt = container_of(tool, struct perf_tool_mt, tool);
+   struct report *rep = mt->priv;
+   struct hist_entry_iter iter = {
+   .hide_unresolved = rep->hide_unresolved,
+   };
+
+   return 

[PATCH 26/37] perf tools: Move BUILD_ID_SIZE definition to perf.h

2014-12-23 Thread Namhyung Kim
The util/event.h includes util/build-id.h only for BUILD_ID_SIZE.
This is a problem when I include util/event.h from util/tool.h which
is also included by util/build-id.h since it now makes a circular
dependency resulting in incomplete type error.

Signed-off-by: Namhyung Kim 
---
 tools/perf/perf.h  | 1 +
 tools/perf/util/build-id.h | 2 --
 tools/perf/util/dso.h  | 1 +
 tools/perf/util/event.h| 1 -
 4 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 37284eb47b56..56ce258314fc 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -30,6 +30,7 @@ static inline unsigned long long rdclock(void)
 }
 
 #define MAX_NR_CPUS256
+#define BUILD_ID_SIZE  20
 
 extern const char *input_name;
 extern bool perf_host, perf_guest;
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 8236319514d5..8f31545edc5b 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -1,8 +1,6 @@
 #ifndef PERF_BUILD_ID_H_
 #define PERF_BUILD_ID_H_ 1
 
-#define BUILD_ID_SIZE 20
-
 #include "tool.h"
 #include 
 
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ac753594a469..c18fcc0e8081 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include "map.h"
+#include "perf.h"
 #include "build-id.h"
 
 enum dso_binary_type {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 09b9e8d3fcf7..5f66abfa61ca 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -6,7 +6,6 @@
 
 #include "../perf.h"
 #include "map.h"
-#include "build-id.h"
 #include "perf_regs.h"
 
 struct mmap_event {
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 31/37] perf record: Show total size of multi file data

2014-12-23 Thread Namhyung Kim
Currently perf record shows header file size only - extends it to show
total size of multi-file data storage.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-record.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 7f7a4725d080..eb485f1ee66e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -538,9 +538,9 @@ static int __cmd_record(struct record *rec, int argc, const 
char **argv)
 */
fprintf(stderr,
"[ perf record: Captured and wrote %.3f MB %s (~%" 
PRIu64 " samples) ]\n",
-   (double)rec->bytes_written / 1024.0 / 1024.0,
+   (double)(u64)perf_data_file__multi_size(file) / 1024.0 
/ 1024.0,
file->path,
-   rec->bytes_written / 24);
+   perf_data_file__multi_size(file) / 24);
}
 
 out_child:
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 23/37] perf tools: Protect dso cache fd with a mutex

2014-12-23 Thread Namhyung Kim
When dso cache is accessed in multi-thread environment, it's possible
to close other dso->data.fd during operation due to open file limit.
Protect the file descriptors using a separate mutex.

Signed-off-by: Namhyung Kim 
---
 tools/perf/tests/dso-data.c |   5 ++
 tools/perf/util/dso.c   | 136 +---
 2 files changed, 94 insertions(+), 47 deletions(-)

diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index caaf37f079b1..0276e7d2d41b 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -111,6 +111,9 @@ int test__dso_data(void)
memset(, 0, sizeof(machine));
 
dso = dso__new((const char *)file);
+   TEST_ASSERT_VAL("failed to get dso", dso);
+
+   dso->binary_type = DSO_BINARY_TYPE__SYSTEM_PATH_DSO;
 
/* Basic 10 bytes tests. */
for (i = 0; i < ARRAY_SIZE(offsets); i++) {
@@ -199,6 +202,8 @@ static int dsos__create(int cnt, int size)
 
dsos[i] = dso__new(file);
TEST_ASSERT_VAL("failed to get dso", dsos[i]);
+
+   dsos[i]->binary_type = DSO_BINARY_TYPE__SYSTEM_PATH_DSO;
}
 
return 0;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 9555b1772fb5..6c1f5619f423 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -213,6 +213,7 @@ bool dso__needs_decompress(struct dso *dso)
  */
 static LIST_HEAD(dso__data_open);
 static long dso__data_open_cnt;
+static pthread_mutex_t dso__data_open_lock = PTHREAD_MUTEX_INITIALIZER;
 
 static void dso__list_add(struct dso *dso)
 {
@@ -240,7 +241,7 @@ static int do_open(char *name)
if (fd >= 0)
return fd;
 
-   pr_debug("dso open failed, mmap: %s\n",
+   pr_debug("dso open failed: %s\n",
 strerror_r(errno, sbuf, sizeof(sbuf)));
if (!dso__data_open_cnt || errno != EMFILE)
break;
@@ -382,7 +383,9 @@ static void check_data_close(void)
  */
 void dso__data_close(struct dso *dso)
 {
+   pthread_mutex_lock(__data_open_lock);
close_dso(dso);
+   pthread_mutex_unlock(__data_open_lock);
 }
 
 /**
@@ -405,6 +408,8 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
if (dso->data.status == DSO_DATA_STATUS_ERROR)
return -1;
 
+   pthread_mutex_lock(__data_open_lock);
+
if (dso->data.fd >= 0)
goto out;
 
@@ -427,6 +432,7 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
else
dso->data.status = DSO_DATA_STATUS_ERROR;
 
+   pthread_mutex_unlock(__data_open_lock);
return dso->data.fd;
 }
 
@@ -534,52 +540,66 @@ dso_cache__memcpy(struct dso_cache *cache, u64 offset,
 }
 
 static ssize_t
-dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
+dso_cache__read(struct dso *dso, struct machine *machine,
+   u64 offset, u8 *data, ssize_t size)
 {
struct dso_cache *cache;
struct dso_cache *old;
-   ssize_t ret;
-
-   do {
-   u64 cache_offset;
+   ssize_t ret = -EINVAL;
+   u64 cache_offset;
 
-   ret = -ENOMEM;
+   cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
+   if (!cache)
+   return -ENOMEM;
 
-   cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
-   if (!cache)
-   break;
+   cache_offset = offset & DSO__DATA_CACHE_MASK;
 
-   cache_offset = offset & DSO__DATA_CACHE_MASK;
-   ret = -EINVAL;
+   pthread_mutex_lock(__data_open_lock);
 
-   if (-1 == lseek(dso->data.fd, cache_offset, SEEK_SET))
-   break;
+   /*
+* dso->data.fd might be closed if other thread opened another
+* file (dso) due to open file limit (RLIMIT_NOFILE).
+*/
+   if (dso->data.fd < 0) {
+   dso->data.fd = open_dso(dso, machine);
+   if (dso->data.fd < 0) {
+   ret = -errno;
+   dso->data.status = DSO_DATA_STATUS_ERROR;
+   goto err_unlock;
+   }
+   }
 
-   ret = read(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE);
-   if (ret <= 0)
-   break;
+   if (-1 == lseek(dso->data.fd, cache_offset, SEEK_SET))
+   goto err_unlock;
 
-   cache->offset = cache_offset;
-   cache->size   = ret;
-   old = dso_cache__insert(dso, cache);
-   if (old) {
-   /* we lose the race */
-   free(cache);
-   cache = old;
-   }
+   ret = read(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE);
+   if (ret <= 0)
+   goto err_unlock;
 
-   ret = dso_cache__memcpy(cache, offset, data, size);
+   

[PATCH 32/37] perf report: Add --multi-thread option and config item

2014-12-23 Thread Namhyung Kim
The --multi-thread option is to enable parallel processing so user can
force serial processing even for multi-file data.  It default to false
but users also can changes this by setting "report.multi_thread"
config option in ~/.perfconfig file.

Signed-off-by: Namhyung Kim 
---
 tools/perf/Documentation/perf-report.txt |  3 +++
 tools/perf/builtin-report.c  | 18 +++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt 
b/tools/perf/Documentation/perf-report.txt
index dd7cccdde498..e00077a658c1 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -318,6 +318,9 @@ OPTIONS
 --header-only::
Show only perf.data header (forces --stdio).
 
+--multi-thread::
+   Speed up report by parallelizing sample processing using multi-thread.
+
 SEE ALSO
 
 linkperf:perf-stat[1], linkperf:perf-annotate[1]
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 796db514db31..6e260eaf3b1a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -51,6 +51,7 @@ struct report {
boolmem_mode;
boolheader;
boolheader_only;
+   boolmulti_thread;
int max_stack;
struct perf_read_values show_threads_values;
const char  *pretty_printing_style;
@@ -82,6 +83,10 @@ static int report__config(const char *var, const char 
*value, void *cb)
rep->queue_size = perf_config_u64(var, value);
return 0;
}
+   if (!strcmp(var, "report.multi-thread")) {
+   rep->multi_thread = perf_config_bool(var, value);
+   return 0;
+   }
 
return perf_default_config(var, value, cb);
 }
@@ -527,7 +532,7 @@ static int __cmd_report(struct report *rep)
if (ret)
return ret;
 
-   if (file->is_multi) {
+   if (rep->multi_thread) {
rep->tool.sample = process_sample_event_multi;
ret = perf_session__process_events_mt(session, >tool,
  multi_report_init,
@@ -558,10 +563,10 @@ static int __cmd_report(struct report *rep)
}
 
/*
-* For multi-file report, it already calls hists__multi_resort()
+* For multi-thread report, it already calls hists__multi_resort()
 * so no need to collapse here.
 */
-   if (!file->is_multi)
+   if (!rep->multi_thread)
report__collapse_hists(rep);
 
if (session_done())
@@ -770,6 +775,8 @@ int cmd_report(int argc, const char **argv, const char 
*prefix __maybe_unused)
 "Don't show entries under that percent", 
parse_percent_limit),
OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
 "how to display percentage of filtered entries", 
parse_filter_percentage),
+   OPT_BOOLEAN(0, "multi-thread", _thread,
+   "Speed up sample processing using multi-thead"),
OPT_END()
};
struct perf_data_file file = {
@@ -814,6 +821,11 @@ int cmd_report(int argc, const char **argv, const char 
*prefix __maybe_unused)
   report.queue_size);
}
 
+   if (report.multi_thread && !file.is_multi) {
+   pr_debug("fallback to single thread for single data file.\n");
+   report.multi_thread = false;
+   }
+
report.session = session;
 
has_br_stack = perf_header__has_feat(>header,
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 34/37] perf tools: Convert lseek + read to pread

2014-12-23 Thread Namhyung Kim
When dso_cache__read() is called, it reads data from the given offset
using lseek + normal read syscall.  It can be combined to a single
pread syscall.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/dso.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d8ee1fd826e7..95c8d5a2b934 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -593,10 +593,7 @@ dso_cache__read(struct dso *dso, struct machine *machine,
}
}
 
-   if (-1 == lseek(dso->data.fd, cache_offset, SEEK_SET))
-   goto err_unlock;
-
-   ret = read(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE);
+   ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, 
cache_offset);
if (ret <= 0)
goto err_unlock;
 
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 25/37] perf hists: Pass hists struct to hist_entry_iter functions

2014-12-23 Thread Namhyung Kim
This is a preparation for perf report multi-thread support.  When
multi-thread is enable, each thread will have its own hists during the
sample processing.

Signed-off-by: Namhyung Kim 
---
 tools/perf/builtin-report.c   |  4 ++--
 tools/perf/builtin-top.c  |  4 ++--
 tools/perf/tests/hists_cumulate.c |  4 ++--
 tools/perf/tests/hists_filter.c   |  3 ++-
 tools/perf/tests/hists_output.c   |  4 ++--
 tools/perf/util/hist.c| 26 +++---
 tools/perf/util/hist.h|  6 --
 7 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4cac79ad3085..aabcfc24afd1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -166,8 +166,8 @@ static int process_sample_event(struct perf_tool *tool,
if (al.map != NULL)
al.map->dso->hit = 1;
 
-   ret = hist_entry_iter__add(, , evsel, sample, rep->max_stack,
-  rep);
+   ret = hist_entry_iter__add(, evsel__hists(evsel), evsel, ,
+  sample, rep->max_stack, rep);
if (ret < 0)
pr_debug("problem adding hist entry, skipping event\n");
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 961cea183a83..818ae35cbd7b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -784,8 +784,8 @@ static void perf_event__process_sample(struct perf_tool 
*tool,
 
pthread_mutex_lock(>lock);
 
-   err = hist_entry_iter__add(, , evsel, sample,
-  top->max_stack, top);
+   err = hist_entry_iter__add(, evsel__hists(evsel), evsel,
+  , sample, top->max_stack, top);
if (err < 0)
pr_err("Problem incrementing symbol period, skipping 
event\n");
 
diff --git a/tools/perf/tests/hists_cumulate.c 
b/tools/perf/tests/hists_cumulate.c
index 4b8226e19a91..b1a2bed721a8 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -104,8 +104,8 @@ static int add_hist_entries(struct hists *hists, struct 
machine *machine)
  ) < 0)
goto out;
 
-   if (hist_entry_iter__add(, , evsel, ,
-PERF_MAX_STACK_DEPTH, NULL) < 0)
+   if (hist_entry_iter__add(, evsel__hists(evsel), evsel, ,
+, PERF_MAX_STACK_DEPTH, NULL) < 
0)
goto out;
 
fake_samples[i].thread = al.thread;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 59e53db7914c..3c54264ec58d 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -81,7 +81,8 @@ static int add_hist_entries(struct perf_evlist *evlist,
  ) < 0)
goto out;
 
-   if (hist_entry_iter__add(, , evsel, ,
+   if (hist_entry_iter__add(, evsel__hists(evsel),
+evsel, , ,
 PERF_MAX_STACK_DEPTH, NULL) < 
0)
goto out;
 
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index f5547610da02..c705bc7a5e78 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -70,8 +70,8 @@ static int add_hist_entries(struct hists *hists, struct 
machine *machine)
  ) < 0)
goto out;
 
-   if (hist_entry_iter__add(, , evsel, ,
-PERF_MAX_STACK_DEPTH, NULL) < 0)
+   if (hist_entry_iter__add(, evsel__hists(evsel), evsel, ,
+, PERF_MAX_STACK_DEPTH, NULL) < 
0)
goto out;
 
fake_samples[i].thread = al.thread;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index d322264bac22..d7cee7165bcd 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -514,7 +514,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, 
struct addr_location *al
u64 cost;
struct mem_info *mi = iter->priv;
struct perf_sample *sample = iter->sample;
-   struct hists *hists = evsel__hists(iter->evsel);
+   struct hists *hists = iter->hists;
struct hist_entry *he;
 
if (mi == NULL)
@@ -544,8 +544,7 @@ static int
 iter_finish_mem_entry(struct hist_entry_iter *iter,
  struct addr_location *al __maybe_unused)
 {
-   struct perf_evsel *evsel = iter->evsel;
-   struct hists *hists = evsel__hists(evsel);
+   struct hists *hists = iter->hists;
struct hist_entry *he = 

[PATCH 33/37] perf tools: Add front cache for dso data access

2014-12-23 Thread Namhyung Kim
There's a high contention in dso_cache__find() due to the dso->lock
when dwarf unwinding is done with libunwind.  Add last accessed
pointers of dso_cache to lockless lookup.  It'll fallback to normal
tree search when it misses the last cache.

The size 16 is arbitrary and works best for my setting.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/dso.c | 28 ++--
 tools/perf/util/dso.h |  2 ++
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 6c1f5619f423..d8ee1fd826e7 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -466,12 +466,31 @@ dso_cache__free(struct dso *dso)
pthread_mutex_unlock(>lock);
 }
 
+static void update_last_cache(struct dso *dso, struct dso_cache *cache)
+{
+   int i;
+
+   for (i = DSO_LAST_CACHE_NR - 1; i > 0; i--)
+   dso->data.last[i] = dso->data.last[i-1];
+
+   dso->data.last[0] = cache;
+}
+
 static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset)
 {
const struct rb_root *root = >data.cache;
struct rb_node * const *p = >rb_node;
const struct rb_node *parent = NULL;
struct dso_cache *cache;
+   int i;
+
+   for (i = 0; i < DSO_LAST_CACHE_NR; i++) {
+   cache = dso->data.last[i];
+
+   if (cache && cache->offset <= offset &&
+   offset < cache->offset + DSO__DATA_CACHE_SIZE)
+   return cache;
+   }
 
pthread_mutex_lock(>lock);
while (*p != NULL) {
@@ -485,8 +504,10 @@ static struct dso_cache *dso_cache__find(struct dso *dso, 
u64 offset)
p = &(*p)->rb_left;
else if (offset >= end)
p = &(*p)->rb_right;
-   else
+   else {
+   update_last_cache(dso, cache);
goto out;
+   }
}
cache = NULL;
 out:
@@ -515,13 +536,16 @@ dso_cache__insert(struct dso *dso, struct dso_cache *new)
p = &(*p)->rb_left;
else if (offset >= end)
p = &(*p)->rb_right;
-   else
+   else {
+   update_last_cache(dso, cache);
goto out;
+   }
}
 
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, root);
 
+   update_last_cache(dso, new);
cache = NULL;
 out:
pthread_mutex_unlock(>lock);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index c18fcc0e8081..28e8bb320495 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -136,6 +136,8 @@ struct dso {
/* dso data file */
struct {
struct rb_root   cache;
+#define DSO_LAST_CACHE_NR  16
+   struct dso_cache *last[DSO_LAST_CACHE_NR];
int  fd;
int  status;
u32  status_seen;
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 28/37] perf tools: Add missing_threads rb tree

2014-12-23 Thread Namhyung Kim
Sometimes it's possible to miss certain meta events like fork/exit and
in this case it can fail to find such thread in the machine's rbtree.
But adding a thread to the tree is dangerous since it's now executed
in multi-thread environment otherwise it'll add an overhead in order
to grab a lock for every search.  So adds a separate missing_threads
tree and protect it with a mutex.  It's expected to be accessed only
if a thread is not found in a normal tree.

Signed-off-by: Namhyung Kim 
---
 tools/perf/tests/thread-lookup-time.c |  8 ++-
 tools/perf/util/build-id.c|  9 +++-
 tools/perf/util/machine.c | 91 +++
 tools/perf/util/machine.h |  2 +
 tools/perf/util/session.c |  8 +--
 tools/perf/util/thread.h  |  1 +
 6 files changed, 80 insertions(+), 39 deletions(-)

diff --git a/tools/perf/tests/thread-lookup-time.c 
b/tools/perf/tests/thread-lookup-time.c
index 6237ecf8caae..04cdde9329d6 100644
--- a/tools/perf/tests/thread-lookup-time.c
+++ b/tools/perf/tests/thread-lookup-time.c
@@ -7,7 +7,9 @@
 static int thread__print_cb(struct thread *th, void *arg __maybe_unused)
 {
printf("thread: %d, start time: %"PRIu64" %s\n",
-  th->tid, th->start_time, th->dead ? "(dead)" : "");
+  th->tid, th->start_time,
+  th->dead ? "(dead)" : th->exited ? "(exited)" :
+  th->missing ? "(missing)" : "");
return 0;
 }
 
@@ -105,6 +107,8 @@ static int lookup_with_timestamp(struct machine *machine)
machine__findnew_thread_time(machine, 0, 0, 7) == 
t3);
 
machine__delete_threads(machine);
+   machine__delete_dead_threads(machine);
+   machine__delete_missing_threads(machine);
return 0;
 }
 
@@ -146,6 +150,8 @@ static int lookup_without_timestamp(struct machine *machine)
machine__findnew_thread_time(machine, 0, 0, -1ULL) == 
t3);
 
machine__delete_threads(machine);
+   machine__delete_dead_threads(machine);
+   machine__delete_missing_threads(machine);
return 0;
 }
 
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0c72680a977f..98446d089b08 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -60,7 +60,14 @@ static int perf_event__exit_del_thread(struct perf_tool 
*tool __maybe_unused,
event->fork.ppid, event->fork.ptid);
 
if (thread) {
-   rb_erase(>rb_node, >threads);
+   if (thread->dead)
+   rb_erase(>rb_node, >dead_threads);
+   else if (thread->missing)
+   rb_erase(>rb_node, >missing_threads);
+   else
+   rb_erase(>rb_node, >threads);
+
+   list_del(>node);
machine->last_match = NULL;
thread__delete(thread);
}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index ffce0bcd2d9a..c7492d4fde29 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -29,6 +29,7 @@ int machine__init(struct machine *machine, const char 
*root_dir, pid_t pid)
 
machine->threads = RB_ROOT;
machine->dead_threads = RB_ROOT;
+   machine->missing_threads = RB_ROOT;
machine->last_match = NULL;
 
machine->vdso_info = NULL;
@@ -89,6 +90,19 @@ static void dsos__delete(struct dsos *dsos)
}
 }
 
+void machine__delete_missing_threads(struct machine *machine)
+{
+   struct rb_node *nd = rb_first(>missing_threads);
+
+   while (nd) {
+   struct thread *t = rb_entry(nd, struct thread, rb_node);
+
+   nd = rb_next(nd);
+   rb_erase(>rb_node, >missing_threads);
+   thread__delete(t);
+   }
+}
+
 void machine__delete_dead_threads(struct machine *machine)
 {
struct rb_node *nd = rb_first(>dead_threads);
@@ -438,11 +452,12 @@ static struct thread 
*__machine__findnew_thread_time(struct machine *machine,
 pid_t pid, pid_t tid,
 u64 timestamp, bool create)
 {
-   struct thread *curr, *pos, *new;
+   struct thread *curr, *pos, *new = NULL;
struct thread *th = NULL;
struct rb_node **p;
struct rb_node *parent = NULL;
bool initial = timestamp == (u64)0;
+   static pthread_mutex_t missing_thread_lock = PTHREAD_MUTEX_INITIALIZER;
 
curr = __machine__findnew_thread(machine, pid, tid, initial);
if (curr && timestamp >= curr->start_time)
@@ -475,44 +490,49 @@ static struct thread 
*__machine__findnew_thread_time(struct machine *machine,
p = &(*p)->rb_right;
}
 
-   if (!create)
-   return NULL;
-
-   if (!curr)
-   return __machine__findnew_thread(machine, pid, tid, true);
+   pthread_mutex_lock(_thread_lock);
 
-  

[PATCH 35/37] perf callchain: Save eh/debug frame offset for dwarf unwind

2014-12-23 Thread Namhyung Kim
When libunwind tries to resolve callchains it needs to know the offset
of .eh_frame_hdr or .debug_frame to access the dso.  Since it calls
dso__data_fd(), it'll try to grab dso->lock everytime for same
information.  So save it to dso_data struct and reuse it.

Note that there's a window between dso__data_fd() and actual use of
the fd.  The fd could be closed by other threads to deal with the open
file limit in dso cache code.  But I think it's ok since in that case
elf_section_offset() will return 0 so it'll be tried in next acess.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/dso.h  |  1 +
 tools/perf/util/unwind-libunwind.c | 31 ---
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 28e8bb320495..5cf8dfe04eac 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -143,6 +143,7 @@ struct dso {
u32  status_seen;
size_t   file_size;
struct list_head open_entry;
+   u64  frame_offset;
} data;
 
union { /* Tool specific area */
diff --git a/tools/perf/util/unwind-libunwind.c 
b/tools/perf/util/unwind-libunwind.c
index 94929ec491f3..3cb78c36faad 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -244,14 +244,17 @@ static int read_unwind_spec_eh_frame(struct dso *dso, 
struct machine *machine,
 u64 *fde_count)
 {
int ret = -EINVAL, fd;
-   u64 offset;
+   u64 offset = dso->data.frame_offset;
 
-   fd = dso__data_fd(dso, machine);
-   if (fd < 0)
-   return -EINVAL;
+   if (offset == 0) {
+   fd = dso__data_fd(dso, machine);
+   if (fd < 0)
+   return -EINVAL;
 
-   /* Check the .eh_frame section for unwinding info */
-   offset = elf_section_offset(fd, ".eh_frame_hdr");
+   /* Check the .eh_frame section for unwinding info */
+   offset = elf_section_offset(fd, ".eh_frame_hdr");
+   dso->data.frame_offset = offset;
+   }
 
if (offset)
ret = unwind_spec_ehframe(dso, machine, offset,
@@ -265,14 +268,20 @@ static int read_unwind_spec_eh_frame(struct dso *dso, 
struct machine *machine,
 static int read_unwind_spec_debug_frame(struct dso *dso,
struct machine *machine, u64 *offset)
 {
-   int fd = dso__data_fd(dso, machine);
+   int fd;
+   u64 ofs = dso->data.frame_offset;
 
-   if (fd < 0)
-   return -EINVAL;
+   if (ofs == 0) {
+   fd = dso__data_fd(dso, machine);
+   if (fd < 0)
+   return -EINVAL;
 
-   /* Check the .debug_frame section for unwinding info */
-   *offset = elf_section_offset(fd, ".debug_frame");
+   /* Check the .debug_frame section for unwinding info */
+   ofs = elf_section_offset(fd, ".debug_frame");
+   dso->data.frame_offset = ofs;
+   }
 
+   *offset = ofs;
if (*offset)
return 0;
 
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 30/37] perf tools: Fix progress ui to support multi thread

2014-12-23 Thread Namhyung Kim
Split ui_progress struct into global and local one.  Each thread
updates local struct without lock and only updates global one if
meaningful progress is done (with lock).

To do that, pass struct ui_progress to __perf_session__process_event()
and set it for the total size of multi-file storage.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/data.c|  22 +
 tools/perf/util/data.h|   3 ++
 tools/perf/util/hist.c|   5 +-
 tools/perf/util/hist.h|   3 +-
 tools/perf/util/session.c | 117 ++
 tools/perf/util/tool.h|   3 ++
 6 files changed, 121 insertions(+), 32 deletions(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index b6f7cdc4a39f..37f75f231c4d 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -290,3 +290,25 @@ ssize_t perf_data_file__write_multi(struct perf_data_file 
*file,
 
return writen(file->multi_fd[idx], buf, size);
 }
+
+s64 perf_data_file__multi_size(struct perf_data_file *file)
+{
+   int i;
+   s64 total_size = perf_data_file__size(file);
+
+   if (!file->is_multi)
+   return total_size;
+
+   for (i = 0; i < file->nr_multi; i++) {
+   int fd = perf_data_file__multi_fd(file, i);
+   long size;
+
+   size = lseek(fd, 0, SEEK_END);
+   if (size < 0)
+   return (s64) -1;
+
+   total_size += size;
+   }
+
+   return total_size;
+}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index f5c229166614..0f0013ac9e30 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -2,6 +2,7 @@
 #define __PERF_DATA_H
 
 #include 
+#include "perf.h"
 
 enum perf_data_mode {
PERF_DATA_MODE_WRITE,
@@ -61,4 +62,6 @@ int perf_data_file__prepare_write(struct perf_data_file 
*file, int nr);
 ssize_t perf_data_file__write_multi(struct perf_data_file *file,
void *buf, size_t size, int idx);
 
+s64 perf_data_file__multi_size(struct perf_data_file *file);
+
 #endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f3b39b45f2ec..60b55a92f23e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1065,12 +1065,13 @@ void hists__collapse_resort(struct hists *hists, struct 
ui_progress *prog)
__hists__collapse_resort(hists, root, prog);
 }
 
-void hists__multi_resort(struct hists *dst, struct hists *src)
+void hists__multi_resort(struct hists *dst, struct hists *src,
+struct ui_progress *prog)
 {
struct rb_root *root = src->entries_in;
 
sort__need_collapse = 1;
-   __hists__collapse_resort(dst, root, NULL);
+   __hists__collapse_resort(dst, root, prog);
 }
 
 static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 4d975f5501ed..e2abc4c75158 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -124,7 +124,8 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char 
*bf, size_t size,
 void hist_entry__free(struct hist_entry *);
 
 void hists__output_resort(struct hists *hists, struct ui_progress *prog);
-void hists__multi_resort(struct hists *dst, struct hists *src);
+void hists__multi_resort(struct hists *dst, struct hists *src,
+struct ui_progress *prog);
 void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
 
 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 34956983ae8e..6d1dfbc650ba 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1258,14 +1258,14 @@ fetch_mmaped_event(struct perf_session *session,
 static int __perf_session__process_events(struct perf_session *session,
  struct events_stats *stats, int fd,
  u64 data_offset, u64 data_size,
- u64 file_size, struct perf_tool *tool)
+ u64 file_size, struct perf_tool *tool,
+ struct ui_progress *prog)
 {
u64 head, page_offset, file_offset, file_pos, size;
int err, mmap_prot, mmap_flags, map_idx = 0;
size_t  mmap_size;
char *buf, *mmaps[NUM_MMAPS];
union perf_event *event;
-   struct ui_progress prog;
s64 skip;
 
perf_tool__fill_defaults(tool);
@@ -1277,8 +1277,6 @@ static int __perf_session__process_events(struct 
perf_session *session,
if (data_size && (data_offset + data_size < file_size))
file_size = data_offset + data_size;
 
-   ui_progress__init(, file_size, "Processing events...");
-
mmap_size = MMAP_SIZE;
if (mmap_size > file_size) {
mmap_size = file_size;
@@ -1344,7 +1342,7 @@ 

[PATCH 36/37] perf tools: Add new perf data command

2014-12-23 Thread Namhyung Kim
From: Jiri Olsa 

Adding new 'perf data' command to provide operations over
data files.

The 'perf data convert' sub command is coming in following
patch, but there's possibility for other useful commands
like 'perf data ls' (to display perf data file in directory
in ls style).

Signed-off-by: Sebastian Andrzej Siewior 
Signed-off-by: Jiri Olsa 
Signed-off-by: Namhyung Kim 
---
 tools/perf/Documentation/perf-data.txt | 15 +++
 tools/perf/Makefile.perf   |  1 +
 tools/perf/builtin-data.c  | 75 ++
 tools/perf/builtin.h   |  1 +
 tools/perf/command-list.txt|  1 +
 tools/perf/perf.c  |  1 +
 6 files changed, 94 insertions(+)
 create mode 100644 tools/perf/Documentation/perf-data.txt
 create mode 100644 tools/perf/builtin-data.c

diff --git a/tools/perf/Documentation/perf-data.txt 
b/tools/perf/Documentation/perf-data.txt
new file mode 100644
index ..b8c83947715c
--- /dev/null
+++ b/tools/perf/Documentation/perf-data.txt
@@ -0,0 +1,15 @@
+perf-data(1)
+==
+
+NAME
+
+perf-data - Data file related processing
+
+SYNOPSIS
+
+[verse]
+'perf data' []  []",
+
+DESCRIPTION
+---
+Data file related processing.
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 47d933454492..f22085cb0b24 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -485,6 +485,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
 BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
 BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
+BUILTIN_OBJS += $(OUTPUT)builtin-data.o
 
 PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
 
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
new file mode 100644
index ..1eee97d020fa
--- /dev/null
+++ b/tools/perf/builtin-data.c
@@ -0,0 +1,75 @@
+#include 
+#include "builtin.h"
+#include "perf.h"
+#include "debug.h"
+#include "parse-options.h"
+
+typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
+
+struct data_cmd {
+   const char  *name;
+   const char  *summary;
+   data_cmd_fn_t   fn;
+};
+
+static struct data_cmd data_cmds[];
+
+#define for_each_cmd(cmd) \
+   for (cmd = data_cmds; cmd && cmd->name; cmd++)
+
+static const struct option data_options[] = {
+   OPT_END()
+};
+
+static const char * const data_usage[] = {
+   "perf data []  []",
+   NULL
+};
+
+static void print_usage(void)
+{
+   struct data_cmd *cmd;
+
+   printf("Usage:\n");
+   printf("\t%s\n\n", data_usage[0]);
+   printf("\tAvailable commands:\n");
+
+   for_each_cmd(cmd) {
+   printf("\t %s\t- %s\n", cmd->name, cmd->summary);
+   }
+
+   printf("\n");
+}
+
+static struct data_cmd data_cmds[] = {
+   { NULL },
+};
+
+int cmd_data(int argc, const char **argv, const char *prefix)
+{
+   struct data_cmd *cmd;
+   const char *cmdstr;
+
+   /* No command specified. */
+   if (argc < 2)
+   goto usage;
+
+   argc = parse_options(argc, argv, data_options, data_usage,
+PARSE_OPT_STOP_AT_NON_OPTION);
+   if (argc < 1)
+   goto usage;
+
+   cmdstr = argv[0];
+
+   for_each_cmd(cmd) {
+   if (strcmp(cmd->name, cmdstr))
+   continue;
+
+   return cmd->fn(argc, argv, prefix);
+   }
+
+   pr_err("Unknown command: %s\n", cmdstr);
+usage:
+   print_usage();
+   return -1;
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index b210d62907e4..3688ad29085f 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -37,6 +37,7 @@ extern int cmd_test(int argc, const char **argv, const char 
*prefix);
 extern int cmd_trace(int argc, const char **argv, const char *prefix);
 extern int cmd_inject(int argc, const char **argv, const char *prefix);
 extern int cmd_mem(int argc, const char **argv, const char *prefix);
+extern int cmd_data(int argc, const char **argv, const char *prefix);
 
 extern int find_scripts(char **scripts_array, char **scripts_path_array);
 #endif
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 0906fc401c52..00fcaf8a5b8d 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -7,6 +7,7 @@ perf-archivemainporcelain common
 perf-bench mainporcelain common
 perf-buildid-cache mainporcelain common
 perf-buildid-list  mainporcelain common
+perf-data  mainporcelain common
 perf-diff  mainporcelain common
 perf-evlistmainporcelain common
 perf-injectmainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 3700a7faca6c..f3c66b81c6be 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -62,6 +62,7 @@ static struct cmd_struct commands[] = {
 

[PATCH 19/37] perf tools: Introduce thread__find_addr_location_time() and friends

2014-12-23 Thread Namhyung Kim
The *_time() variants are for find appropriate map (and symbol) at the
given time.  This is based on the fact that map_groups list is sorted
by time in the previous patch.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/util/event.c| 59 ++
 tools/perf/util/machine.c  | 51 ++--
 tools/perf/util/thread.c   | 21 ++
 tools/perf/util/thread.h   | 10 +++
 tools/perf/util/unwind-libdw.c | 11 +++
 tools/perf/util/unwind-libunwind.c | 18 ++--
 6 files changed, 129 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2d04949bdc7d..3bb186a26314 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -731,16 +731,14 @@ int perf_event__process(struct perf_tool *tool 
__maybe_unused,
return machine__process_event(machine, event, sample);
 }
 
-void thread__find_addr_map(struct thread *thread, u8 cpumode,
-  enum map_type type, u64 addr,
-  struct addr_location *al)
+static void map_groups__find_addr_map(struct map_groups *mg, u8 cpumode,
+ enum map_type type, u64 addr,
+ struct addr_location *al)
 {
-   struct map_groups *mg = thread->mg;
struct machine *machine = mg->machine;
bool load_map = false;
 
al->machine = machine;
-   al->thread = thread;
al->addr = addr;
al->cpumode = cpumode;
al->filtered = 0;
@@ -809,6 +807,35 @@ void thread__find_addr_map(struct thread *thread, u8 
cpumode,
}
 }
 
+void thread__find_addr_map(struct thread *thread, u8 cpumode,
+  enum map_type type, u64 addr,
+  struct addr_location *al)
+{
+   al->thread = thread;
+   map_groups__find_addr_map(thread->mg, cpumode, type, addr, al);
+}
+
+void thread__find_addr_map_time(struct thread *thread, u8 cpumode,
+   enum map_type type, u64 addr,
+   struct addr_location *al, u64 timestamp)
+{
+   struct map_groups *mg;
+   struct thread *leader;
+
+   if (thread->tid == thread->pid_)
+   leader = thread;
+   else
+   leader = machine__find_thread(thread->mg->machine,
+ thread->pid_, thread->pid_);
+
+   BUG_ON(leader == NULL);
+
+   mg = thread__get_map_groups(leader, timestamp);
+
+   al->thread = thread;
+   map_groups__find_addr_map(mg, cpumode, type, addr, al);
+}
+
 void thread__find_addr_location(struct thread *thread,
u8 cpumode, enum map_type type, u64 addr,
struct addr_location *al)
@@ -821,6 +848,21 @@ void thread__find_addr_location(struct thread *thread,
al->sym = NULL;
 }
 
+void thread__find_addr_location_time(struct thread *thread, u8 cpumode,
+enum map_type type, u64 addr,
+struct addr_location *al, u64 timestamp)
+{
+   struct map_groups *mg;
+
+   mg = thread__get_map_groups(thread, timestamp);
+   map_groups__find_addr_map(mg, cpumode, type, addr, al);
+   if (al->map != NULL)
+   al->sym = map__find_symbol(al->map, al->addr,
+  mg->machine->symbol_filter);
+   else
+   al->sym = NULL;
+}
+
 int perf_event__preprocess_sample(const union perf_event *event,
  struct machine *machine,
  struct addr_location *al,
@@ -845,7 +887,12 @@ int perf_event__preprocess_sample(const union perf_event 
*event,
machine->vmlinux_maps[MAP__FUNCTION] == NULL)
machine__create_kernel_maps(machine);
 
-   thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
+   /*
+* sample->time is -1ULL if !PERF_SAMPLE_TIME which ends up
+* with using most recent map_groups (same as default behavior).
+*/
+   thread__find_addr_map_time(thread, cpumode, MAP__FUNCTION, sample->ip,
+  al, sample->time);
dump_printf(" .. dso: %s\n",
al->map ? al->map->dso->long_name :
al->level == 'H' ? "[hypervisor]" : "");
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index beae6e8fe789..ffce0bcd2d9a 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1466,7 +1466,7 @@ static bool symbol__match_regex(struct symbol *sym, 
regex_t *regex)
 
 static void ip__resolve_ams(struct thread *thread,
struct addr_map_symbol *ams,
-   u64 ip)
+   u64 ip, u64 timestamp)
 {
struct addr_location al;
 
@@ 

[PATCH 37/37] perf data: Implement 'split' subcommand

2014-12-23 Thread Namhyung Kim
The perf data split command is for splitting a (large) single data
file into multiple files under a directory (perf.data.dir by default)
so that it can be processed and reported using multiple threads.

Signed-off-by: Namhyung Kim 
---
 tools/perf/Documentation/perf-data.txt |  28 +
 tools/perf/builtin-data.c  | 223 +
 2 files changed, 251 insertions(+)

diff --git a/tools/perf/Documentation/perf-data.txt 
b/tools/perf/Documentation/perf-data.txt
index b8c83947715c..42708702f10c 100644
--- a/tools/perf/Documentation/perf-data.txt
+++ b/tools/perf/Documentation/perf-data.txt
@@ -13,3 +13,31 @@ SYNOPSIS
 DESCRIPTION
 ---
 Data file related processing.
+
+COMMANDS
+
+split::
+   Split single data file (perf.data) into multiple files under a directory
+   in order to be reported by multiple threads.
+
+OPTIONS for 'split'
+-
+-i::
+--input::
+   Specify input perf data file path.
+
+-o::
+--output::
+   Specify output perf data directory path.
+
+-v::
+--verbose::
+Be more verbose (show counter open errors, etc).
+
+-f::
+--force::
+Don't complain, do it.
+
+SEE ALSO
+
+linkperf:perf[1], linkperf:perf-report[1]
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 1eee97d020fa..5f3173826850 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -2,10 +2,14 @@
 #include "builtin.h"
 #include "perf.h"
 #include "debug.h"
+#include "session.h"
+#include "evlist.h"
 #include "parse-options.h"
 
 typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
 
+static const char *output_name;
+
 struct data_cmd {
const char  *name;
const char  *summary;
@@ -41,10 +45,229 @@ static void print_usage(void)
printf("\n");
 }
 
+static int data_cmd_split(int argc, const char **argv, const char *prefix);
+
 static struct data_cmd data_cmds[] = {
+   { "split", "split single data file into multi-file", data_cmd_split },
{ NULL },
 };
 
+#define FD_HASH_BITS  7
+#define FD_HASH_SIZE  (1 << FD_HASH_BITS)
+#define FD_HASH_MASK  (FD_HASH_SIZE - 1)
+
+struct data_split {
+   struct perf_tooltool;
+   struct perf_session *session;
+   enum {
+   PER_CPU,
+   PER_THREAD,
+   } mode;
+   int header_fd;
+   u64 header_written;
+   struct hlist_head   fd_hash[FD_HASH_SIZE];
+   int fd_hash_nr;
+};
+
+struct fdhash_node {
+   int id;
+   int fd;
+   struct hlist_node   list;
+};
+
+static struct hlist_head *get_hash(struct data_split *split, int id)
+{
+   return >fd_hash[id % FD_HASH_MASK];
+}
+
+static int perf_event__rewrite_header(struct perf_tool *tool,
+ union perf_event *event)
+{
+   struct data_split *split = container_of(tool, struct data_split, tool);
+   ssize_t size;
+
+   size = writen(split->header_fd, event, event->header.size);
+   if (size < 0)
+   return -errno;
+
+   split->header_written += size;
+   return 0;
+}
+
+static int split_other_events(struct perf_tool *tool,
+   union perf_event *event,
+   struct perf_sample *sample __maybe_unused,
+   struct machine *machine __maybe_unused)
+{
+   return perf_event__rewrite_header(tool, event);
+}
+
+static int split_sample_event(struct perf_tool *tool,
+   union perf_event *event,
+   struct perf_sample *sample,
+   struct perf_evsel *evsel __maybe_unused,
+   struct machine *machine __maybe_unused)
+{
+   struct data_split *split = container_of(tool, struct data_split, tool);
+   int id = split->mode == PER_CPU ? sample->cpu : sample->tid;
+   int fd = -1;
+   char buf[PATH_MAX];
+   struct hlist_head *head;
+   struct fdhash_node *node;
+
+   head = get_hash(split, id);
+   hlist_for_each_entry(node, head, list) {
+   if (node->id == id) {
+   fd = node->fd;
+   break;
+   }
+   }
+
+   if (fd == -1) {
+   scnprintf(buf, sizeof(buf), "%s/perf.data.%d",
+ output_name, split->fd_hash_nr++);
+
+   fd = open(buf, O_RDWR|O_CREAT|O_TRUNC, 0600);
+   if (fd < 0) {
+   pr_err("cannot open data file: %s: %m\n", buf);
+   return -1;
+   }
+
+   node = malloc(sizeof(*node));
+   if (node == NULL) {
+   pr_err("memory allocation failed\n");
+   return -1;
+   }
+
+   node->id = id;
+   

[PATCH 24/37] perf session: Pass struct events stats to event processing functions

2014-12-23 Thread Namhyung Kim
Pass stats structure so that it can point separate object when used in
multi-thread environment.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/ordered-events.c |  4 +-
 tools/perf/util/session.c| 87 +++-
 tools/perf/util/session.h|  1 +
 3 files changed, 54 insertions(+), 38 deletions(-)

diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index fd4be94125fb..e933c51d7090 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -183,7 +183,9 @@ static int __ordered_events__flush(struct perf_session *s,
if (ret)
pr_err("Can't parse sample, err = %d\n", ret);
else {
-   ret = perf_session__deliver_event(s, iter->event, 
, tool,
+   ret = perf_session__deliver_event(s, >stats,
+ iter->event,
+ , tool,
  iter->file_offset);
if (ret)
return ret;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4f0fcd2d3901..af2608e782ae 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -779,6 +779,7 @@ static struct machine *
 }
 
 static int deliver_sample_value(struct perf_session *session,
+   struct events_stats *stats,
struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -795,7 +796,7 @@ static int deliver_sample_value(struct perf_session 
*session,
}
 
if (!sid || sid->evsel == NULL) {
-   ++session->stats.nr_unknown_id;
+   ++stats->nr_unknown_id;
return 0;
}
 
@@ -803,6 +804,7 @@ static int deliver_sample_value(struct perf_session 
*session,
 }
 
 static int deliver_sample_group(struct perf_session *session,
+   struct events_stats *stats,
struct perf_tool *tool,
union  perf_event *event,
struct perf_sample *sample,
@@ -812,7 +814,7 @@ static int deliver_sample_group(struct perf_session 
*session,
u64 i;
 
for (i = 0; i < sample->read.group.nr; i++) {
-   ret = deliver_sample_value(session, tool, event, sample,
+   ret = deliver_sample_value(session, stats, tool, event, sample,
   >read.group.values[i],
   machine);
if (ret)
@@ -824,6 +826,7 @@ static int deliver_sample_group(struct perf_session 
*session,
 
 static int
 perf_session__deliver_sample(struct perf_session *session,
+struct events_stats *stats,
 struct perf_tool *tool,
 union  perf_event *event,
 struct perf_sample *sample,
@@ -840,14 +843,15 @@ perf_session__deliver_sample(struct perf_session *session,
 
/* For PERF_SAMPLE_READ we have either single or group mode. */
if (read_format & PERF_FORMAT_GROUP)
-   return deliver_sample_group(session, tool, event, sample,
+   return deliver_sample_group(session, stats, tool, event, sample,
machine);
else
-   return deliver_sample_value(session, tool, event, sample,
+   return deliver_sample_value(session, stats, tool, event, sample,
>read.one, machine);
 }
 
 int perf_session__deliver_event(struct perf_session *session,
+   struct events_stats *stats,
union perf_event *event,
struct perf_sample *sample,
struct perf_tool *tool, u64 file_offset)
@@ -866,14 +870,14 @@ int perf_session__deliver_event(struct perf_session 
*session,
case PERF_RECORD_SAMPLE:
dump_sample(evsel, event, sample);
if (evsel == NULL) {
-   ++session->stats.nr_unknown_id;
+   ++stats->nr_unknown_id;
return 0;
}
if (machine == NULL) {
-   ++session->stats.nr_unprocessable_samples;
+   ++stats->nr_unprocessable_samples;
return 0;
}
-   return perf_session__deliver_sample(session, tool, event,
+   return perf_session__deliver_sample(session, stats, tool, event,
sample, evsel, machine);
case PERF_RECORD_MMAP:
   

[PATCH 18/37] perf tools: Remove thread when map groups initialization failed

2014-12-23 Thread Namhyung Kim
Otherwise it'll break the machine->threads tree.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/machine.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 031bace39fdc..beae6e8fe789 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -411,6 +411,7 @@ static struct thread *__machine__findnew_thread(struct 
machine *machine,
 * leader and that would screwed the rb tree.
 */
if (thread__init_map_groups(th, machine)) {
+   rb_erase(>rb_node, >threads);
thread__delete(th);
return NULL;
}
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 17/37] perf tools: Maintain map groups list in a leader thread

2014-12-23 Thread Namhyung Kim
To support multi-threaded perf report, we need to maintain time-sorted
map groups.  Add ->mg_list member to struct thread and sort the list
by time.  Now leader threads have one more refcnt for map groups in
the list so also update the thread-mg-share test case.

Currently only add a new map groups when an exec (comm) event is
received.

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/tests/thread-mg-share.c |  7 +++-
 tools/perf/util/event.c|  2 +
 tools/perf/util/machine.c  |  2 +-
 tools/perf/util/map.c  |  1 +
 tools/perf/util/map.h  |  2 +
 tools/perf/util/thread.c   | 80 +-
 tools/perf/util/thread.h   |  3 ++
 7 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/thread-mg-share.c 
b/tools/perf/tests/thread-mg-share.c
index b028499dd3cf..8933e01d0549 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -23,6 +23,9 @@ int test__thread_mg_share(void)
 * with several threads and checks they properly share and
 * maintain map groups info (struct map_groups).
 *
+* Note that a leader thread has one more refcnt for its
+* (current) map groups.
+*
 * thread group (pid: 0, tids: 0, 1, 2, 3)
 * other  group (pid: 4, tids: 4, 5)
*/
@@ -43,7 +46,7 @@ int test__thread_mg_share(void)
leader && t1 && t2 && t3 && other);
 
mg = leader->mg;
-   TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 4);
+   TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 5);
 
/* test the map groups pointer is shared */
TEST_ASSERT_VAL("map groups don't match", mg == t1->mg);
@@ -59,7 +62,7 @@ int test__thread_mg_share(void)
TEST_ASSERT_VAL("failed to find other leader", other_leader);
 
other_mg = other->mg;
-   TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 2);
+   TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 3);
 
TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg);
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ff7594a27c73..2d04949bdc7d 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -750,6 +750,8 @@ void thread__find_addr_map(struct thread *thread, u8 
cpumode,
return;
}
 
+   BUG_ON(mg == NULL);
+
if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
al->level = 'k';
mg = >kmaps;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 2cc088d71922..031bace39fdc 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -330,7 +330,7 @@ static void machine__update_thread_pid(struct machine 
*machine,
goto out_err;
 
if (!leader->mg)
-   leader->mg = map_groups__new(machine);
+   thread__set_map_groups(leader, map_groups__new(machine), 0);
 
if (!leader->mg)
goto out_err;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 62ca9f2607d5..f0c1e2a24fee 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -422,6 +422,7 @@ void map_groups__init(struct map_groups *mg, struct machine 
*machine)
}
mg->machine = machine;
mg->refcnt = 1;
+   mg->timestamp = 0;
 }
 
 static void maps__delete(struct rb_root *maps)
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 6951a9d42339..dd92510b03d1 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -61,7 +61,9 @@ struct map_groups {
struct rb_root   maps[MAP__NR_TYPES];
struct list_head removed_maps[MAP__NR_TYPES];
struct machine   *machine;
+   u64  timestamp;
int  refcnt;
+   struct list_head list;
 };
 
 struct map_groups *map_groups__new(struct machine *machine);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index f2465f17cf16..109ceb5e2a85 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -10,13 +10,64 @@
 #include "comm.h"
 #include "unwind.h"
 
+struct map_groups *thread__get_map_groups(struct thread *thread, u64 timestamp)
+{
+   struct map_groups *mg;
+
+   list_for_each_entry(mg, >mg_list, list)
+   if (timestamp >= mg->timestamp)
+   return mg;
+
+   return thread->mg;
+}
+
+int thread__set_map_groups(struct thread *thread, struct map_groups *mg,
+  u64 timestamp)
+{
+   struct list_head *pos;
+   struct map_groups *old;
+
+   if (mg == NULL)
+   return -ENOMEM;
+
+   /*
+* Only a leader thread can have map groups list - others
+* reference it through map_groups__get.  This means the
+* leader thread will have one more refcnt than others.
+*/
+   if (thread->tid != thread->pid_)
+   

[PATCH 16/37] perf tools: Add a test case for timed thread handling

2014-12-23 Thread Namhyung Kim
A test case for verifying live and dead thread tree management during
time change and new machine__find{,new}_thread_time().

Cc: Frederic Weisbecker 
Signed-off-by: Namhyung Kim 
---
 tools/perf/Makefile.perf  |   1 +
 tools/perf/tests/builtin-test.c   |   4 +
 tools/perf/tests/tests.h  |   1 +
 tools/perf/tests/thread-lookup-time.c | 174 ++
 4 files changed, 180 insertions(+)
 create mode 100644 tools/perf/tests/thread-lookup-time.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index e4528a4a3a8c..6094f0a10d8b 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -448,6 +448,7 @@ LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
 LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
 LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
 LIB_OBJS += $(OUTPUT)tests/thread-comm.o
+LIB_OBJS += $(OUTPUT)tests/thread-lookup-time.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 1b463d82a71a..e4d335de19ea 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -171,6 +171,10 @@ static struct test {
.func = test__thread_comm,
},
{
+   .desc = "Test thread lookup with time",
+   .func = test__thread_lookup_time,
+   },
+   {
.func = NULL,
},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 43ac17780629..1090337f63e5 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -52,6 +52,7 @@ int test__switch_tracking(void);
 int test__fdarray__filter(void);
 int test__fdarray__add(void);
 int test__thread_comm(void);
+int test__thread_lookup_time(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-lookup-time.c 
b/tools/perf/tests/thread-lookup-time.c
new file mode 100644
index ..6237ecf8caae
--- /dev/null
+++ b/tools/perf/tests/thread-lookup-time.c
@@ -0,0 +1,174 @@
+#include "tests.h"
+#include "machine.h"
+#include "thread.h"
+#include "map.h"
+#include "debug.h"
+
+static int thread__print_cb(struct thread *th, void *arg __maybe_unused)
+{
+   printf("thread: %d, start time: %"PRIu64" %s\n",
+  th->tid, th->start_time, th->dead ? "(dead)" : "");
+   return 0;
+}
+
+static int lookup_with_timestamp(struct machine *machine)
+{
+   struct thread *t1, *t2, *t3;
+   union perf_event fork = {
+   .fork = {
+   .pid = 0,
+   .tid = 0,
+   .ppid = 1,
+   .ptid = 1,
+   },
+   };
+   struct perf_sample sample = {
+   .time = 5,
+   };
+
+   /* start_time is set to 0 */
+   t1 = machine__findnew_thread(machine, 0, 0);
+
+   if (verbose > 1) {
+   printf("= after t1 created ==\n");
+   machine__for_each_thread(machine, thread__print_cb, NULL);
+   }
+
+   TEST_ASSERT_VAL("wrong start time of old thread", t1->start_time == 0);
+
+   TEST_ASSERT_VAL("cannot find current thread",
+   machine__find_thread(machine, 0, 0) == t1);
+
+   TEST_ASSERT_VAL("cannot find current thread with time",
+   machine__findnew_thread_time(machine, 0, 0, 1) == 
t1);
+
+   /* start_time is overwritten to new value */
+   thread__set_comm(t1, "/usr/bin/perf", 2);
+
+   if (verbose > 1) {
+   printf("= after t1 set comm ==\n");
+   machine__for_each_thread(machine, thread__print_cb, NULL);
+   }
+
+   TEST_ASSERT_VAL("failed to update start time", t1->start_time == 2);
+
+   TEST_ASSERT_VAL("should not find passed thread",
+   /* this will create yet another dead thread */
+   machine__findnew_thread_time(machine, 0, 0, 1) != 
t1);
+
+   TEST_ASSERT_VAL("cannot find overwritten thread with time",
+   machine__find_thread_time(machine, 0, 0, 2) == t1);
+
+   /* now t1 goes to dead thread tree, and create t2 */
+   machine__process_fork_event(machine, , );
+
+   if (verbose > 1) {
+   printf("= after t2 forked ==\n");
+   machine__for_each_thread(machine, thread__print_cb, NULL);
+   }
+
+   t2 = machine__find_thread(machine, 0, 0);
+   TEST_ASSERT_VAL("cannot find current thread", t2 != NULL);
+
+   TEST_ASSERT_VAL("wrong start time of new thread", t2->start_time == 
5);
+
+   TEST_ASSERT_VAL("dead thread cannot be found",
+   machine__find_thread_time(machine, 0, 0, 1) != t1);
+
+   TEST_ASSERT_VAL("cannot find dead thread after new thread",
+   

[PATCH 01/37] perf tools: Set attr.task bit for a tracking event

2014-12-23 Thread Namhyung Kim
The perf_event_attr.task bit is to track task (fork and exit) events
but it missed to be set by perf_evsel__config().  While it was not a
problem in practice since setting other bits (comm/mmap) ended up
being in same result, it'd be good to set it explicitly anyway.

Signed-off-by: Namhyung Kim 
---
 tools/perf/util/evsel.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1e90c8557ede..e17d2b1624bc 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -709,6 +709,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct 
record_opts *opts)
if (opts->sample_weight)
perf_evsel__set_sample_bit(evsel, WEIGHT);
 
+   attr->task  = track;
attr->mmap  = track;
attr->mmap2 = track && !perf_missing_features.mmap2;
attr->comm  = track;
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] serial: 8250_early: prepare for dynamic BASE_BAUD

2014-12-23 Thread Vineet Gupta
BASE_BAUD is pain in neck for multi-platform support as it hard codes at
build time the clk value for early uart.

Mitigate this by allowing arches/platforms to provide their own version
which can do dynamic setup based on DT values etc (see next patch for
usage)

This was needed for ARC SDP platforms based on 2 different FPGA flows, each
with a different UART clk value.

Signed-off-by: Vineet Gupta 
Cc: Greg Kroah-Hartman 
Cc: Jiri Slaby 
Cc: linux-ser...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Rob Herring 
Cc: Arnd Bergmann 
---
 drivers/tty/serial/earlycon.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 64fe25a4285c..bfd3537739e0 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -54,6 +54,15 @@ static void __iomem * __init earlycon_map(unsigned long 
paddr, size_t size)
return base;
 }
 
+unsigned int __weak __init earlycon_base_baud(char *options)
+{
+#ifdef BASE_BAUD
+   return BASE_BAUD;
+#else
+   return 1843200/16;  /* x86 early console */
+#endif
+}
+
 static int __init parse_options(struct earlycon_device *device,
char *options)
 {
@@ -87,7 +96,7 @@ static int __init parse_options(struct earlycon_device 
*device,
return -EINVAL;
}
 
-   port->uartclk = BASE_BAUD * 16;
+   port->uartclk = earlycon_base_baud(options) * 16;
 
options = strchr(options, ',');
if (options) {
@@ -156,7 +165,7 @@ int __init of_setup_earlycon(unsigned long addr,
 
port->iotype = UPIO_MEM;
port->mapbase = addr;
-   port->uartclk = BASE_BAUD * 16;
+   port->uartclk = earlycon_base_baud(NULL) * 16;
port->membase = earlycon_map(addr, SZ_4K);
 
early_console_dev.con->data = _console_dev;
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] ARC: runtime determine BASE_BAUD per machine

2014-12-23 Thread Vineet Gupta
Signed-off-by: Vineet Gupta 
Cc: Greg Kroah-Hartman 
Cc: Jiri Slaby 
Cc: linux-ser...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Rob Herring 
Cc: Arnd Bergmann 
---
 arch/arc/include/asm/serial.h | 24 
 arch/arc/kernel/devtree.c | 24 
 2 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/arch/arc/include/asm/serial.h b/arch/arc/include/asm/serial.h
index 602b0970a764..a8c0b8743709 100644
--- a/arch/arc/include/asm/serial.h
+++ b/arch/arc/include/asm/serial.h
@@ -10,26 +10,10 @@
 #define _ASM_ARC_SERIAL_H
 
 /*
- * early-8250 requires BASE_BAUD to be defined and includes this header.
- * We put in a typical value:
- * (core clk / 16) - i.e. UART samples 16 times per sec.
- * Athough in multi-platform-image this might not work, specially if the
- * clk driving the UART is different.
- * We can't use DeviceTree as this is typically for early serial.
+ * 8250_early (now earlycon) include this hdr and expect BASE_BAUD definition
+ * for setting up uartclk.
+ * Now that is done via arch provided earlycon_base_baud() which can use FDT
+ * provided info as well to provide uartclk based on DT in use.
  */
 
-#include 
-
-#define BASE_BAUD  (arc_get_core_freq() / 16)
-
-/*
- * This is definitely going to break early 8250 consoles on multi-platform
- * images but hey, it won't add any code complexity for a debug feature of
- * one broken driver.
- */
-#ifdef CONFIG_ARC_PLAT_TB10X
-#undef BASE_BAUD
-#define BASE_BAUD  (arc_get_core_freq() / 16 / 3)
-#endif
-
 #endif /* _ASM_ARC_SERIAL_H */
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index fffdb5e41b20..8adc5958982f 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -17,6 +17,28 @@
 #include 
 #include 
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+
+static unsigned int arc_base_baud;
+
+unsigned int __init serial8250_early_base_baud(char *options)
+{
+   return arc_base_baud/16;
+}
+
+static void __init arc_set_early_base_baud(unsigned long dt_root)
+{
+   unsigned int core_clk = arc_get_core_freq();
+
+   if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x"))
+   arc_base_baud = core_clk/3;
+   else
+   arc_base_baud = core_clk;
+}
+#else
+#define arc_set_early_base_baud(dt_root)
+#endif
+
 static const void * __init arch_get_next_mach(const char *const **match)
 {
static const struct machine_desc *mdesc = __arch_info_begin;
@@ -56,5 +78,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
if (clk)
arc_set_core_freq(of_read_ulong(clk, len/4));
 
+   arc_set_early_base_baud(dt_root);
+
return mdesc;
 }
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] serial: 8250_early: optimize early 8250 uart

2014-12-23 Thread Vineet Gupta
In early 8250, IER is already zero so no point in writing this - twice
per char.

This helped improve the SystemC model based ARC OSCI platform

Signed-off-by: Vineet Gupta 
Cc: Greg Kroah-Hartman 
Cc: Jiri Slaby 
Cc: linux-ser...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Rob Herring 
---
 drivers/tty/serial/8250/8250_early.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_early.c 
b/drivers/tty/serial/8250/8250_early.c
index 4858b8a99d3b..ce2a8abd1f54 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -95,13 +95,16 @@ static void __init early_serial8250_write(struct console 
*console,
 
/* Save the IER and disable interrupts */
ier = serial8250_early_in(port, UART_IER);
-   serial8250_early_out(port, UART_IER, 0);
+   if (ier)
+   serial8250_early_out(port, UART_IER, 0);
 
uart_console_write(port, s, count, serial_putc);
 
/* Wait for transmitter to become empty and restore the IER */
wait_for_xmitr(port);
-   serial8250_early_out(port, UART_IER, ier);
+
+   if (ier)
+   serial8250_early_out(port, UART_IER, ier);
 }
 
 static unsigned int __init probe_baud(struct uart_port *port)
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3] Early 8250 fixlets

2014-12-23 Thread Vineet Gupta
Hi,

This series addresses some of the issues seen on early 8250 uart when
working with ARC SDP platform.

Thx,
-Vineet

Vineet Gupta (3):
  serial: 8250_early: optimize early 8250 uart
  serial: 8250_early: prepare for dynamic BASE_BAUD
  ARC: runtime determine BASE_BAUD per machine

 arch/arc/include/asm/serial.h| 24 
 arch/arc/kernel/devtree.c| 24 
 drivers/tty/serial/8250/8250_early.c |  7 +--
 drivers/tty/serial/earlycon.c| 13 +++--
 4 files changed, 44 insertions(+), 24 deletions(-)

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 5/6] input: touchscreen: ti_am335x_tsc: Use charge delay DT parameter

2014-12-23 Thread Vignesh R
This patch reads charge delay from tsc DT node and writes to
REG_CHARGEDELAY register. If the charge delay is not specified in DT
then default value of 0x400(CHARGEDLY_OPENDLY) is used.

Signed-off-by: Vignesh R 
---
v5:
 - print out a warning when ti,charge-delay is not specified

 drivers/input/touchscreen/ti_am335x_tsc.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c 
b/drivers/input/touchscreen/ti_am335x_tsc.c
index 8650b1dd24dc..9cb8b4a01dca 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -52,6 +52,7 @@ struct titsc {
u32 bit_xp, bit_xn, bit_yp, bit_yn;
u32 inp_xp, inp_xn, inp_yp, inp_yn;
u32 step_mask;
+   u32 charge_delay;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -177,7 +178,7 @@ static void titsc_step_config(struct titsc *ts_dev)
 
config = titsc_readl(ts_dev, REG_IDLECONFIG);
titsc_writel(ts_dev, REG_CHARGECONFIG, config);
-   titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+   titsc_writel(ts_dev, REG_CHARGEDELAY, ts_dev->charge_delay);
 
/* coordinate_readouts + 1 ... coordinate_readouts + 2 is for Z */
config = STEPCONFIG_MODE_HWSYNC |
@@ -368,6 +369,17 @@ static int titsc_parse_dt(struct platform_device *pdev,
if (err < 0)
return err;
 
+   err = of_property_read_u32(node, "ti,charge-delay",
+  _dev->charge_delay);
+   /*
+* If ti,charge-delay value is not specified, then use CHARGEDLY_OPENDLY
+* as the default value.
+*/
+   if (err < 0) {
+   ts_dev->charge_delay = CHARGEDLY_OPENDLY;
+   dev_warn(>dev, "ti,charge-delay not specified\n");
+   }
+
return of_property_read_u32_array(node, "ti,wire-config",
ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 2/6] input: touchscreen: ti_am335x_tsc: Remove udelay in interrupt handler

2014-12-23 Thread Vignesh R
From: Brad Griffis 

TSC interrupt handler had udelay to avoid reporting of false pen-up
interrupt to user space. This patch implements workaround suggesting in
Advisory 1.0.31 of silicon errata for am335x, thus eliminating udelay
and touchscreen lag. This also improves performance of touchscreen and
eliminates sudden jump of cursor at touch release.

IDLECONFIG and CHARGECONFIG registers are to be configured
with same values in order to eliminate false pen-up events. This
workaround may result in false pen-down to be detected, hence considerable
charge step delay needs to be added. The charge delay is set to 0xB000
(in terms of ADC clock cycles) by default.

TSC steps are disabled at the end of every sampling cycle and EOS bit is
set. Once the EOS bit is set, the TSC steps need to be re-enabled to begin
next sampling cycle.

Signed-off-by: Brad Griffis 
[vigne...@ti.com: Ported the patch from v3.12 to v3.19rc1]

Signed-off-by: Vignesh R 
---

v5:
 - enable TSC steps only on EOS interrup

v4:
 - check for PEN_IRQ bit in ADCFSM to avoid false-pen when ADC
   and TSC are used together.
 - Set charge delay to 0x400 as default. Most devices function
   normally at this value.

 drivers/input/touchscreen/ti_am335x_tsc.c | 67 ++-
 include/linux/mfd/ti_am335x_tscadc.h  |  3 +-
 2 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c 
b/drivers/input/touchscreen/ti_am335x_tsc.c
index dfbb9fe6a270..8650b1dd24dc 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -173,11 +173,9 @@ static void titsc_step_config(struct titsc *ts_dev)
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
 
-   /* Charge step configuration */
-   config = ts_dev->bit_xp | ts_dev->bit_yn |
-   STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
-   STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
+   /* Make CHARGECONFIG same as IDLECONFIG */
 
+   config = titsc_readl(ts_dev, REG_IDLECONFIG);
titsc_writel(ts_dev, REG_CHARGECONFIG, config);
titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
 
@@ -261,12 +259,34 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 {
struct titsc *ts_dev = dev;
struct input_dev *input_dev = ts_dev->input;
-   unsigned int status, irqclr = 0;
+   unsigned int fsm, status, irqclr = 0;
unsigned int x = 0, y = 0;
unsigned int z1, z2, z;
-   unsigned int fsm;
 
-   status = titsc_readl(ts_dev, REG_IRQSTATUS);
+   status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
+   if (status & IRQENB_HW_PEN) {
+   ts_dev->pen_down = true;
+   titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
+   titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+   irqclr |= IRQENB_HW_PEN;
+   }
+
+   if (status & IRQENB_PENUP) {
+   fsm = titsc_readl(ts_dev, REG_ADCFSM);
+   if (fsm == ADCFSM_STEPID) {
+   ts_dev->pen_down = false;
+   input_report_key(input_dev, BTN_TOUCH, 0);
+   input_report_abs(input_dev, ABS_PRESSURE, 0);
+   input_sync(input_dev);
+   } else {
+   ts_dev->pen_down = true;
+   }
+   irqclr |= IRQENB_PENUP;
+   }
+
+   if (status & IRQENB_EOS)
+   irqclr |= IRQENB_EOS;
+
/*
 * ADC and touchscreen share the IRQ line.
 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
@@ -297,37 +317,11 @@ static irqreturn_t titsc_irq(int irq, void *dev)
}
irqclr |= IRQENB_FIFO0THRES;
}
-
-   /*
-* Time for sequencer to settle, to read
-* correct state of the sequencer.
-*/
-   udelay(SEQ_SETTLE);
-
-   status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
-   if (status & IRQENB_PENUP) {
-   /* Pen up event */
-   fsm = titsc_readl(ts_dev, REG_ADCFSM);
-   if (fsm == ADCFSM_STEPID) {
-   ts_dev->pen_down = false;
-   input_report_key(input_dev, BTN_TOUCH, 0);
-   input_report_abs(input_dev, ABS_PRESSURE, 0);
-   input_sync(input_dev);
-   } else {
-   ts_dev->pen_down = true;
-   }
-   irqclr |= IRQENB_PENUP;
-   }
-
-   if (status & IRQENB_HW_PEN) {
-
-   titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
-   titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
-   }
-
if (irqclr) {
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
-   am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
+   if (status & IRQENB_EOS)
+   

[PATCH v5 4/6] ARM: dts: AM335x: Make charge delay a DT parameter for TSC

2014-12-23 Thread Vignesh R
The charge delay value is by default 0x400. But it can be set to lower
values on some boards, as long as false pen-ups are avoided. Lowering the
value increases the sampling rate (though current sampling rate is
sufficient for TSC operation). In some boards, the value has to be
increased to avoid false pen-up events. Hence, charge delay has been
made a DT parameter.

Signed-off-by: Vignesh R 
---
v4:
 - Set charge delay to 0x400 as default. Most devices function normally
   at this value

 .../devicetree/bindings/input/touchscreen/ti-tsc-adc.txt  | 15 +++
 arch/arm/boot/dts/am335x-evm.dts  |  1 +
 2 files changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt 
b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
index 878549ba814d..6df5028a4ad3 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
@@ -28,6 +28,20 @@ Required properties:
ti,adc-channels: List of analog inputs available for ADC.
 AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
 
+Optional properties:
+- child "tsc"
+   ti,charge-delay: Length of touch screen charge delay step in terms of
+ADC clock cycles. Charge delay value should be large
+in order to avoid false pen-up events. This value
+affects the overall sampling speed, hence need to be
+kept as low as possible, while avoiding false pen-up
+event. Start from a lower value, say 0x400, and
+increase value until false pen-up events are avoided.
+The pen-up detection happens immediately after the
+charge step, so this does in fact function as a
+hardware knob for adjusting the amount of "settling
+time".
+
 Example:
tscadc: tscadc@44e0d000 {
compatible = "ti,am3359-tscadc";
@@ -36,6 +50,7 @@ Example:
ti,x-plate-resistance = <200>;
ti,coordiante-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
+   ti,charge-delay = <0x400>;
};
 
adc {
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 54f118c08db8..66342515df20 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -648,6 +648,7 @@
ti,x-plate-resistance = <200>;
ti,coordinate-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
+   ti,charge-delay = <0x400>;
};
 
adc {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 1/6] input: touchscreen: ti_am335x_tsc Interchange touchscreen and ADC steps

2014-12-23 Thread Vignesh R
From: Brad Griffis 

This patch makes the initial changes required to workaround TSC-false
pen-up interrupts. It is required to implement these changes in order to
remove udelay in the TSC interrupt handler and false pen-up events.
The charge step is to be executed immediately after sampling X+. Hence
TSC is made to use higher numbered steps (steps 5 to 16 for 5 co-ordinate
readouts, 4 wire TSC configuration) and ADC to use lower ones. Further
X co-ordinate readouts must be the last to be sampled, thus co-ordinates
are sampled in the order Y-Z-X.

Signed-off-by: Brad Griffis 
[vigne...@ti.com: Ported the patch from v3.12 to v3.19rc1]

Signed-off-by: Vignesh R 
Acked-by: Jonathan Cameron 
---
 drivers/iio/adc/ti_am335x_adc.c   |  5 ++--
 drivers/input/touchscreen/ti_am335x_tsc.c | 42 ++-
 2 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index b730864731e8..adba23246474 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -86,19 +86,18 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
 {
struct tiadc_device *adc_dev = iio_priv(indio_dev);
unsigned int stepconfig;
-   int i, steps;
+   int i, steps = 0;
 
/*
 * There are 16 configurable steps and 8 analog input
 * lines available which are shared between Touchscreen and ADC.
 *
-* Steps backwards i.e. from 16 towards 0 are used by ADC
+* Steps forwards i.e. from 0 towards 16 are used by ADC
 * depending on number of input lines needed.
 * Channel would represent which analog input
 * needs to be given to ADC to digitalize data.
 */
 
-   steps = TOTAL_STEPS - adc_dev->channels;
if (iio_buffer_enabled(indio_dev))
stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
| STEPCONFIG_MODE_SWCNT;
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c 
b/drivers/input/touchscreen/ti_am335x_tsc.c
index 004f1346a957..dfbb9fe6a270 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -121,7 +121,7 @@ static void titsc_step_config(struct titsc *ts_dev)
 {
unsigned intconfig;
int i;
-   int end_step;
+   int end_step, first_step, tsc_steps;
u32 stepenable;
 
config = STEPCONFIG_MODE_HWSYNC |
@@ -140,9 +140,11 @@ static void titsc_step_config(struct titsc *ts_dev)
break;
}
 
-   /* 1 … coordinate_readouts is for X */
-   end_step = ts_dev->coordinate_readouts;
-   for (i = 0; i < end_step; i++) {
+   tsc_steps = ts_dev->coordinate_readouts * 2 + 2;
+   first_step = TOTAL_STEPS - tsc_steps;
+   /* Steps 16 to 16-coordinate_readouts is for X */
+   end_step = first_step + tsc_steps;
+   for (i = end_step - ts_dev->coordinate_readouts; i < end_step; i++) {
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
@@ -164,9 +166,9 @@ static void titsc_step_config(struct titsc *ts_dev)
break;
}
 
-   /* coordinate_readouts … coordinate_readouts * 2 is for Y */
-   end_step = ts_dev->coordinate_readouts * 2;
-   for (i = ts_dev->coordinate_readouts; i < end_step; i++) {
+   /* 1 ... coordinate_readouts is for Y */
+   end_step = first_step + ts_dev->coordinate_readouts;
+   for (i = first_step; i < end_step; i++) {
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
@@ -179,7 +181,7 @@ static void titsc_step_config(struct titsc *ts_dev)
titsc_writel(ts_dev, REG_CHARGECONFIG, config);
titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
 
-   /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
+   /* coordinate_readouts + 1 ... coordinate_readouts + 2 is for Z */
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_AVG_16 | ts_dev->bit_yp |
ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
@@ -194,8 +196,11 @@ static void titsc_step_config(struct titsc *ts_dev)
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
STEPCONFIG_OPENDLY);
 
-   /* The steps1 … end and bit 0 for TS_Charge */
-   stepenable = (1 << (end_step + 2)) - 1;
+   /* The steps end ... end - readouts * 2 + 2 and bit 0 for TS_Charge */
+   stepenable = 1;
+   for (i = 0; i < tsc_steps; i++)
+   stepenable |= 1 << (first_step + i + 1);
+
ts_dev->step_mask = stepenable;
am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
 }
@@ -209,6 +214,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
unsigned int read, diff;

[PATCH v5 3/6] mfd: ti_am335x_tscadc: Remove unwanted reg_se_cache save

2014-12-23 Thread Vignesh R
In one shot mode, sequencer automatically disables all enabled steps at
the end of each cycle. (both ADC steps and TSC steps) Hence these steps
need not be saved in reg_se_cache for clearing these steps at a later
stage.
Also, when ADC wakes up Sequencer should not be busy executing any of the
config steps except for the charge step. Previously charge step was 1 ADC
clock cycle and hence it was ignored.
TSC steps are always disabled at the end of each conversion cycle, hence
there is no need to explicitly disable TSC steps by writing 0 to REG_SE.

Signed-off-by: Vignesh R 
---

v5:
 - Remove unnecessary clearing of REG_SE

 drivers/mfd/ti_am335x_tscadc.c   | 13 +
 include/linux/mfd/ti_am335x_tscadc.h |  1 +
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 467c80e1c4ae..e4e4b22eebc9 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -68,12 +68,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev 
*tsadc)
DEFINE_WAIT(wait);
u32 reg;
 
-   /*
-* disable TSC steps so it does not run while the ADC is using it. If
-* write 0 while it is running (it just started or was already running)
-* then it completes all steps that were enabled and stops then.
-*/
-   tscadc_writel(tsadc, REG_SE, 0);
reg = tscadc_readl(tsadc, REG_ADCFSM);
if (reg & SEQ_STATUS) {
tsadc->adc_waiting = true;
@@ -86,8 +80,12 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev 
*tsadc)
spin_lock_irq(>reg_lock);
finish_wait(>reg_se_wait, );
 
+   /*
+* Sequencer should either be idle or
+* busy applying the charge step.
+*/
reg = tscadc_readl(tsadc, REG_ADCFSM);
-   WARN_ON(reg & SEQ_STATUS);
+   WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP));
tsadc->adc_waiting = false;
}
tsadc->adc_in_use = true;
@@ -96,7 +94,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev 
*tsadc)
 void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
 {
spin_lock_irq(>reg_lock);
-   tsadc->reg_se_cache |= val;
am335x_tscadc_need_adc(tsadc);
 
tscadc_writel(tsadc, REG_SE, val);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h 
b/include/linux/mfd/ti_am335x_tscadc.h
index 3f4e994ace2b..1fd50dcfe47c 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -128,6 +128,7 @@
 
 /* Sequencer Status */
 #define SEQ_STATUS BIT(5)
+#define CHARGE_STEP0x11
 
 #define ADC_CLK300
 #define TOTAL_STEPS16
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 6/6] input: touchscreen: ti_am335x_tsc: Replace delta filtering with median filtering

2014-12-23 Thread Vignesh R
Previously, delta filtering was applied TSC co-ordinate readouts before
reporting a single value to user space. This patch replaces delta filtering
with median filtering. Median filtering sorts co-ordinate readouts, drops min
and max values, and reports the average of remaining values. This method is
more sensible than delta filering. Median filtering is applied only if number
of readouts is greater than 3 else just average of co-ordinate readouts is
reported.

Signed-off-by: Vignesh R 
---
 drivers/input/touchscreen/ti_am335x_tsc.c | 91 +--
 1 file changed, 51 insertions(+), 40 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c 
b/drivers/input/touchscreen/ti_am335x_tsc.c
index 9cb8b4a01dca..504b85db6425 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -204,56 +205,61 @@ static void titsc_step_config(struct titsc *ts_dev)
am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
 }
 
+static int titsc_cmp_coord(const void *a, const void *b)
+{
+   return *(int *)a - *(int *)b;
+}
+
 static void titsc_read_coordinates(struct titsc *ts_dev,
u32 *x, u32 *y, u32 *z1, u32 *z2)
 {
-   unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
-   unsigned int prev_val_x = ~0, prev_val_y = ~0;
-   unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
-   unsigned int read, diff;
-   unsigned int i, channel;
+   unsigned int yvals[7], xvals[7];
+   unsigned int i, xsum = 0, ysum = 0;
unsigned int creads = ts_dev->coordinate_readouts;
-   unsigned int first_step = TOTAL_STEPS - (creads * 2 + 2);
 
-   *z1 = *z2 = 0;
-   if (fifocount % (creads * 2 + 2))
-   fifocount -= fifocount % (creads * 2 + 2);
-   /*
-* Delta filter is used to remove large variations in sampled
-* values from ADC. The filter tries to predict where the next
-* coordinate could be. This is done by taking a previous
-* coordinate and subtracting it form current one. Further the
-* algorithm compares the difference with that of a present value,
-* if true the value is reported to the sub system.
-*/
-   for (i = 0; i < fifocount; i++) {
-   read = titsc_readl(ts_dev, REG_FIFO0);
-
-   channel = (read & 0xf) >> 16;
-   read &= 0xfff;
-   if (channel > first_step + creads + 2) {
-   diff = abs(read - prev_val_x);
-   if (diff < prev_diff_x) {
-   prev_diff_x = diff;
-   *x = read;
-   }
-   prev_val_x = read;
+   for (i = 0; i < creads; i++) {
+   yvals[i] = titsc_readl(ts_dev, REG_FIFO0);
+   yvals[i] &= 0xfff;
+   }
 
-   } else if (channel == first_step + creads + 1) {
-   *z1 = read;
+   *z1 = titsc_readl(ts_dev, REG_FIFO0);
+   *z1 &= 0xfff;
+   *z2 = titsc_readl(ts_dev, REG_FIFO0);
+   *z2 &= 0xfff;
 
-   } else if (channel == first_step + creads + 2) {
-   *z2 = read;
+   for (i = 0; i < creads; i++) {
+   xvals[i] = titsc_readl(ts_dev, REG_FIFO0);
+   xvals[i] &= 0xfff;
+   }
 
-   } else if (channel > first_step) {
-   diff = abs(read - prev_val_y);
-   if (diff < prev_diff_y) {
-   prev_diff_y = diff;
-   *y = read;
-   }
-   prev_val_y = read;
+   /*
+* If co-ordinates readouts is less than 4 then
+* report the average. In case of 4 or more
+* readouts, sort the co-ordinate samples, drop
+* min and max values and report the average of
+* remaining values.
+*/
+   if (creads <=  3) {
+   for (i = 0; i < creads; i++) {
+   ysum += yvals[i];
+   xsum += xvals[i];
}
+   ysum /= creads;
+   xsum /= creads;
+   } else {
+   sort(yvals, creads, sizeof(unsigned int),
+titsc_cmp_coord, NULL);
+   sort(xvals, creads, sizeof(unsigned int),
+titsc_cmp_coord, NULL);
+   for (i = 1; i < creads - 1; i++) {
+   ysum += yvals[i];
+   xsum += xvals[i];
+   }
+   ysum /= creads - 2;
+   xsum /= creads - 2;
}
+   *y = ysum;
+   *x = xsum;
 }
 
 static irqreturn_t titsc_irq(int irq, void *dev)
@@ -369,6 +375,11 @@ static int titsc_parse_dt(struct platform_device *pdev,
if (err < 0)
return err;
 
+   if 

[PATCH v5 0/6] Touchscreen performance related fixes

2014-12-23 Thread Vignesh R
This series is rebase of v4 onto v3.19-rc1. It also fixes concerns
expressed on v4 wrt simultaneous use of IIO and TSC.

I have tested this patch series on am335x-evm and Beaglebone black
with lcd7-cape.

Note that, these patches do not work as expected on Beaglebone Black
with BB-View 4.3 Cape from Farnell due to a hardware issue in the cape.

Change log:

v5:
 - Rebased onto v3.19-rc1
 - minor changes in patch 2,3 and 5.

v3:
 - Replace delta filtering logic in TSC driver with median filtering
   as suggested by Richard.
 - Addressed Lee Jones comments.

v2:
 - Addressed comments by Hartmut Knaack
 - patch 2 was split into two as per Lee Jones comment

Brad Griffis (2):
  input: touchscreen: ti_am335x_tsc Interchange touchscreen and ADC
steps
  input: touchscreen: ti_am335x_tsc: Remove udelay in interrupt handler

Vignesh R (4):
  mfd: ti_am335x_tscadc: Remove unwanted reg_se_cache save
  ARM: dts: AM335x: Make charge delay a DT parameter for TSC
  input: touchscreen: ti_am335x_tsc: Use charge delay DT parameter
  input: touchscreen: ti_am335x_tsc: Replace delta filtering with median
filtering

 .../bindings/input/touchscreen/ti-tsc-adc.txt  |  15 ++
 arch/arm/boot/dts/am335x-evm.dts   |   1 +
 drivers/iio/adc/ti_am335x_adc.c|   5 +-
 drivers/input/touchscreen/ti_am335x_tsc.c  | 196 -
 drivers/mfd/ti_am335x_tscadc.c |  13 +-
 include/linux/mfd/ti_am335x_tscadc.h   |   4 +-
 6 files changed, 136 insertions(+), 98 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 1/5] ASoC: dwc: Prepare clock before use

2014-12-23 Thread Andrew Jackson
On 12/23/14 13:56, Andrew Jackson wrote:
> From: Andrew Jackson 
> 
> Some I2S clocks may require some time to get the clock ready
> for operation and so need to be prepared before they are enabled.
> So, prepare the clock as well as enabling it, but combine the
> two through clk_prepare_enable.

More turkey-focussed issues: this should have a clk_disable_unprepare too.  Sigh

Andrew

> Signed-off-by: Andrew Jackson 
> ---
>  sound/soc/dwc/designware_i2s.c |2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
> index 06d3a34..9573ec7 100644
> --- a/sound/soc/dwc/designware_i2s.c
> +++ b/sound/soc/dwc/designware_i2s.c
> @@ -411,7 +411,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
>   if (IS_ERR(dev->clk))
>   return  PTR_ERR(dev->clk);
>  
> - ret = clk_enable(dev->clk);
> + ret = clk_prepare_enable(dev->clk);
>   if (ret < 0)
>   goto err_clk_put;
>  
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 2/5] ASoC: dwc: Switch to managed clock resource

2014-12-23 Thread Andrew Jackson
On 12/23/14 13:56, Andrew Jackson wrote:
> From: Andrew Jackson 
> 
> Simplify error handling during probe by using managed clock
> resources.

In my haste to get to the Christmas turkey I missed a clk_put elsewhere.  Will 
fix and resubmit.

 Andrew

> Signed-off-by: Andrew Jackson 
> ---
>  sound/soc/dwc/designware_i2s.c |6 ++
>  1 files changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
> index 9573ec7..b3dc535 100644
> --- a/sound/soc/dwc/designware_i2s.c
> +++ b/sound/soc/dwc/designware_i2s.c
> @@ -407,13 +407,13 @@ static int dw_i2s_probe(struct platform_device *pdev)
>  
>   dev->capability = pdata->cap;
>   dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
> - dev->clk = clk_get(>dev, NULL);
> + dev->clk = devm_clk_get(>dev, NULL);
>   if (IS_ERR(dev->clk))
>   return  PTR_ERR(dev->clk);
>  
>   ret = clk_prepare_enable(dev->clk);
>   if (ret < 0)
> - goto err_clk_put;
> + return ret;
>  
>   dev_set_drvdata(>dev, dev);
>   ret = snd_soc_register_component(>dev, _i2s_component,
> @@ -427,8 +427,6 @@ static int dw_i2s_probe(struct platform_device *pdev)
>  
>  err_clk_disable:
>   clk_disable(dev->clk);
> -err_clk_put:
> - clk_put(dev->clk);
>   return ret;
>  }
>  
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] kbuild: merge bounds.h and asm-offsets.h rules

2014-12-23 Thread Masahiro Yamada
The rules "cmd_bounds" and "cmd_offsets" are almost the same.
(The difference is only the include guards.)  They can be merged.

Signed-off-by: Masahiro Yamada 
---

 Kbuild | 59 +--
 1 file changed, 21 insertions(+), 38 deletions(-)

diff --git a/Kbuild b/Kbuild
index 5d7c729..55a639f 100644
--- a/Kbuild
+++ b/Kbuild
@@ -5,19 +5,20 @@
 # 2) Generate asm-offsets.h (may need bounds.h)
 # 3) Check for missing system calls
 
-#
-# 1) Generate bounds.h
-
-bounds-file := include/generated/bounds.h
-
-always  := $(bounds-file)
-targets := $(bounds-file) kernel/bounds.s
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+   "/^->/{s:->#\(.*\):/* \1 */:; \
+   s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+   s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+   s:->::; p;}"
+endef
 
-quiet_cmd_bounds = GEN $@
-define cmd_bounds
+quiet_cmd_offsets = GEN $@
+define cmd_offsets
(set -e; \
-echo "#ifndef __LINUX_BOUNDS_H__"; \
-echo "#define __LINUX_BOUNDS_H__"; \
+INCLUDE_GUARD=$$(echo __$(notdir $@)__ | tr '[a-z].-' '[A-Z]__'); \
+echo "#ifndef $$INCLUDE_GUARD"; \
+echo "#define $$INCLUDE_GUARD"; \
 echo "/*"; \
 echo " * DO NOT MODIFY."; \
 echo " *"; \
@@ -30,6 +31,14 @@ define cmd_bounds
 echo "#endif" ) > $@
 endef
 
+#
+# 1) Generate bounds.h
+
+bounds-file := include/generated/bounds.h
+
+always  := $(bounds-file)
+targets := $(bounds-file) kernel/bounds.s
+
 # We use internal kbuild rules to avoid the "is up to date" message from make
 kernel/bounds.s: kernel/bounds.c FORCE
$(Q)mkdir -p $(dir $@)
@@ -37,7 +46,7 @@ kernel/bounds.s: kernel/bounds.c FORCE
 
 $(obj)/$(bounds-file): kernel/bounds.s Kbuild
$(Q)mkdir -p $(dir $@)
-   $(call cmd,bounds)
+   $(call cmd,offsets)
 
 #
 # 2) Generate asm-offsets.h
@@ -49,32 +58,6 @@ always  += $(offsets-file)
 targets += $(offsets-file)
 targets += arch/$(SRCARCH)/kernel/asm-offsets.s
 
-
-# Default sed regexp - multiline due to syntax constraints
-define sed-y
-   "/^->/{s:->#\(.*\):/* \1 */:; \
-   s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
-   s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
-   s:->::; p;}"
-endef
-
-quiet_cmd_offsets = GEN $@
-define cmd_offsets
-   (set -e; \
-echo "#ifndef __ASM_OFFSETS_H__"; \
-echo "#define __ASM_OFFSETS_H__"; \
-echo "/*"; \
-echo " * DO NOT MODIFY."; \
-echo " *"; \
-echo " * This file was generated by Kbuild"; \
-echo " *"; \
-echo " */"; \
-echo ""; \
-sed -ne $(sed-y) $<; \
-echo ""; \
-echo "#endif" ) > $@
-endef
-
 # We use internal kbuild rules to avoid the "is up to date" message from make
 arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \
   $(obj)/$(bounds-file) FORCE
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [v3.19-rc1] read_events => aio_read_events => WARNING: "do not call blocking ops when !TASK_RUNNING"

2014-12-23 Thread Fam Zheng
On Mon, 12/22 13:12, Bjørn Mork wrote:
> Hello,
> 
> I got this warning on v3.19-rc1:
> 
> [   16.325814] [ cut here ]
> [   16.325832] WARNING: CPU: 0 PID: 3368 at kernel/sched/core.c:7303 
> __might_sleep+0x55/0x94()
> [   16.325839] do not call blocking ops when !TASK_RUNNING; state=1 set at 
> [] prepare_to_wait_event+0x8c/0xd8
> [   16.325843] Modules linked in: xt_multiport xt_addrtype xt_conntrack 
> ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_conntrack_ipv4 
> nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack bridge dm_thin_pool 
> dm_persistent_data crc32c_generic libcrc32c dm_bio_prison dm_bufio dm_mod 
> iptable_filter ip_tables bnep xt_hl nf_log_ipv6 nf_log_common xt_LOG 
> binfmt_misc ip6table_filter ip6_tables x_tables nfsd nfs_acl nfs lockd grace 
> fscache sunrpc 8021q garp mrp stp llc tun fuse loop iTCO_wdt 
> iTCO_vendor_support snd_hda_codec_conexant snd_hda_codec_generic coretemp 
> arc4 kvm_intel kvm ecb evdev psmouse serio_raw uvcvideo videobuf2_vmalloc 
> videobuf2_memops cdc_mbim cdc_wdm cdc_ncm videobuf2_core v4l2_common usbnet 
> mii cdc_acm videodev iwlmvm btusb mac80211 bluetooth iwlwifi snd_hda_intel 
> i2c_i801 snd_hda_controller
> [   16.325980]  lpc_ich mfd_core cfg80211 snd_hda_codec snd_hwdep snd_pcm_oss 
> snd_mixer_oss snd_pcm snd_timer thinkpad_acpi wmi nvram snd soundcore rfkill 
> ac i915 battery i2c_algo_bit drm_kms_helper video drm button acpi_cpufreq 
> processor ext4 crc16 jbd2 mbcache nbd microcode sg sr_mod sd_mod cdrom ahci 
> libahci libata scsi_mod e1000e ehci_pci uhci_hcd ehci_hcd ptp usbcore 
> usb_common pps_core thermal thermal_sys
> [   16.326070] CPU: 0 PID: 3368 Comm: mysqld Not tainted 3.19.0-rc1 #270
> [   16.326074] Hardware name: LENOVO 2776LEG/2776LEG, BIOS 6EET55WW (3.15 ) 
> 12/19/2011
> [   16.326077]  0009 88022a66fc58 813cf430 
> 
> [   16.326087]  88022a66fca8 88022a66fc98 8104117c 
> 92e8
> [   16.326095]  81060e84 815a5241 026d 
> 
> [   16.326104] Call Trace:
> [   16.326112]  [] dump_stack+0x4c/0x65
> [   16.326119]  [] warn_slowpath_common+0x9c/0xb6
> [   16.326126]  [] ? __might_sleep+0x55/0x94
> [   16.326132]  [] warn_slowpath_fmt+0x41/0x43
> [   16.326141]  [] ? native_sched_clock+0x35/0x37
> [   16.326147]  [] ? prepare_to_wait_event+0x8c/0xd8
> [   16.326153]  [] ? prepare_to_wait_event+0x8c/0xd8
> [   16.326159]  [] __might_sleep+0x55/0x94
> [   16.326166]  [] mutex_lock_nested+0x2a/0x39e
> [   16.326173]  [] ? spin_unlock_irqrestore+0x9/0xb
> [   16.326180]  [] ? local_clock+0x19/0x22
> [   16.326187]  [] ? lock_release_holdtime.part.26+0x71/0x7f
> [   16.326194]  [] ? _raw_spin_unlock_irqrestore+0x3a/0x48
> [   16.326201]  [] aio_read_events+0x45/0x282
> [   16.326208]  [] read_events+0x1c0/0x23c
> [   16.326214]  [] ? abort_exclusive_wait+0x95/0x95
> [   16.326221]  [] ? hrtimer_get_res+0x47/0x47
> [   16.326227]  [] ? hrtimer_start_range_ns+0xf/0x11
> [   16.326234]  [] SyS_io_getevents+0x4c/0x76
> [   16.326241]  [] system_call_fastpath+0x12/0x17
> [   16.326246] ---[ end trace aa79768e2e6ba68a ]---
> 
> 
> And the mysqld process just sits there burning CPU:
> 
> top - 13:01:23 up 33 min, 15 users,  load average: 10.07, 10.23, 9.28
> Tasks: 175 total,   2 running, 173 sleeping,   0 stopped,   0 zombie
> %Cpu(s):  4.0 us, 95.5 sy,  0.0 ni,  0.2 id,  0.1 wa,  0.0 hi,  0.2 si,  0.0 
> st
> KiB Mem:   8069208 total,  4414640 used,  3654568 free,   475752 buffers
> KiB Swap:  9525244 total,0 used,  9525244 free.  2063192 cached Mem
> 
>   PID USER  PR  NIVIRTRESSHR S  %CPU %MEM TIME+ COMMAND   
>   
> 
>  3343 mysql 20   0  549944  47456  10492 S 171.9  0.6  60:21.11 mysqld
>   
> 
> 
> 
> Looking at it, it just loops over the io_getevents syscall:
> 
> 
> nemi:/tmp# strace -fp 3343
> Process 3343 attached with 17 threads
> [pid  3414] futex(0x7f08cbf43ba4, FUTEX_WAIT_PRIVATE, 95, NULL  ...>
> [pid  3410] rt_sigtimedwait([HUP QUIT ALRM TERM TSTP], NULL, NULL, 8 
> 
> [pid  3396] futex(0x7f08cd669a0c, FUTEX_WAIT_PRIVATE, 1, NULL 
> [pid  3395] restart_syscall(<... resuming interrupted call ...>  ...>
> [pid  3393] restart_syscall(<... resuming interrupted call ...>  ...>
> [pid  3375] io_getevents(139675742199808, 1, 256,  
> [pid  3394] restart_syscall(<... resuming interrupted call ...>  ...>
> [pid  3343] restart_syscall(<... resuming interrupted call ...>  ...>
> [pid  3368] io_getevents(139675744239616, 1, 256,  
> [pid  3370] io_getevents(139675744198656, 1, 256,  
> [pid  3372] io_getevents(139675744157696, 1, 256,  
> [pid  3369] io_getevents(139675744219136, 1, 256,  
> [pid  3376] io_getevents(139675696115712, 

[PATCH 2/2] kbuild: remove redundant line from bounds.h/asm-offsets.h

2014-12-23 Thread Masahiro Yamada
This line produces an extra comment line for bounds.h and
asm-offsets.h.

Signed-off-by: Masahiro Yamada 
---

 Kbuild | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Kbuild b/Kbuild
index 55a639f..5ac6d06 100644
--- a/Kbuild
+++ b/Kbuild
@@ -23,7 +23,6 @@ define cmd_offsets
 echo " * DO NOT MODIFY."; \
 echo " *"; \
 echo " * This file was generated by Kbuild"; \
-echo " *"; \
 echo " */"; \
 echo ""; \
 sed -ne $(sed-y) $<; \
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] kbuild: Refactor ./Kbuild

2014-12-23 Thread Masahiro Yamada



Masahiro Yamada (2):
  kbuild: merge bounds.h and asm-offsets.h rules
  kbuild: remove redundant line from bounds.h/asm-offsets.h

 Kbuild | 60 +---
 1 file changed, 21 insertions(+), 39 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] openvswitch: fix odd_ptr_err.cocci warnings

2014-12-23 Thread kbuild test robot
net/openvswitch/vport-gre.c:188:5-11: inconsistent IS_ERR and PTR_ERR, PTR_ERR 
on line 189

 PTR_ERR should access the value just tested by IS_ERR

Semantic patch information:
 There can be false positives in the patch case, where it is the call
 IS_ERR that is wrong.

Generated by: scripts/coccinelle/tests/odd_ptr_err.cocci

CC: Pravin B Shelar 
Signed-off-by: Fengguang Wu 
---

 vport-gre.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -186,7 +186,7 @@ static int gre_tnl_send(struct vport *vp
/* Push Tunnel header. */
skb = __build_header(skb, tunnel_hlen);
if (IS_ERR(skb)) {
-   err = PTR_ERR(rt);
+   err = PTR_ERR(skb);
skb = NULL;
goto err_free_rt;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 5/8] irqchip: Conexant CX92755 interrupts controller driver

2014-12-23 Thread Baruch Siach
Hi Arnd,

On Tue, Dec 23, 2014 at 10:02:18PM +0100, Arnd Bergmann wrote:
> On Tuesday 23 December 2014 09:58:42 Baruch Siach wrote:
> > +static void __exception_irq_entry digicolor_handle_irq(struct pt_regs 
> > *regs)
> > +{
> > +   u32 status, hwirq;
> > +
> > +   do {
> > +   status = readl(digicolor_irq_base + IC_INT0STATUS_LO);
> > +   if (status) {
> > +   hwirq = ffs(status) - 1;
> > +   } else {
> > +   status = readl(digicolor_irq_base + 
> > IC_INT0STATUS_XLO);
> > +   if (status)
> > +   hwirq = ffs(status) - 1 + 32;
> > +   else
> > +   return;
> > +   }
> > +
> > +   handle_domain_irq(digicolor_irq_domain, hwirq, regs);
> > +   } while (1);
> > +}
> > 
> 
> Have you tried using the generic_irqchip code for this? The hardware
> seems simple enough.

Thanks for the tip. I'll look into converting to GENERIC_IRQ_CHIP for next 
version.

baruch

-- 
 http://baruch.siach.name/blog/  ~. .~   Tk Open Systems
=}ooO--U--Ooo{=
   - bar...@tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2] cpufreq: suspend cpufreq governors on shutdown

2014-12-23 Thread Doug Anderson
We should stop cpufreq governors when we shut down the system.  If we
don't do this, we can end up with this deadlock:

1. cpufreq governor may be running on a CPU other than CPU0.
2. In machine_restart() we call smp_send_stop() which stops CPUs.
   If one of these CPUs was actively running a cpufreq governor
   then it may have the mutex / spinlock needed to access the main
   PMIC in the system (perhaps over I2C)
3. If a machine needs access to the main PMIC in order to shutdown
   then it will never get it since the mutex was lost when the other
   CPU stopped.
4. We'll hang (possibly eventually hitting the hard lockup detector).

Let's avoid the problem by stopping the cpufreq governor at shutdown,
which is a sensible thing to do anyway.

Signed-off-by: Doug Anderson 
---
Changes in v2:
- Add a comment about why we register
- Don't create cpufreq_shutdown() wrapper function

 drivers/cpufreq/cpufreq.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a09a29c..33f3d65 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -2550,6 +2551,14 @@ int cpufreq_unregister_driver(struct cpufreq_driver 
*driver)
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
 
+/*
+ * Stop cpufreq at shutdown to make sure it isn't holding any locks
+ * or mutexes when secondary CPUs are halted.
+ */
+static struct syscore_ops cpufreq_syscore_ops = {
+   .shutdown = cpufreq_suspend,
+};
+
 static int __init cpufreq_core_init(void)
 {
if (cpufreq_disabled())
@@ -2558,6 +2567,8 @@ static int __init cpufreq_core_init(void)
cpufreq_global_kobject = kobject_create();
BUG_ON(!cpufreq_global_kobject);
 
+   register_syscore_ops(_syscore_ops);
+
return 0;
 }
 core_initcall(cpufreq_core_init);
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] cpufreq: suspend cpufreq governors on shutdown

2014-12-23 Thread Doug Anderson
Virseh,


On Tue, Dec 23, 2014 at 5:46 PM, Viresh Kumar  wrote:
> On 24 December 2014 at 05:41, Doug Anderson  wrote:
>> We should stop cpufreq governors when we shut down the system.  If we
>> don't do this, we can end up with this deadlock:
>
> Can you also add what exactly happens in such deadlock? Some lockdeps?
> Or just a hang ?

It only fails 1 in ~50 calls to halt.

When it fails, most times I get a hang.  Sometimes I actually got a hard lockup:

[   23.511813] reboot: Power down
[   40.418425] Kernel panic - not syncing: Watchdog detected hard
LOCKUP on cpu 1

I'm slightly amazed that the hard lockup detector even fired (and I'm
not sure why it sometimes doesn't fire).  ...when I use kdb to get a
trace at this point:

Stack traceback for pid 6564
0xecd2ee00 65641  00   D  0xecd2f1e8  halt
[] (__schedule) from [] (schedule+0xa4/0xa8)
[] (schedule) from [] (schedule_preempt_disabled+0x18/0x1c)
[] (schedule_preempt_disabled) from []
(mutex_lock_nested+0x294/0x3e4)
[] (mutex_lock_nested) from [] (regmap_lock_mutex+0x1c/0x20)
[] (regmap_lock_mutex) from []
(regmap_update_bits+0x34/0x6c)
[] (regmap_update_bits) from []
(rk808_device_shutdown+0x54/0x7c)
[] (rk808_device_shutdown) from []
(machine_power_off+0x34/0x3c)
[] (machine_power_off) from [] (kernel_power_off+0x68/0x7c)
[] (kernel_power_off) from [] (SyS_reboot+0x154/0x1fc)
[] (SyS_reboot) from [] (ret_fast_syscall+0x0/0x48)


I'm not used to using lockdep.  Trying now.  OK, no lockdep warning.

I'm relatively confident that I understand the problem because I added
a bunch of other debug info.  You can see my patch at
.  In the case I
captured I confirmed that I was stopping CPU1 while it held the mutex.


>> 1. cpufreq governor may be running on a CPU other than CPU0.
>> 2. In machine_restart() we call smp_send_stop() which stops CPUs.
>>If one of these CPUs was actively running a cpufreq governor
>>then it may have the mutex / spinlock needed to access the main
>>PMIC in the system (perhaps over I2C)
>> 3. If a machine needs access to the main PMIC in order to shutdown
>>then it will never get it since the mutex was lost when the other
>>CPU stopped.
>>
>> Let's avoid the race by stopping the cpufreq governor at shutdown,
>> which is a sensible thing to do anyway.
>>
>> Signed-off-by: Doug Anderson 
>> ---
>> NOTE: This was developed / tested / on a 3.14 kernel with backports.
>> I have confirmed that it compiles on a mainline kernel and doesn't
>> crash, but I haven't verified that there isn't some other fix in
>> mainline that also fixes this problem.  If you are aware of such a fix
>> then please drop this patch.
>
> No, its a new problem.

OK, good to know.


>>  drivers/cpufreq/cpufreq.c | 12 
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>> index a09a29c..bd89721 100644
>> --- a/drivers/cpufreq/cpufreq.c
>> +++ b/drivers/cpufreq/cpufreq.c
>> @@ -27,6 +27,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  #include 
>>
>> @@ -2550,6 +2551,15 @@ int cpufreq_unregister_driver(struct cpufreq_driver 
>> *driver)
>>  }
>>  EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
>>
>> +static void cpufreq_shutdown(void)
>> +{
>> +   cpufreq_suspend();
>> +}
>> +
>> +static struct syscore_ops cpufreq_syscore_ops = {
>> +   .shutdown = cpufreq_shutdown,
>
> directly pass cpufreq_suspend() here and add a note over the
> cpufreq_syscore_ops on why it exists here.

Done.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/8] ARM: digicolor: add low level debug support

2014-12-23 Thread Baruch Siach
Hi Arnd,

On Tue, Dec 23, 2014 at 10:00:17PM +0100, Arnd Bergmann wrote:
> On Tuesday 23 December 2014 09:58:39 Baruch Siach wrote:
> > @@ -14,5 +14,6 @@ static const char *digicolor_dt_compat[] __initconst = {
> >  };
> >  
> >  DT_MACHINE_START(DIGICOLOR, "Conexant Digicolor (Flattened Device Tree)")
> > +   .map_io = debug_ll_io_init,
> > .dt_compat  = digicolor_dt_compat,
> >  MACHINE_END
> 
> This change is not needed, the debug_ll_io_init function is used by default
> if no other map_io callback is specified.

OK. I'll remove it for next version.

Thanks,
baruch

-- 
 http://baruch.siach.name/blog/  ~. .~   Tk Open Systems
=}ooO--U--Ooo{=
   - bar...@tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] perf hists browser: Fix segfault when showing callchain

2014-12-23 Thread Namhyung Kim
When perf report on TUI shows callchain it checks first node has
siblings to determine whether it needs to print percentage value.  But
it missed a case that first node is NULL.  So sometimes it segfaults
like below:

  $ perf top -g
  perf: Segmentation fault
   backtrace 
  perf[0x4fcefb]
  /usr/lib/libc.so.6(+0x33b20)[0x7f2a35839b20]
  perf(rb_next+0x8)[0x47d3d8]
  perf[0x4f6058]
  perf[0x4f833b]
  perf[0x4f8610]
  perf[0x4f209e]
  perf(ui_browser__run+0x3a)[0x4f2e6a]
  perf[0x4f94ee]
  perf(perf_evlist__tui_browse_hists+0x94)[0x4fbbf4]
  perf[0x444d10]
  /usr/lib/libpthread.so.0(+0x7314)[0x7f2a37070314]
  /usr/lib/libc.so.6(clone+0x6d)[0x7f2a358ee5bd]

  $ addr2line -e `which perf` 0x4f6058
  /home/namhyung/project/linux/tools/perf/ui/browsers/hists.c:553

I don't know why the backtrace didn't print some symbols..

Fixes: 4087d11cd945 ("perf hists browser: Print overhead percent value for 
first-level callchain")
Signed-off-by: Namhyung Kim 
---
 tools/perf/ui/browsers/hists.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index e6bb04b5b09b..788506eef567 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -550,7 +550,7 @@ static int hist_browser__show_callchain(struct hist_browser 
*browser,
bool need_percent;
 
node = rb_first(root);
-   need_percent = !!rb_next(node);
+   need_percent = node && rb_next(node);
 
while (node) {
struct callchain_node *child = rb_entry(node, struct 
callchain_node, rb_node);
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/4] ARM: dts: Add exynos_usbphy node for exynos3250

2014-12-23 Thread Jaewon Kim
This patch adds device tree node for exynos_usbphy to use USB 2.0 Device.

Signed-off-by: Jaewon Kim 
---
 arch/arm/boot/dts/exynos3250.dtsi |   10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/exynos3250.dtsi 
b/arch/arm/boot/dts/exynos3250.dtsi
index 2246549..27d385f 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -279,6 +279,16 @@
status = "disabled";
};
 
+   exynos_usbphy: exynos-usbphy@125B {
+   compatible = "samsung,exynos3250-usb2-phy";
+   reg = <0x125B 0x100>;
+   samsung,pmureg-phandle = <_system_controller>;
+   clocks = < CLK_USBOTG>, < CLK_SCLK_UPLL>;
+   clock-names = "phy", "ref";
+   #phy-cells = <1>;
+   status = "disabled";
+   };
+
amba {
compatible = "arm,amba-bus";
#address-cells = <1>;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 3/4] ARM: dts: Enable USB node for exynos3250-rinato

2014-12-23 Thread Jaewon Kim
This patch enables hsotg and usbphy node to use USB 2.0 Device.

Signed-off-by: Jaewon Kim 
---
 arch/arm/boot/dts/exynos3250-rinato.dts |   10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 80aa8b4..bf4c17b 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -125,6 +125,16 @@
};
 };
 
+_usbphy {
+   status = "okay";
+};
+
+ {
+   vusb_d-supply = <_reg>;
+   vusb_a-supply = <_reg>;
+   status = "okay";
+};
+
 _0 {
#address-cells = <1>;
#size-cells = <0>;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 4/4] ARM: dts: Enable USB node for exynos3250-monk

2014-12-23 Thread Jaewon Kim
This patch adds device tree node for hsotg to control USB 2.0 Device.

Signed-off-by: Jaewon Kim 
---
 arch/arm/boot/dts/exynos3250-monk.dts |   10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/exynos3250-monk.dts 
b/arch/arm/boot/dts/exynos3250-monk.dts
index 24822aa..0c1d85d 100644
--- a/arch/arm/boot/dts/exynos3250-monk.dts
+++ b/arch/arm/boot/dts/exynos3250-monk.dts
@@ -134,6 +134,16 @@
};
 };
 
+_usbphy {
+   status = "okay";
+};
+
+ {
+   vusb_d-supply = <_reg>;
+   vusb_a-supply = <_reg>;
+   status = "okay";
+};
+
 _0 {
#address-cells = <1>;
#size-cells = <0>;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/4] ARM: dts: Add hsotg node for exynos3250

2014-12-23 Thread Jaewon Kim
This patch adds device tree node for hsotg to control USB 2.0 Device.

Signed-off-by: Jaewon Kim 
---
 arch/arm/boot/dts/exynos3250.dtsi |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/exynos3250.dtsi 
b/arch/arm/boot/dts/exynos3250.dtsi
index 27d385f..204a84b 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -255,6 +255,17 @@
status = "disabled";
};
 
+   hsotg: hsotg@1248 {
+   compatible = "snps,dwc2";
+   reg = <0x1248 0x2>;
+   interrupts = <0 141 0>;
+   clocks = < CLK_USBOTG>;
+   clock-names = "otg";
+   phys = <_usbphy 0>;
+   phy-names = "usb2-phy";
+   status = "disabled";
+   };
+
mshc_0: mshc@1251 {
compatible = "samsung,exynos5250-dw-mshc";
reg = <0x1251 0x1000>;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 0/4] ARM: dts: Add USB node for exynos3250 SoC boards

2014-12-23 Thread Jaewon Kim
This patch series adds USB device node and phy for exynos3250 SoC.
And enables for rinato and monk boards.

Changes in v2:
 - remove unnessasary property "samsung,sysreg-phandle"
 - change "xusbxti" clock to "CLK_SCLK_UPLL"

Jaewon Kim (4):
  ARM: dts: Add exynos_usbphy node for exynos3250
  ARM: dts: Add hsotg node for exynos3250
  ARM: dts: Enable USB node for exynos3250-rinato
  ARM: dts: Enable USB node for exynos3250-monk

 arch/arm/boot/dts/exynos3250-monk.dts   |   10 ++
 arch/arm/boot/dts/exynos3250-rinato.dts |   10 ++
 arch/arm/boot/dts/exynos3250.dtsi   |   21 +
 3 files changed, 41 insertions(+)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] linux/kernel.h: merge ARRAY_AND_SIZE defines

2014-12-23 Thread Joe Perches
On Wed, 2014-12-24 at 14:38 +0900, Masahiro Yamada wrote:
> ARRAY_AND_SIZE is a useful macro.  Its definition is already
> duplicated in some headers.  Move it to include/linux/kernel.h.

I think it's not a good/useful macro and
would prefer the uses expanded instead.

The uses of ARRAY_AND_SIZE in structure
definitions aren't particularly bad, but the
ARRAY_AND_SIZE uses that hide the number of
arguments in a function I think are suboptimal.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] usb: gadget: ffs: Fix sparse error

2014-12-23 Thread Joe Perches
On Wed, 2014-12-24 at 10:59 +0530, Rohith Seelaboyina wrote:
> Dynamic memory allocation through kmalloc is more safer
> than declaring variable array size, Fix this error by
> using kmalloc for memory allocation, Check if memory
> allocation is successful and return -ENOMEM on failure.
[]
> diff --git a/drivers/usb/gadget/function/f_fs.c 
> b/drivers/usb/gadget/function/f_fs.c
[]
> @@ -397,10 +397,15 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data 
> *ffs, char __user *buf,
>* We are holding ffs->ev.waitq.lock and ffs->mutex and we need
>* to release them.
>*/
> - struct usb_functionfs_event events[n];
>   unsigned i = 0;
> + int ret;
> + struct usb_functionfs_event *events = kmalloc(n *
> + sizeof(struct usb_functionfs_event), GFP_KERNEL);
> +
> + if (unlikely(!events))
> + return -ENOMEM;
>  
> - memset(events, 0, sizeof events);
> + memset(events, 0, n * sizeof(*events));

kcalloc without memset please.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Merry Xmas and how 2 get your spendings back ;)

2014-12-23 Thread Richard
Hi!

Here is your new live for 2015!
Luving it!


 
http://aff.optiontime.com/promoRedirect?key=ej0xMzUyNDQ1MSZsPTEzNTI0NDQ1JnA9NjQ4MQ%3D%3D




























No more such info ? Simply answer 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] linux/kernel.h: merge ARRAY_AND_SIZE defines

2014-12-23 Thread Masahiro Yamada
ARRAY_AND_SIZE is a useful macro.  Its definition is already
duplicated in some headers.  Move it to include/linux/kernel.h.

Signed-off-by: Masahiro Yamada 
---

 arch/arm/mach-mmp/common.h| 1 -
 arch/arm/mach-pxa/generic.h   | 2 --
 arch/arm/mach-ux500/db8500-regs.h | 2 --
 drivers/pinctrl/pinctrl-lantiq.h  | 2 --
 include/linux/kernel.h| 1 +
 5 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index cf445ba..e503f63 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -1,5 +1,4 @@
 #include 
-#define ARRAY_AND_SIZE(x)  (x), ARRAY_SIZE(x)
 
 extern void timer_init(int irq);
 
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 7a9fa1a..da11977 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -23,8 +23,6 @@ extern void pxa_timer_init(void);
mi->bank[__nr].start = (__start), \
mi->bank[__nr].size = (__size)
 
-#define ARRAY_AND_SIZE(x)  (x), ARRAY_SIZE(x)
-
 #define pxa25x_handle_irq icip_handle_irq
 extern void __init pxa25x_init_irq(void);
 extern void __init pxa25x_map_io(void);
diff --git a/arch/arm/mach-ux500/db8500-regs.h 
b/arch/arm/mach-ux500/db8500-regs.h
index 2739955..80a6deb 100644
--- a/arch/arm/mach-ux500/db8500-regs.h
+++ b/arch/arm/mach-ux500/db8500-regs.h
@@ -195,6 +195,4 @@
 /* Used by some plat-nomadik code */
 #define io_p2v(n)  __io_address(n)
 
-#define ARRAY_AND_SIZE(x)  (x), ARRAY_SIZE(x)
-
 #endif
diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
index c7cfad5..508d205 100644
--- a/drivers/pinctrl/pinctrl-lantiq.h
+++ b/drivers/pinctrl/pinctrl-lantiq.h
@@ -21,8 +21,6 @@
 
 #include "core.h"
 
-#define ARRAY_AND_SIZE(x)  (x), ARRAY_SIZE(x)
-
 #define LTQ_MAX_MUX4
 #define MFPR_FUNC_MASK 0x3
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 049d43b..4e8fc3d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -59,6 +59,7 @@ void printch(int c);
 #define IS_ALIGNED(x, a)   (((x) & ((typeof(x))(a) - 1)) == 0)
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+#define ARRAY_AND_SIZE(x)  (x), ARRAY_SIZE(x)
 
 /*
  * This looks more complex than it should be. But we need to
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] usb: gadget: ffs: Fix sparse error

2014-12-23 Thread Rohith Seelaboyina
This patch fixes the sparse error in functionfs
driver.

drivers/usb/gadget/function/f_fs.c:400:44: error: bad
constant experssion.

Dynamic memory allocation through kmalloc is more safer
than declaring variable array size, Fix this error by
using kmalloc for memory allocation, Check if memory
allocation is successful and return -ENOMEM on failure.

Signed-off-by: Rohith Seelaboyina 
---
 drivers/usb/gadget/function/f_fs.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/function/f_fs.c 
b/drivers/usb/gadget/function/f_fs.c
index 63314ede7ba6..6ac50891b697 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -397,10 +397,15 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data 
*ffs, char __user *buf,
 * We are holding ffs->ev.waitq.lock and ffs->mutex and we need
 * to release them.
 */
-   struct usb_functionfs_event events[n];
unsigned i = 0;
+   int ret;
+   struct usb_functionfs_event *events = kmalloc(n *
+   sizeof(struct usb_functionfs_event), GFP_KERNEL);
+
+   if (unlikely(!events))
+   return -ENOMEM;
 
-   memset(events, 0, sizeof events);
+   memset(events, 0, n * sizeof(*events));
 
do {
events[i].type = ffs->ev.types[i];
@@ -421,8 +426,10 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, 
char __user *buf,
spin_unlock_irq(>ev.waitq.lock);
mutex_unlock(>mutex);
 
-   return unlikely(__copy_to_user(buf, events, sizeof events))
-   ? -EFAULT : sizeof events;
+   ret = unlikely(__copy_to_user(buf, events, n * sizeof(*events)))
+   ? -EFAULT : n * sizeof(*events);
+   kfree(events);
+   return ret;
 }
 
 static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH RFC v3 13/18] drm: panel: Add support for Himax HX8369A MIPI DSI panel

2014-12-23 Thread Liu Ying

Hi Andrzej,

On 12/23/2014 06:38 PM, Andrzej Hajda wrote:

Hi Liu Ying,

On 12/23/2014 04:46 AM, Liu Ying wrote:

This patch adds support for Himax HX8369A MIPI DSI panel.

Signed-off-by: Liu Ying 
---
v2->v3:
  * Sort the included header files alphabetically.

v1->v2:
  * Address almost all comments from Thierry Reding.
  * Remove several DT properties as they can be implied by the compatible 
string.
  * Add the HIMAX/himax prefixes to the driver's Kconfig name and driver name.
  * Move the driver's Makefile entry place to sort the entries alphabetically.
  * Reuse several standard DCS functions instead of inventing wheels.
  * Move the panel resetting and power logics to the driver probe/remove stages.
This may simplify panel prepare/unprepare hooks. The power consumption 
should
not change a lot at DPMS since the panel enters sleep mode at that time.


What kind of issues did you have with reset/power logic in
prepare/unprepare? As I see it should be just a matter of moving
power on/off functions to prepare/unprepare, am I right?


The issue is that the panel does not work any more if I have the
reset/power logic in prepare/unprepare.  I don't see any valuable
information in dmesg when the system boots up or I unblank/blank
the framebuffer manually via sysfs.  The panel backlight does not
light up.

I think it should be a matter of moving (power-on and reset)/
power-off to prepare/unprepare.

In my system, the power for the panel is always enabled.  So, this
issue is probably caused by the reset operation.




  * Add the module author.
  * Other minor changes, such as coding style issues.

  .../devicetree/bindings/panel/himax,hx8369a.txt|  41 ++
  drivers/gpu/drm/panel/Kconfig  |   5 +
  drivers/gpu/drm/panel/Makefile |   1 +
  drivers/gpu/drm/panel/panel-himax-hx8369a.c| 573 +
  4 files changed, 620 insertions(+)
  create mode 100644 Documentation/devicetree/bindings/panel/himax,hx8369a.txt
  create mode 100644 drivers/gpu/drm/panel/panel-himax-hx8369a.c

diff --git a/Documentation/devicetree/bindings/panel/himax,hx8369a.txt 
b/Documentation/devicetree/bindings/panel/himax,hx8369a.txt
new file mode 100644
index 000..36a2f11
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/himax,hx8369a.txt
@@ -0,0 +1,41 @@
+Himax HX8369A WVGA 16.7M color TFT single chip driver with internal GRAM
+
+Himax HX8369A is a WVGA resolution driving controller.
+It is designed to provide a single chip solution that combines a source
+driver and power supply circuits to drive a TFT dot matrix LCD with
+480RGBx864 dots at the maximum.
+
+The HX8369A supports several interface modes, including MPU MIPI DBI Type
+A/B mode, MIPI DPI/DBI Type C mode, MIPI DSI video mode, MIPI DSI command
+mode and MDDI mode. The interface mode is selected by the external hardware
+pins BS[3:0].
+
+Currently, only the MIPI DSI video mode is supported.
+
+Required properties:
+  - compatible: should be a panel's compatible string
+  - reg: the virtual channel number of a DSI peripheral as described in [1]
+  - reset-gpios: a GPIO spec for the reset pin
+
+Optional properties:
+  - vdd1-supply: I/O and interface power supply
+  - vdd2-supply: analog power supply
+  - vdd3-supply: logic power supply
+  - dsi-vcc-supply: DSI and MDDI power supply
+  - vpp-supply: OTP programming voltage
+  - bs0-gpios: a GPIO spec for the pin BS0
+  - bs1-gpios: a GPIO spec for the pin BS1
+  - bs2-gpios: a GPIO spec for the pin BS2
+  - bs3-gpios: a GPIO spec for the pin BS3


I wonder if it wouldn't be better to replace it by gpio list, sth like:
  - bs-gpios: list of four GPIO specs for BS0-BS3 pins

At least documentation suggests it [1], it also allows to omit some pins
if necessary, but it is just suggestion.

[1]: Documentation/devicetree/bindings/gpio/gpio.txt


The suggestion looks good.  I may try to use the gpio list.  Thanks.




+
+[1] Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt
+
+Example:
+   panel {
+   compatible = "truly,tft480800-16-e-dsi";
+   reg = <0>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_mipi_panel>;
+   reset-gpios = < 11 GPIO_ACTIVE_LOW>;
+   bs2-gpios = < 14 GPIO_ACTIVE_HIGH>;
+   };
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 024e98e..81b0bf0 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -16,6 +16,11 @@ config DRM_PANEL_SIMPLE
  that it can be automatically turned off when the panel goes into a
  low power state.

+config DRM_PANEL_HIMAX_HX8369A
+   tristate "Himax HX8369A panel"
+   depends on OF
+   select DRM_MIPI_DSI
+
  config DRM_PANEL_LD9040
tristate "LD9040 RGB/SPI panel"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 4b2a043..d5dbe06 100644
--- 

Re: [PATCH V3 2/2] dmaengine: Add driver for IMG MDC

2014-12-23 Thread Vinod Koul
On Thu, Dec 11, 2014 at 02:59:17PM -0800, Andrew Bresticker wrote:
> Add support for the IMG Multi-threaded DMA Controller (MDC) found on
> certain IMG SoCs.  Currently this driver supports the variant present
> on the MIPS-based Pistachio SoC.a

Overall looks okay. I also need some review by DT folks on the bindings

> +static void mdc_list_desc_config(struct mdc_chan *mchan,
> +  struct mdc_hw_list_desc *ldesc,
> +  enum dma_transfer_direction dir,
> +  dma_addr_t src, dma_addr_t dst, size_t len)
> +{
> + struct mdc_dma *mdma = mchan->mdma;
> + unsigned int max_burst, burst_size;
> +
> + ldesc->gen_conf = MDC_GENERAL_CONFIG_IEN | MDC_GENERAL_CONFIG_LIST_IEN |
> + MDC_GENERAL_CONFIG_LEVEL_INT | MDC_GENERAL_CONFIG_PHYSICAL_W |
> + MDC_GENERAL_CONFIG_PHYSICAL_R;
> + ldesc->readport_conf =
> + (mchan->thread << MDC_READ_PORT_CONFIG_STHREAD_SHIFT) |
> + (mchan->thread << MDC_READ_PORT_CONFIG_RTHREAD_SHIFT) |
> + (mchan->thread << MDC_READ_PORT_CONFIG_WTHREAD_SHIFT);
> + ldesc->read_addr = src;
> + ldesc->write_addr = dst;
> + ldesc->xfer_size = len - 1;
> + ldesc->node_addr = 0;
> + ldesc->cmds_done = 0;
> + ldesc->ctrl_status = MDC_CONTROL_AND_STATUS_LIST_EN |
> + MDC_CONTROL_AND_STATUS_EN;
> + ldesc->next_desc = NULL;
> +
> + if (IS_ALIGNED(dst, mdma->bus_width) &&
> + IS_ALIGNED(src, mdma->bus_width))
> + max_burst = mdma->bus_width * mdma->max_burst_mult;
> + else
> + max_burst = mdma->bus_width * (mdma->max_burst_mult - 1);
> +
> + if (dir == DMA_MEM_TO_DEV) {
> + ldesc->gen_conf |= MDC_GENERAL_CONFIG_INC_R;
> + ldesc->readport_conf |= MDC_READ_PORT_CONFIG_DREQ_ENABLE;
> + mdc_set_read_width(ldesc, mdma->bus_width);
> + mdc_set_write_width(ldesc, mchan->config.dst_addr_width);
> + burst_size = min(max_burst, mchan->config.dst_maxburst *
> +  mchan->config.dst_addr_width);
why is this calculation done for burst size? Shouldn't we take the
config.dst_maxburst value configured by client?


> +static struct dma_async_tx_descriptor *mdc_prep_slave_sg(
> + struct dma_chan *chan, struct scatterlist *sgl,
> + unsigned int sg_len, enum dma_transfer_direction dir,
> + unsigned long flags, void *context)
> +{
> + struct mdc_chan *mchan = to_mdc_chan(chan);
> + struct mdc_dma *mdma = mchan->mdma;
> + struct mdc_tx_desc *mdesc;
> + struct scatterlist *sg;
> + struct mdc_hw_list_desc *curr, *prev = NULL;
> + dma_addr_t curr_phys, prev_phys;
> + unsigned int i;
> +
> + if (!sgl)
> + return NULL;
> +
> + if (!is_slave_direction(dir))
> + return NULL;
> +
> + if (mdc_check_slave_width(mchan, dir) < 0)
> + return NULL;
> +
> + mdesc = kzalloc(sizeof(*mdesc), GFP_NOWAIT);
> + if (!mdesc)
> + return NULL;
> + mdesc->chan = mchan;
> +
> + for_each_sg(sgl, sg, sg_len, i) {
> + dma_addr_t buf = sg_dma_address(sg);
> + size_t buf_len = sg_dma_len(sg);
> +
> + while (buf_len > 0) {
> + size_t xfer_size;
> +
> + curr = dma_pool_alloc(mdma->desc_pool, GFP_NOWAIT,
> +   _phys);
> + if (!curr)
> + goto free_desc;
> +
> + if (!prev) {
> + mdesc->list_phys = curr_phys;
> + mdesc->list = curr;
> + } else {
> + prev->node_addr = curr_phys;
> + prev->next_desc = curr;
> + }
> +
> + xfer_size = min_t(size_t, mdma->max_xfer_size,
> +   buf_len);
> +
> + if (dir == DMA_MEM_TO_DEV) {
> + mdc_list_desc_config(mchan, curr, dir, buf,
> +  mchan->config.dst_addr,
> +  xfer_size);
> + } else {
> + mdc_list_desc_config(mchan, curr, dir,
> +  mchan->config.src_addr,
> +  buf, xfer_size);
> + }
> +
> + prev = curr;
> + prev_phys = curr_phys;
> +
> + mdesc->list_len++;
> + mdesc->list_xfer_size += xfer_size;
> + buf += xfer_size;
> + buf_len -= xfer_size;
i see this pattern is repeat in all the .prepare calls, can we make it bit
generic and use that in the these three calls..

> + 

Re: [v3 06/26] iommu, x86: No need to migrating irq for VT-d Posted-Interrupts

2014-12-23 Thread Jiang Liu
On 2014/12/24 10:32, Zhang, Yang Z wrote:
> Jiang Liu wrote on 2014-12-24:
>> On 2014/12/24 9:38, Zhang, Yang Z wrote:
>>> Paolo Bonzini wrote on 2014-12-23:


 On 23/12/2014 10:07, Wu, Feng wrote:
>> On 23/12/2014 01:37, Zhang, Yang Z wrote:
>>> I don't quite understand it. If user set an interrupt's affinity
>>> to a CPU, but he still see the interrupt delivers to other CPUs in host.
>>> Do you think it is a right behavior?
>>
>> No, the interrupt is not delivered at all in the host.  Normally you'd 
>> have:
>>
>> - interrupt delivered to CPU from host affinity
>>
>> - VFIO interrupt handler writes to irqfd
>>
>> - interrupt delivered to vCPU from guest affinity
>>
>> Here, you just skip the first two steps.  The interrupt is
>> delivered to the thread that is running the vCPU directly, so the
>> host affinity is bypassed entirely.
>>
>> ... unless you are considering the case where the vCPU is blocked
>> and the host is processing the posted interrupt wakeup vector.
>> In that case yes, it would be better to set NDST to a CPU
>> matching the host
>> affinity.
>
> In my understanding, wakeup vector should have no relationship
> with the host affinity of the irq. Wakeup notification event
> should be delivered to the pCPU which the vCPU was blocked on. And
> in kernel's point of view, the irq is not associated with the wakeup 
> vector, right?

 That is correct indeed.  It is not associated to the wakeup vector,
 hence this patch is right, I think.

 However, the wakeup vector has the same function as the VFIO
 interrupt handler, so you could argue that it is tied to the host
 affinity rather than the guest.  Let's wait for Yang to answer.
>>>
>>> Actually, that's my original question too. I am wondering what
>>> happens if the
>> user changes the assigned device's affinity in host's /proc/irq/? If
>> ignore it is acceptable, then this patch is ok. But it seems the
>> discussion out of my scope, need some experts to tell us their idea since it 
>> will impact the user experience.
>> Hi Yang,
> 
> Hi Jiang,
> 
>>  Originally we have a proposal to return failure when user sets IRQ
>> affinity through native OS interfaces if an IRQ is in PI mode. But
>> that proposal will break CPU hot-removal because OS needs to migrate
>> away all IRQs binding to the CPU to be offlined. Then we propose
>> saving user IRQ affinity setting without changing hardware
>> configuration (keeping PI configuration). Later when PI mode is
>> disabled, the cached affinity setting will be used to setup IRQ
>> destination for native OS. On the other hand, for IRQ in PI mode, it
>> won't be delivered to native OS, so user may not sense that the IRQ is 
>> delivered to CPUs other than those in the affinity set.
> 
> The IRQ is still there but will be delivered to host in the form of PI 
> event(if the VCPU is running in root-mode). I am not sure whether those 
> interrupts should be reflected in /proc/interrupts? If the answer is yes, 
> then which entries should be used, a new PI entry or use the original IRQ 
> entry?

You are right, the native interrupt statistics will become inaccurate.
Maybe some document about this behavior is preferred.

> 
>> In that aspect, I think it's acceptable:) Regards!
> 
> Yes, if all of you guys(especially the IRQ maintainer) are think it is 
> acceptable then we can follow current implementation and document it.
Good suggestion, we will send an email to Thomas for advice after New
Year.
> 
>> Gerry
>>>

 Paolo
>>>
>>>
>>> Best regards,
>>> Yang
>>>
>>>
> 
> 
> Best regards,
> Yang
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/2] merge_config.sh: add -? for help

2014-12-23 Thread Masahiro Yamada
Hi, Olof

Not that I care, but what does this patch improve?




On Thu, 11 Dec 2014 12:55:04 -0800
Olof Johansson  wrote:

> It's usual enough for help text that it makes sense to support it.
> 
> Signed-off-by: Olof Johansson 
> ---
>  scripts/kconfig/merge_config.sh |   12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
> index 2ab91b9..0c89537 100755
> --- a/scripts/kconfig/merge_config.sh
> +++ b/scripts/kconfig/merge_config.sh
> @@ -28,11 +28,11 @@ trap clean_up HUP INT TERM
>  
>  usage() {
>   echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
> - echo "  -hdisplay this help text"
> - echo "  -monly merge the fragments, do not execute the make command"
> - echo "  -nuse allnoconfig instead of alldefconfig"
> - echo "  -rlist redundant entries when merging fragments"
> - echo "  -Odir to put generated output files"
> + echo "  -h or -? display this help text"
> + echo "  -m   only merge the fragments, do not execute the make 
> command"
> + echo "  -n   use allnoconfig instead of alldefconfig"
> + echo "  -r   list redundant entries when merging fragments"
> + echo "  -O   dir to put generated output files"
>  }
>  
>  MAKE=true
> @@ -52,7 +52,7 @@ while true; do
>   shift
>   continue
>   ;;
> - "-h")
> + "-h"|"-?")
>   usage
>   exit
>   ;;
> -- 
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC/PATCH] extcon: otg_gpio: add driver for USB OTG port controlled by GPIO(s)

2014-12-23 Thread Peter Chen
On Tue, Dec 23, 2014 at 11:40:23AM -0800, David Cohen wrote:
> Hi Peter,
> 
> Thanks for the review.
> 
> On Tue, Dec 23, 2014 at 09:25:18AM +0800, Peter Chen wrote:
> > On Mon, Dec 22, 2014 at 02:43:37PM -0800, David Cohen wrote:
> > > Some platforms have an USB OTG port fully (or partially) controlled by
> > > GPIOs:
> > > 
> > > (1) USB ID is connected directly to GPIO
> > > 
> > > Optionally:
> > > (2) VBUS is enabled by a GPIO (when ID is grounded)
> > > (3) Platform has 2 USB controllers connected to same port: one for
> > > device and one for host role. D+/- are switched between phys
> > > by GPIO.
> > 
> > Would you explain how it works? Choosing controller runtime?
> 
> Both controllers are (indirectly) connected to the same micro B port.
> The D+/- goes from the port to a switch operated by a GPIO. From the
> switch, D+/- may go to Host controller's phy or Device controller's phy.
> Depends on the GPIO level.
> 

Get it, why the design like that? If your controller supports both
roles, the software can do role switch by ID pin (through gpio in your
case).

> > 
> > > 
> > > As per initial version, this driver has the duty to control whether
> > > USB-Host cable is plugged in or not:
> > 
> > You mean Micro-AB cable, right?
> 
> > > +
> > > + vup->gpio_usb_mux = devm_gpiod_get_index(dev, "usb mux",
> > > +  VUPORT_GPIO_USB_MUX);
> > > + if (IS_ERR(vup->gpio_usb_mux))
> > > + dev_info(dev, "cannot request USB USB MUX, skipping it.\n");
> > 
> > Using dev_err
> 
> That's not really an error, although the IS_ERR() suggests otherwise.
> The driver works well if a board doesn't need this mux (I'll add a
> comment to state that clear). IMHO either keep dev_info or use dev_dgb
> instead?
> 

If that, dev_dbg may be suitable.


-- 

Best Regards,
Peter Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] bfin_can: rewrite the blackfin CAN driver into arch independent style

2014-12-23 Thread Aaron Wu
Rewrite the blackfin CAN driver into arch independent style

Signed-off-by: Aaron Wu 
---
 drivers/net/can/bfin_can.c |  145 ++--
 1 file changed, 72 insertions(+), 73 deletions(-)

diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index 417d5099..34c6607 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -78,8 +78,8 @@ static int bfin_can_set_bittiming(struct net_device *dev)
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
 
-   bfin_write(>clock, clk);
-   bfin_write(>timing, timing);
+   writew(clk, >clock);
+   writew(timing, >timing);
 
netdev_info(dev, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing);
 
@@ -94,16 +94,14 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
int i;
 
/* disable interrupts */
-   bfin_write(>mbim1, 0);
-   bfin_write(>mbim2, 0);
-   bfin_write(>gim, 0);
+   writew(0, >mbim1);
+   writew(0, >mbim2);
+   writew(0, >gim);
 
/* reset can and enter configuration mode */
-   bfin_write(>control, SRS | CCR);
-   SSYNC();
-   bfin_write(>control, CCR);
-   SSYNC();
-   while (!(bfin_read(>control) & CCA)) {
+   writew(SRS | CCR, >control);
+   writew(CCR, >control);
+   while (!(readw(>control) & CCA)) {
udelay(10);
if (--timeout == 0) {
netdev_err(dev, "fail to enter configuration mode\n");
@@ -116,34 +114,33 @@ static void bfin_can_set_reset_mode(struct net_device 
*dev)
 * by writing to CAN Mailbox Configuration Registers 1 and 2
 * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
 */
-   bfin_write(>mc1, 0);
-   bfin_write(>mc2, 0);
+   writew(0, >mc1);
+   writew(0, >mc2);
 
/* Set Mailbox Direction */
-   bfin_write(>md1, 0x);   /* mailbox 1-16 are RX */
-   bfin_write(>md2, 0);   /* mailbox 17-32 are TX */
+   writew(0x, >md1);   /* mailbox 1-16 are RX */
+   writew(0, >md2);   /* mailbox 17-32 are TX */
 
/* RECEIVE_STD_CHL */
for (i = 0; i < 2; i++) {
-   bfin_write(>chl[RECEIVE_STD_CHL + i].id0, 0);
-   bfin_write(>chl[RECEIVE_STD_CHL + i].id1, AME);
-   bfin_write(>chl[RECEIVE_STD_CHL + i].dlc, 0);
-   bfin_write(>msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
-   bfin_write(>msk[RECEIVE_STD_CHL + i].aml, 0x);
+   writew(0, >chl[RECEIVE_STD_CHL + i].id0);
+   writew(AME, >chl[RECEIVE_STD_CHL + i].id1);
+   writew(0, >chl[RECEIVE_STD_CHL + i].dlc);
+   writew(0x1FFF, >msk[RECEIVE_STD_CHL + i].amh);
+   writew(0x, >msk[RECEIVE_STD_CHL + i].aml);
}
 
/* RECEIVE_EXT_CHL */
for (i = 0; i < 2; i++) {
-   bfin_write(>chl[RECEIVE_EXT_CHL + i].id0, 0);
-   bfin_write(>chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
-   bfin_write(>chl[RECEIVE_EXT_CHL + i].dlc, 0);
-   bfin_write(>msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
-   bfin_write(>msk[RECEIVE_EXT_CHL + i].aml, 0x);
+   writew(0, >chl[RECEIVE_EXT_CHL + i].id0);
+   writew(AME | IDE, >chl[RECEIVE_EXT_CHL + i].id1);
+   writew(0, >chl[RECEIVE_EXT_CHL + i].dlc);
+   writew(0x1FFF, >msk[RECEIVE_EXT_CHL + i].amh);
+   writew(0x, >msk[RECEIVE_EXT_CHL + i].aml);
}
 
-   bfin_write(>mc2, BIT(TRANSMIT_CHL - 16));
-   bfin_write(>mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
-   SSYNC();
+   writew(BIT(TRANSMIT_CHL - 16), >mc2);
+   writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), >mc1);
 
priv->can.state = CAN_STATE_STOPPED;
 }
@@ -157,9 +154,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
 * leave configuration mode
 */
-   bfin_write(>control, bfin_read(>control) & ~CCR);
+   writew(readw(>control) & ~CCR, >control);
 
-   while (bfin_read(>status) & CCA) {
+   while (readw(>status) & CCA) {
udelay(10);
if (--timeout == 0) {
netdev_err(dev, "fail to leave configuration mode\n");
@@ -170,26 +167,25 @@ static void bfin_can_set_normal_mode(struct net_device 
*dev)
/*
 * clear _All_  tx and rx interrupts
 */
-   bfin_write(>mbtif1, 0x);
-   bfin_write(>mbtif2, 0x);
-   bfin_write(>mbrif1, 0x);
-   bfin_write(>mbrif2, 0x);
+   writew(0x, >mbtif1);
+   writew(0x, >mbtif2);
+   writew(0x, >mbrif1);
+   writew(0x, >mbrif2);
 
/*
 * clear global interrupt status register
 */
-   bfin_write(>gis, 0x7FF); /* overwrites with '1' */
+   writew(0x7FF, >gis); /* overwrites with '1' */
 
/*
 * Initialize 

[PATCH 2/2] staging: speakup: Combine the consecutive string

2014-12-23 Thread Panir.Nyan
Combine the consecutive string

Signed-off-by: Panir Nyan 
---
 drivers/staging/speakup/kobjects.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/speakup/kobjects.c 
b/drivers/staging/speakup/kobjects.c
index b12c76d..3708bc1 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -566,7 +566,7 @@ ssize_t spk_var_show(struct kobject *kobj, struct 
kobj_attribute *attr,
if (ch >= ' ' && ch < '~')
*cp1++ = ch;
else
-   cp1 += sprintf(cp1, "\\""x%02x", ch);
+   cp1 += sprintf(cp1, "\\x%02x", ch);
}
*cp1++ = '"';
*cp1++ = '\n';
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] staging: speakup: Split the comment to fit the length

2014-12-23 Thread Panir.Nyan
Split the comment to fit the length.

Signed-off-by: Panir Nyan 
---
 drivers/staging/speakup/synth.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index f3aa423..01eddab 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -30,9 +30,9 @@ struct speakup_info_t speakup_info = {
 * must be taken at each kernel->speakup transition and released at
 * each corresponding speakup->kernel transition.
 *
-* The progression thread only interferes with the speakup machinery 
through
-* the synth buffer, so only needs to take the lock while tinkering with
-* the buffer.
+* The progression thread only interferes with the speakup machinery
+* through the synth buffer, so only needs to take the lock
+* while tinkering with the buffer.
 *
 * We use spin_lock/trylock_irqsave and spin_unlock_irqrestore with this
 * spinlock because speakup needs to disable the keyboard IRQ.
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [v3 06/26] iommu, x86: No need to migrating irq for VT-d Posted-Interrupts

2014-12-23 Thread Zhang, Yang Z
Wu, Feng wrote on 2014-12-24:
> 
> 
> Zhang, Yang Z wrote on 2014-12-24:
>> Cc: io...@lists.linux-foundation.org; linux-kernel@vger.kernel.org;
>> KVM list; Eric Auger
>> Subject: RE: [v3 06/26] iommu, x86: No need to migrating irq for
>> VT-d Posted-Interrupts
>> 
>> Jiang Liu wrote on 2014-12-24:
>>> On 2014/12/24 9:38, Zhang, Yang Z wrote:
 Paolo Bonzini wrote on 2014-12-23:
> 
> 
> On 23/12/2014 10:07, Wu, Feng wrote:
>>> On 23/12/2014 01:37, Zhang, Yang Z wrote:
 I don't quite understand it. If user set an interrupt's affinity
 to a CPU, but he still see the interrupt delivers to other CPUs
 in host. Do you think it is a right behavior?
>>> 
>>> No, the interrupt is not delivered at all in the host. Normally
>>> you'd have:
>>> 
>>> - interrupt delivered to CPU from host affinity
>>> 
>>> - VFIO interrupt handler writes to irqfd
>>> 
>>> - interrupt delivered to vCPU from guest affinity
>>> 
>>> Here, you just skip the first two steps.  The interrupt is
>>> delivered to the thread that is running the vCPU directly, so
>>> the host affinity is bypassed entirely.
>>> 
>>> ... unless you are considering the case where the vCPU is
>>> blocked and the host is processing the posted interrupt wakeup vector.
>>> In that case yes, it would be better to set NDST to a CPU
>>> matching the host
>>> affinity.
>> 
>> In my understanding, wakeup vector should have no relationship
>> with the host affinity of the irq. Wakeup notification event
>> should be delivered to the pCPU which the vCPU was blocked on.
>> And in kernel's point of view, the irq is not associated with
>> the wakeup vector,
>> right?
> 
> That is correct indeed.  It is not associated to the wakeup
> vector, hence this patch is right, I think.
> 
> However, the wakeup vector has the same function as the VFIO
> interrupt handler, so you could argue that it is tied to the
> host affinity rather than the guest.  Let's wait for Yang to answer.
 
 Actually, that's my original question too. I am wondering what
 happens if the
>>> user changes the assigned device's affinity in host's /proc/irq/? If
>>> ignore it is acceptable, then this patch is ok. But it seems the
>>> discussion out of my scope, need some experts to tell us their idea
>>> since it will impact the user experience. Hi Yang,
>> 
>> Hi Jiang,
>> 
>>> Originally we have a proposal to return failure when user sets
>>> IRQ affinity through native OS interfaces if an IRQ is in PI mode.
>>> But that proposal will break CPU hot-removal because OS needs to
>>> migrate away all IRQs binding to the CPU to be offlined. Then we
>>> propose saving user IRQ affinity setting without changing hardware
>>> configuration (keeping PI configuration). Later when PI mode is
>>> disabled, the cached affinity setting will be used to setup IRQ
>>> destination for native OS. On the other hand, for IRQ in PI mode,
>>> it won't be delivered to native OS, so user may not sense that the
>>> IRQ is
>> delivered to CPUs other than those in the affinity set.
>> 
>> The IRQ is still there but will be delivered to host in the form of
>> PI event(if the VCPU is running in root-mode). I am not sure whether
>> those interrupts should be reflected in /proc/interrupts? If the
>> answer is yes, then which entries should be used, a new PI entry or
>> use the
> original IRQ entry?
> 
> Even though, setting the affinity of the IRQ in host should not affect
> the destination of the PI event (normal notification event of wakeup

This is your implementation. To me, disable PI if the VCPU is going to 
run in the CPU out of IRQ affinity bitmap also is acceptable. And it will 
keep the user interface looks the same as before. 

Hi Thomas, Ingo, Peter

Can you guys help to review this patch? Really appreciate if you can give
some feedbacks.

> notification event), because the destination of the PI event is
> determined in NDST field of Posted-interrupts descriptor and PI
> notification vector is global. Just had a discussion with Jiang
> offline, maybe we can add the statistics information for the notification 
> vector in /proc/interrupts just like any other global interrupts.
> 
> Thanks,
> Feng
> 
>> 
>>> In that aspect, I think it's acceptable:) Regards!
>> 
>> Yes, if all of you guys(especially the IRQ maintainer) are think it
>> is acceptable then we can follow current implementation and document it.
>> 
>>> Gerry
 
> 
> Paolo
 
 
 Best regards,
 Yang
 
 
>> 
>> 
>> Best regards,
>> Yang
>>


Best regards,
Yang


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 0/7] ARM: hisi: enable HiP01 SoC

2014-12-23 Thread Wei Xu


On 2014/12/24 11:09, Wang Long wrote:
> Hi, Xu Wei
> 
> This series patch enable Hisilicon HiP01 SoC. The HiP01 SoC series
> chip is designed for networking product, it integrates a rich peripheral
> interfaces to support network applications and supports both one 
> core or dual cores and quad cores. The core is Cortex A9. 

Hi Wang Long,

> This series patch rebased on Linux 3.19-rc1.

Thanks!
I will pick up these patch set and sent a pull request to a...@kernel.org.

Best Regards,
Wei

> Best Regards
> 
> Wang Long (7):
>   ARM: debug: add HiP01 debug uart
>   ARM: hisi: enable HiP01 SoC
>   ARM: dts: Add hip01-ca9x2 dts file
>   ARM: config: enable ARCH_HIP01
>   ARM: hisi: add a common smp_prepares_cpus function
>   ARM: hisi: rename secondary_startup function
>   ARM: hisi: enable smp for HiP01
> 
>  .../bindings/arm/hisilicon/hisilicon.txt   |  25 +
>  arch/arm/Kconfig.debug |  10 ++
>  arch/arm/boot/dts/Makefile |   1 +
>  arch/arm/boot/dts/hip01-ca9x2.dts  |  51 ++
>  arch/arm/boot/dts/hip01.dtsi   | 110 
> +
>  arch/arm/configs/hisi_defconfig|   1 +
>  arch/arm/configs/multi_v7_defconfig|   1 +
>  arch/arm/mach-hisi/Kconfig |   8 ++
>  arch/arm/mach-hisi/core.h  |   5 +-
>  arch/arm/mach-hisi/headsmp.S   |   2 +-
>  arch/arm/mach-hisi/hisilicon.c |  10 ++
>  arch/arm/mach-hisi/hotplug.c   |  31 ++
>  arch/arm/mach-hisi/platsmp.c   |  56 ++-
>  13 files changed, 306 insertions(+), 5 deletions(-)
>  create mode 100644 arch/arm/boot/dts/hip01-ca9x2.dts
>  create mode 100644 arch/arm/boot/dts/hip01.dtsi
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[git pull] drm fixes

2014-12-23 Thread Dave Airlie


Hi Linus,

Xmas fixes pull:

core: one atomic fix, revert the WARN_ON dumb buffers patch.
agp: fixup Dave J.
nouveau: fix 3.18 regression for old userspace
tegra fixes: vblank and iommu fixes
amdkfd: fix bugs shown by testing with userspace, init apertures once
msm:  hdmi fixes and cleanup
i915: misc fixes

There is also a link ordering fix that I've asked to be cc'ed to you,
putting iommu before gpu, it fixes an issue with amdkfd when things are 
all in the kernel, but I didn't like sending it via my tree without 
discussion.

I'll probably be a bit on/off for a few weeks with pulls now, due to
holidays and LCA, so don't be surprised if stuff gets a bit backed up,
and things end up a bit large due to lag.

Dave.

The following changes since commit 97bf6af1f928216fd6c5a66e8a57bfa95a659672:

  Linux 3.19-rc1 (2014-12-20 17:08:50 -0800)

are available in the git repository at:

  git://people.freedesktop.org/~airlied/linux drm-fixes

for you to fetch changes up to da6b51d007da17fd394405055e2f0109ec5f05f4:

  Revert "drm/gem: Warn on illegal use of the dumb buffer interface v2" 
(2014-12-24 13:13:22 +1000)


Alexey Skidanov (1):
  amdkfd: init aperture once per process

Chris Wilson (3):
  drm/i915: Invalidate media caches on gen7
  drm/i915: Force the CS stall for invalidate flushes
  drm/i915: Disable PSMI sleep messages on all rings around context switches

Dave Airlie (7):
  nouveau: bring back legacy mmap handler
  Merge branch 'msm-fixes-3.19' of 
git://people.freedesktop.org/~robclark/linux into drm-fixes
  Merge tag 'topic/atomic-fixes-2014-12-17' of 
git://anongit.freedesktop.org/drm-intel into drm-fixes
  Merge tag 'drm-intel-next-fixes-2014-12-17' of 
git://anongit.freedesktop.org/drm-intel into drm-fixes
  Merge tag 'drm/tegra/for-3.19-rc1-fixes' of 
git://people.freedesktop.org/~tagr/linux into drm-fixes
  Merge tag 'amdkfd-fixes-2014-12-23' of 
git://people.freedesktop.org/~gabbayo/linux into drm-fixes
  Revert "drm/gem: Warn on illegal use of the dumb buffer interface v2"

Dave Jones (1):
  agp: Fix up email address & attributions in AGP MODULE_AUTHOR tags

Imre Deak (3):
  drm/i915: vlv: fix IRQ masking when uninstalling interrupts
  drm/i915: move RPS PM_IER enabling to gen6_enable_rps_interrupts
  drm/i915: sanitize RPS resetting during GPU reset

Jilai Wang (2):
  drm/msm/hdmi: enable regulators before clocks to avoid warnings
  drm/msm/hdmi: rework HDMI IRQ handler

Markus Elfring (2):
  drm/msm: Deletion of unnecessary checks before two function calls
  drm/msm: Deletion of unnecessary checks before the function call 
"release_firmware"

Oded Gabbay (3):
  drm/amd: Add get_fw_version to kfd-->kgd interface
  drm/radeon: Add implementation of get_fw_version
  amdkfd: Display MEC fw version in topology node

Rob Clark (3):
  drm/atomic: fix potential null ptr on plane enable
  drm/msm: block incoming update on pending updates
  drm/msm/mdp5: update irqs on crtc<->encoder link change

Sean Paul (1):
  drm/tegra: dc: Select root window for event dispatch

Thierry Reding (7):
  drm/irq: Add drm_crtc_send_vblank_event()
  drm/irq: Add drm_crtc_handle_vblank()
  drm/irq: Add drm_crtc_vblank_count()
  drm/tegra: dc: Consistently use the same pipe
  drm/tegra: dc: Fix a potential race on page-flip completion
  drm/tegra: gem: Flush buffer objects upon allocation
  drm/tegra: gem: Use the proper size for GEM objects

 drivers/char/agp/ali-agp.c  |  2 +-
 drivers/char/agp/amd64-agp.c|  2 +-
 drivers/char/agp/ati-agp.c  |  2 +-
 drivers/char/agp/backend.c  |  2 +-
 drivers/char/agp/intel-agp.c|  2 +-
 drivers/char/agp/intel-gtt.c|  2 +-
 drivers/char/agp/nvidia-agp.c   |  2 +-
 drivers/char/agp/via-agp.c  |  2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c|  4 --
 drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c|  6 +--
 drivers/gpu/drm/amd/amdkfd/kfd_process.c|  9 
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c   |  8 ++-
 drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 15 ++
 drivers/gpu/drm/drm_atomic_helper.c |  2 +-
 drivers/gpu/drm/drm_irq.c   | 60 +
 drivers/gpu/drm/i915/i915_drv.c |  6 ++-
 drivers/gpu/drm/i915/i915_drv.h |  5 +-
 drivers/gpu/drm/i915/i915_gem.c | 28 ++
 drivers/gpu/drm/i915/i915_gem_context.c | 48 ++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c  |  3 --
 drivers/gpu/drm/i915/i915_irq.c | 18 +--
 drivers/gpu/drm/i915/i915_reg.h |  3 ++
 drivers/gpu/drm/i915/intel_pm.c | 28 ++
 

[PATCH 1/7] ARM: debug: add HiP01 debug uart

2014-12-23 Thread Wang Long
Add the support of Hisilicon HiP01 debug uart.
The uart of hip01 is 8250 compatible.

Signed-off-by: Wang Long 
---
 arch/arm/Kconfig.debug | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 5ddd490..e0cf6ce 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -272,6 +272,14 @@ choice
  Say Y here if you want the debug print routines to direct
  their output to the UART on Highbank based devices.
 
+   config DEBUG_HIP01_UART
+   bool "Hisilicon Hip01 Debug UART"
+   depends on ARCH_HIP01
+   select DEBUG_UART_8250
+   help
+ Say Y here if you want kernel low-level debugging support
+ on HIP01 UART.
+
config DEBUG_HIP04_UART
bool "Hisilicon HiP04 Debug UART"
depends on ARCH_HIP04
@@ -1252,6 +1260,7 @@ config DEBUG_UART_PHYS
default 0x1600 if ARCH_INTEGRATOR
default 0x18000300 if DEBUG_BCM_5301X
default 0x1c09 if DEBUG_VEXPRESS_UART0_RS1
+   default 0x20001000 if DEBUG_HIP01_UART
default 0x2006 if DEBUG_RK29_UART0
default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
@@ -1394,6 +1403,7 @@ config DEBUG_UART_VIRT
default 0xfef36000 if DEBUG_HIGHBANK_UART
default 0xfefff700 if ARCH_IOP33X
default 0xff003000 if DEBUG_U300_UART
+   default 0xffd01000 if DEBUG_HIP01_UART
default DEBUG_UART_PHYS if !MMU
depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/7] ARM: hisi: enable HiP01 SoC

2014-12-23 Thread Wang Long
Hi, Xu Wei

This series patch enable Hisilicon HiP01 SoC. The HiP01 SoC series
chip is designed for networking product, it integrates a rich peripheral
interfaces to support network applications and supports both one 
core or dual cores and quad cores. The core is Cortex A9. 

This series patch rebased on Linux 3.19-rc1.

Best Regards

Wang Long (7):
  ARM: debug: add HiP01 debug uart
  ARM: hisi: enable HiP01 SoC
  ARM: dts: Add hip01-ca9x2 dts file
  ARM: config: enable ARCH_HIP01
  ARM: hisi: add a common smp_prepares_cpus function
  ARM: hisi: rename secondary_startup function
  ARM: hisi: enable smp for HiP01

 .../bindings/arm/hisilicon/hisilicon.txt   |  25 +
 arch/arm/Kconfig.debug |  10 ++
 arch/arm/boot/dts/Makefile |   1 +
 arch/arm/boot/dts/hip01-ca9x2.dts  |  51 ++
 arch/arm/boot/dts/hip01.dtsi   | 110 +
 arch/arm/configs/hisi_defconfig|   1 +
 arch/arm/configs/multi_v7_defconfig|   1 +
 arch/arm/mach-hisi/Kconfig |   8 ++
 arch/arm/mach-hisi/core.h  |   5 +-
 arch/arm/mach-hisi/headsmp.S   |   2 +-
 arch/arm/mach-hisi/hisilicon.c |  10 ++
 arch/arm/mach-hisi/hotplug.c   |  31 ++
 arch/arm/mach-hisi/platsmp.c   |  56 ++-
 13 files changed, 306 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/boot/dts/hip01-ca9x2.dts
 create mode 100644 arch/arm/boot/dts/hip01.dtsi

-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] KVM: ioapic: Record edge-triggered interrupts delivery status.

2014-12-23 Thread Wincy Van
This patch fixes the bug discussed in
https://www.mail-archive.com/kvm@vger.kernel.org/msg109813.html

This patch uses a new field named irr_delivered to record the
delivery status of edge-triggered interrupts, and clears the
delivered interrupts in kvm_get_ioapic. So it has the same effect
of commit 0bc830b05c667218d703f2026ec866c49df974fc
("KVM: ioapic: clear IRR for edge-triggered interrupts at delivery")
while avoids the bug of Windows guests.

Signed-off-by: Wincy Van 
---
 arch/x86/kvm/ioapic.c |7 ++-
 arch/x86/kvm/ioapic.h |1 +
 2 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
index b1947e0..a2e9d96 100644
--- a/arch/x86/kvm/ioapic.c
+++ b/arch/x86/kvm/ioapic.c
@@ -206,6 +206,8 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, 
unsigned int irq,
 
old_irr = ioapic->irr;
ioapic->irr |= mask;
+   if (edge)
+   ioapic->irr_delivered &= ~mask;
if ((edge && old_irr == ioapic->irr) ||
(!edge && entry.fields.remote_irr)) {
ret = 0;
@@ -349,7 +351,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int 
irq, bool line_status)
irqe.shorthand = 0;
 
if (irqe.trig_mode == IOAPIC_EDGE_TRIG)
-   ioapic->irr &= ~(1 << irq);
+   ioapic->irr_delivered |= 1 << irq;
 
if (irq == RTC_GSI && line_status) {
/*
@@ -597,6 +599,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS;
ioapic->ioregsel = 0;
ioapic->irr = 0;
+   ioapic->irr_delivered = 0;
ioapic->id = 0;
memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS);
rtc_irq_eoi_tracking_reset(ioapic);
@@ -654,6 +657,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state 
*state)
 
spin_lock(>lock);
memcpy(state, ioapic, sizeof(struct kvm_ioapic_state));
+   state->irr &= ~ioapic->irr_delivered;
spin_unlock(>lock);
return 0;
 }
@@ -667,6 +671,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state 
*state)
spin_lock(>lock);
memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
ioapic->irr = 0;
+   ioapic->irr_delivered = 0;
update_handled_vectors(ioapic);
kvm_vcpu_request_scan_ioapic(kvm);
kvm_ioapic_inject_all(ioapic, state->irr);
diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h
index 3c91955..a5cdfc0 100644
--- a/arch/x86/kvm/ioapic.h
+++ b/arch/x86/kvm/ioapic.h
@@ -77,6 +77,7 @@ struct kvm_ioapic {
struct rtc_status rtc_status;
struct delayed_work eoi_inject;
u32 irq_eoi[IOAPIC_NUM_PINS];
+   u32 irr_delivered;
 };
 
 #ifdef DEBUG
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/7] ARM: config: enable ARCH_HIP01

2014-12-23 Thread Wang Long
Make hip01 share the hisi_defconfig.
And add it into multi_v7_defconfig too.

Signed-off-by: Wang Long 
---
 arch/arm/configs/hisi_defconfig | 1 +
 arch/arm/configs/multi_v7_defconfig | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig
index 1125436..c34da58 100644
--- a/arch/arm/configs/hisi_defconfig
+++ b/arch/arm/configs/hisi_defconfig
@@ -8,6 +8,7 @@ CONFIG_ARCH_HI3xxx=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_HIX5HD2=y
+CONFIG_ARCH_HIP01=y
 CONFIG_ARCH_HIP04=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 2328fe7..23523ed 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -32,6 +32,7 @@ CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_HISI=y
 CONFIG_ARCH_HI3xxx=y
 CONFIG_ARCH_HIX5HD2=y
+CONFIG_ARCH_HIP01=y
 CONFIG_ARCH_HIP04=y
 CONFIG_ARCH_KEYSTONE=y
 CONFIG_ARCH_MESON=y
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/7] ARM: dts: Add hip01-ca9x2 dts file

2014-12-23 Thread Wang Long
Add dts file for Hisilicon hip01 ca9x2 board

Signed-off-by: Wang Long 
---
 .../bindings/arm/hisilicon/hisilicon.txt   |  25 +
 arch/arm/boot/dts/Makefile |   1 +
 arch/arm/boot/dts/hip01-ca9x2.dts  |  50 ++
 arch/arm/boot/dts/hip01.dtsi   | 110 +
 4 files changed, 186 insertions(+)
 create mode 100644 arch/arm/boot/dts/hip01-ca9x2.dts
 create mode 100644 arch/arm/boot/dts/hip01.dtsi

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt 
b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index f717c7b..35b1bd4 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -9,6 +9,10 @@ HiP04 D01 Board
 Required root node properties:
- compatible = "hisilicon,hip04-d01";
 
+HiP01 ca9x2 Board
+Required root node properties:
+   - compatible = "hisilicon,hip01-ca9x2";
+
 
 Hisilicon system controller
 
@@ -37,6 +41,27 @@ Example:
};
 
 ---
+Hisilicon HiP01 system controller
+
+Required properties:
+- compatible : "hisilicon,hip01-sysctrl"
+- reg : Register address and size
+
+The HiP01 system controller is mostly compatible with hisilicon
+system controller,but it has some specific control registers for
+HIP01 SoC family, such as slave core boot, and also some same
+registers located at different offset.
+
+Example:
+
+   /* for hip01-ca9x2 */
+   sysctrl: system-controller@1000 {
+   compatible = "hisilicon,hip01-sysctrl", "hisilicon,sysctrl";
+   reg = <0x1000 0x1000>;
+   reboot-offset = <0x4>;
+   };
+
+---
 Hisilicon CPU controller
 
 Required properties:
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 91bd5bd..70c2fd0 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -105,6 +105,7 @@ dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb
 dtb-$(CONFIG_ARCH_HIX5HD2) += hisi-x5hd2-dkb.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
ecx-2000.dtb
+dtb-$(CONFIG_ARCH_HIP01) += hip01-ca9x2.dtb
 dtb-$(CONFIG_ARCH_HIP04) += hip04-d01.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
integratorcp.dtb
diff --git a/arch/arm/boot/dts/hip01-ca9x2.dts 
b/arch/arm/boot/dts/hip01-ca9x2.dts
new file mode 100644
index 000..3f157ae
--- /dev/null
+++ b/arch/arm/boot/dts/hip01-ca9x2.dts
@@ -0,0 +1,50 @@
+/*
+ * Hisilicon Ltd. HiP01 SoC
+ *
+ * Copyright (C) 2014 Hisilicon Ltd.
+ * Copyright (C) 2014 Huawei Ltd.
+ *
+ * Author: Wang Long 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+/* First 8KB reserved for secondary core boot */
+/memreserve/ 0x8000 0x2000;
+
+#include "hip01.dtsi"
+
+/ {
+   model = "Hisilicon HIP01 Development Board";
+   compatible = "hisilicon,hip01-ca9x2", "hisilicon,hip01";
+
+   cpus {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   cpu@0 {
+   device_type = "cpu";
+   compatible = "arm,cortex-a9";
+   reg = <0>;
+   };
+
+   cpu@1 {
+   device_type = "cpu";
+   compatible = "arm,cortex-a9";
+   reg = <1>;
+   };
+   };
+
+   memory {
+   device_type = "memory";
+   reg = <0x8000 0x8000>;
+   };
+};
+
+ {
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/hip01.dtsi b/arch/arm/boot/dts/hip01.dtsi
new file mode 100644
index 000..33130f8
--- /dev/null
+++ b/arch/arm/boot/dts/hip01.dtsi
@@ -0,0 +1,110 @@
+/*
+ * Hisilicon Ltd. HiP01 SoC
+ *
+ * Copyright (c) 2014 Hisilicon Ltd.
+ * Copyright (c) 2014 Huawei Ltd.
+ *
+ * Author: Wang Long 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+   interrupt-parent = <>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   gic: interrupt-controller@1e001000 {
+   compatible = "arm,cortex-a9-gic";
+   #interrupt-cells = <3>;
+   #address-cells = <0>;
+   interrupt-controller;
+   reg = <0x1a001000 0x1000>, <0x1a000100 0x1000>;
+   };
+
+   hisi_refclk144mhz: refclk144mkhz {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <14400>;
+   clock-output-names = "hisi:refclk144khz";
+  

[PATCH 7/7] ARM: hisi: enable smp for HiP01

2014-12-23 Thread Wang Long
enable smp for HiP01 board.

Signed-off-by: Wang Long 
---
 arch/arm/boot/dts/hip01-ca9x2.dts |  1 +
 arch/arm/mach-hisi/core.h |  3 +++
 arch/arm/mach-hisi/hotplug.c  | 31 
 arch/arm/mach-hisi/platsmp.c  | 50 +++
 4 files changed, 85 insertions(+)

diff --git a/arch/arm/boot/dts/hip01-ca9x2.dts 
b/arch/arm/boot/dts/hip01-ca9x2.dts
index 3f157ae..eca5e42 100644
--- a/arch/arm/boot/dts/hip01-ca9x2.dts
+++ b/arch/arm/boot/dts/hip01-ca9x2.dts
@@ -25,6 +25,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+   enable-method = "hisilicon,hip01-smp";
 
cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h
index 75520b0..92a682d 100644
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -17,4 +17,7 @@ extern struct smp_operations hix5hd2_smp_ops;
 extern void hix5hd2_set_cpu(int cpu, bool enable);
 extern void hix5hd2_cpu_die(unsigned int cpu);
 
+extern struct smp_operations hip01_smp_ops;
+extern void hip01_set_cpu(int cpu, bool enable);
+extern void hip01_cpu_die(unsigned int cpu);
 #endif
diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c
index 84e6919..a129aae 100644
--- a/arch/arm/mach-hisi/hotplug.c
+++ b/arch/arm/mach-hisi/hotplug.c
@@ -65,6 +65,9 @@
 #define PMC0_CPU1_PMC_ENABLE   (1 << 7)
 #define PMC0_CPU1_POWERDOWN(1 << 3)
 
+#define HIP01_PERI90x50
+#define PERI9_CPU1_RESET   (1 << 1)
+
 enum {
HI3620_CTRL,
ERROR_CTRL,
@@ -209,6 +212,34 @@ void hix5hd2_set_cpu(int cpu, bool enable)
}
 }
 
+void hip01_set_cpu(int cpu, bool enable)
+{
+   unsigned int temp;
+   struct device_node *np;
+
+   if (!ctrl_base) {
+   np = of_find_compatible_node(NULL, NULL, 
"hisilicon,hip01-sysctrl");
+   if (np)
+   ctrl_base = of_iomap(np, 0);
+   else
+   BUG();
+   }
+
+   if (enable) {
+   /* reset on CPU1  */
+   temp = readl_relaxed(ctrl_base + HIP01_PERI9);
+   temp |= PERI9_CPU1_RESET;
+   writel_relaxed(temp, ctrl_base + HIP01_PERI9);
+
+   udelay(50);
+
+   /* unreset on CPU1 */
+   temp = readl_relaxed(ctrl_base + HIP01_PERI9);
+   temp &= ~PERI9_CPU1_RESET;
+   writel_relaxed(temp, ctrl_base + HIP01_PERI9);
+   }
+}
+
 static inline void cpu_enter_lowpower(void)
 {
unsigned int v;
diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c
index 4a70f56..8880c8e 100644
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -10,10 +10,12 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 #include 
+#include 
 
 #include "core.h"
 
@@ -132,5 +134,53 @@ struct smp_operations hix5hd2_smp_ops __initdata = {
 #endif
 };
 
+
+#define SC_SCTL_REMAP_CLR  0x0100
+#define HIP01_BOOT_ADDRESS 0x8000
+#define REG_SC_CTRL0x000
+
+void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
+{
+   void __iomem *virt;
+
+   virt = phys_to_virt(start_addr);
+
+   writel_relaxed(0xe51ff004, virt);
+   writel_relaxed(jump_addr, virt + 4);
+}
+
+static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+   phys_addr_t jumpaddr;
+   unsigned int remap_reg_value = 0;
+   struct device_node *node;
+
+
+   jumpaddr = virt_to_phys(hisi_secondary_startup);
+   hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr);
+
+   node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
+   if (WARN_ON(!node))
+   return -1;
+   ctrl_base = of_iomap(node, 0);
+
+   /* set the secondary core boot from DDR */
+   remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
+   barrier();
+   remap_reg_value |= SC_SCTL_REMAP_CLR;
+   barrier();
+   writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL);
+
+   hip01_set_cpu(cpu, true);
+
+   return 0;
+}
+
+struct smp_operations hip01_smp_ops __initdata = {
+   .smp_prepare_cpus   = hisi_common_smp_prepare_cpus,
+   .smp_boot_secondary = hip01_boot_secondary,
+};
+
 CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", _smp_ops);
 CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", _smp_ops);
+CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", _smp_ops);
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/7] ARM: hisi: enable HiP01 SoC

2014-12-23 Thread Wang Long
Enable Hisilicon HiP01 SoC. This HiP01 SoC series support both
one core or dual cores and quad cores. The core is Cortex A9.

Signed-off-by: Wang Long 
---
 arch/arm/mach-hisi/Kconfig |  8 
 arch/arm/mach-hisi/hisilicon.c | 10 ++
 2 files changed, 18 insertions(+)

diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index cd19433..83061ad 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -22,6 +22,14 @@ config ARCH_HI3xxx
help
  Support for Hisilicon Hi36xx SoC family
 
+config ARCH_HIP01
+   bool "Hisilicon HIP01 family" if ARCH_MULTI_V7
+   select HAVE_ARM_SCU if SMP
+   select HAVE_ARM_TWD if SMP
+   select ARM_GLOBAL_TIMER
+   help
+ Support for Hisilicon HIP01 SoC family
+
 config ARCH_HIP04
bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7
select ARM_ERRATA_798181 if SMP
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index 7744c35..76b9070 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -72,3 +72,13 @@ static const char *hip04_compat[] __initconst = {
 DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)")
.dt_compat  = hip04_compat,
 MACHINE_END
+
+static const char *hip01_compat[] __initconst = {
+   "hisilicon,hip01",
+   "hisilicon,hip01-ca9x2",
+   NULL,
+};
+
+DT_MACHINE_START(HIP01, "Hisilicon HIP01 (Flattened Device Tree)")
+   .dt_compat  = hip01_compat,
+MACHINE_END
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 5/7] ARM: hisi: add a common smp_prepares_cpus function

2014-12-23 Thread Wang Long
As hix5hd2 and hip01 has the same .smp_prepare_cpus
in struct smp_operations, so rename hix5hd2_smp_prepare_cpus
to hisi_common_smp_prepare_cpus.

the hip01 will use hisi_common_smp_prepare_cpus in its
struct smp_operations.

Signed-off-by: Wang Long 
---
 arch/arm/mach-hisi/platsmp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c
index 575dd82..b3c3a58 100644
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -96,7 +96,7 @@ struct smp_operations hi3xxx_smp_ops __initdata = {
 #endif
 };
 
-static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus)
+static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus)
 {
hisi_enable_scu_a9();
 }
@@ -125,7 +125,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct 
task_struct *idle)
 
 
 struct smp_operations hix5hd2_smp_ops __initdata = {
-   .smp_prepare_cpus   = hix5hd2_smp_prepare_cpus,
+   .smp_prepare_cpus   = hisi_common_smp_prepare_cpus,
.smp_boot_secondary = hix5hd2_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
.cpu_die= hix5hd2_cpu_die,
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 6/7] ARM: hisi: rename secondary_startup function

2014-12-23 Thread Wang Long
As hix5hd2 and hip01 has the same secondary_startup
so rename hix5hd2_secondary_startup to
to hisi_secondary_startup.

the hip01 will use hisi_secondary_startup for the
secondary core boot.

Signed-off-by: Wang Long 
---
 arch/arm/mach-hisi/core.h| 2 +-
 arch/arm/mach-hisi/headsmp.S | 2 +-
 arch/arm/mach-hisi/platsmp.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h
index 88b1f48..75520b0 100644
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -12,7 +12,7 @@ extern void hi3xxx_cpu_die(unsigned int cpu);
 extern int hi3xxx_cpu_kill(unsigned int cpu);
 extern void hi3xxx_set_cpu(int cpu, bool enable);
 
-extern void hix5hd2_secondary_startup(void);
+extern void hisi_secondary_startup(void);
 extern struct smp_operations hix5hd2_smp_ops;
 extern void hix5hd2_set_cpu(int cpu, bool enable);
 extern void hix5hd2_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-hisi/headsmp.S b/arch/arm/mach-hisi/headsmp.S
index 278889c..81e35b1 100644
--- a/arch/arm/mach-hisi/headsmp.S
+++ b/arch/arm/mach-hisi/headsmp.S
@@ -11,6 +11,6 @@
 
__CPUINIT
 
-ENTRY(hix5hd2_secondary_startup)
+ENTRY(hisi_secondary_startup)
bl  v7_invalidate_l1
b   secondary_startup
diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c
index b3c3a58..4a70f56 100644
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -116,7 +116,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct 
task_struct *idle)
 {
phys_addr_t jumpaddr;
 
-   jumpaddr = virt_to_phys(hix5hd2_secondary_startup);
+   jumpaddr = virt_to_phys(hisi_secondary_startup);
hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
hix5hd2_set_cpu(cpu, true);
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [v3 06/26] iommu, x86: No need to migrating irq for VT-d Posted-Interrupts

2014-12-23 Thread Wu, Feng


> -Original Message-
> From: Zhang, Yang Z
> Sent: Wednesday, December 24, 2014 10:33 AM
> To: Jiang Liu; Paolo Bonzini; Wu, Feng; Thomas Gleixner; Ingo Molnar; H. Peter
> Anvin; x...@kernel.org; Gleb Natapov; dw...@infradead.org;
> j...@8bytes.org; Alex Williamson
> Cc: io...@lists.linux-foundation.org; linux-kernel@vger.kernel.org; KVM list;
> Eric Auger
> Subject: RE: [v3 06/26] iommu, x86: No need to migrating irq for VT-d
> Posted-Interrupts
> 
> Jiang Liu wrote on 2014-12-24:
> > On 2014/12/24 9:38, Zhang, Yang Z wrote:
> >> Paolo Bonzini wrote on 2014-12-23:
> >>>
> >>>
> >>> On 23/12/2014 10:07, Wu, Feng wrote:
> > On 23/12/2014 01:37, Zhang, Yang Z wrote:
> >> I don't quite understand it. If user set an interrupt's affinity
> >> to a CPU, but he still see the interrupt delivers to other CPUs in 
> >> host.
> >> Do you think it is a right behavior?
> >
> > No, the interrupt is not delivered at all in the host.  Normally you'd
> have:
> >
> > - interrupt delivered to CPU from host affinity
> >
> > - VFIO interrupt handler writes to irqfd
> >
> > - interrupt delivered to vCPU from guest affinity
> >
> > Here, you just skip the first two steps.  The interrupt is
> > delivered to the thread that is running the vCPU directly, so the
> > host affinity is bypassed entirely.
> >
> > ... unless you are considering the case where the vCPU is blocked
> > and the host is processing the posted interrupt wakeup vector.
> > In that case yes, it would be better to set NDST to a CPU
> > matching the host
> > affinity.
> 
>  In my understanding, wakeup vector should have no relationship
>  with the host affinity of the irq. Wakeup notification event
>  should be delivered to the pCPU which the vCPU was blocked on. And
>  in kernel's point of view, the irq is not associated with the wakeup 
>  vector,
> right?
> >>>
> >>> That is correct indeed.  It is not associated to the wakeup vector,
> >>> hence this patch is right, I think.
> >>>
> >>> However, the wakeup vector has the same function as the VFIO
> >>> interrupt handler, so you could argue that it is tied to the host
> >>> affinity rather than the guest.  Let's wait for Yang to answer.
> >>
> >> Actually, that's my original question too. I am wondering what
> >> happens if the
> > user changes the assigned device's affinity in host's /proc/irq/? If
> > ignore it is acceptable, then this patch is ok. But it seems the
> > discussion out of my scope, need some experts to tell us their idea since 
> > it will
> impact the user experience.
> > Hi Yang,
> 
> Hi Jiang,
> 
> > Originally we have a proposal to return failure when user sets IRQ
> > affinity through native OS interfaces if an IRQ is in PI mode. But
> > that proposal will break CPU hot-removal because OS needs to migrate
> > away all IRQs binding to the CPU to be offlined. Then we propose
> > saving user IRQ affinity setting without changing hardware
> > configuration (keeping PI configuration). Later when PI mode is
> > disabled, the cached affinity setting will be used to setup IRQ
> > destination for native OS. On the other hand, for IRQ in PI mode, it
> > won't be delivered to native OS, so user may not sense that the IRQ is
> delivered to CPUs other than those in the affinity set.
> 
> The IRQ is still there but will be delivered to host in the form of PI 
> event(if the
> VCPU is running in root-mode). I am not sure whether those interrupts should
> be reflected in /proc/interrupts? If the answer is yes, then which entries 
> should
> be used, a new PI entry or use the original IRQ entry?

Even though, setting the affinity of the IRQ in host should not affect the 
destination of the
PI event (normal notification event of wakeup notification event), because the 
destination
of the PI event is determined in NDST field of Posted-interrupts descriptor and 
PI notification
vector is global. Just had a discussion with Jiang offline, maybe we can add 
the statistics
information for the notification vector in /proc/interrupts just like any other 
global
interrupts.

Thanks,
Feng

> 
> > In that aspect, I think it's acceptable:) Regards!
> 
> Yes, if all of you guys(especially the IRQ maintainer) are think it is 
> acceptable
> then we can follow current implementation and document it.
> 
> > Gerry
> >>
> >>>
> >>> Paolo
> >>
> >>
> >> Best regards,
> >> Yang
> >>
> >>
> 
> 
> Best regards,
> Yang
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH net-next V2] virtio-net: don't do header check for dodgy gso packets

2014-12-23 Thread Jason Wang
There's no need to do header check for virtio-net since:

- Host sets dodgy for all gso packets from guest and check the header.
- Host should be prepared for all kinds of evil packets from guest, since
  malicious guest can send any kinds of packet.

So this patch sets NETIF_F_GSO_ROBUST for virtio-net to skip the check.

Cc: Rusty Russell 
Cc: Michael S. Tsirkin 
Acked-by: Michael S. Tsirkin 
Signed-off-by: Jason Wang 
---
Changes from V1:
- typo fixes
---
 drivers/net/virtio_net.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index b8bd719..45c6ce2 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1761,6 +1761,8 @@ static int virtnet_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
dev->hw_features |= NETIF_F_TSO_ECN;
 
+   dev->features |= NETIF_F_GSO_ROBUST;
+
if (gso)
dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
/* (!csum && gso) case will be fixed by register_netdev() */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: frequent lockups in 3.18rc4

2014-12-23 Thread Dave Jones
On Mon, Dec 22, 2014 at 03:59:19PM -0800, Linus Torvalds wrote:
 
 > But in the meantime please do keep that thing running as long as you
 > can. Let's see if we get bigger jumps. Or perhaps we'll get a negative
 > result - the original softlockup bug happening *without* any bigger
 > hpet jumps.

So I've got this box a *little* longer than anticipated.
It's now been running 30 hours with not a single NMI lockup.
and that's with my kitchen-sink debugging kernel.

The 'hpet off' messages continue to be spewed, and again they're
all in the same range of 4293198075 -> 4294967266

Dave
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Nouveau] [PATCH nouveau 08/11] instmem: add dummy support for GK20A

2014-12-23 Thread Vince Hsu

Hi,

On 12/24/2014 12:39 AM, Ilia Mirkin wrote:

On Tue, Dec 23, 2014 at 5:40 AM, Vince Hsu  wrote:

This is a workaround to avoid the instmem backup/restore during the suspend
and resume process in nv50 instemem driver.

Signed-off-by: Vince Hsu 
---
  drm/Kbuild|  1 +
  nvkm/engine/device/nve0.c |  2 +-
  nvkm/include/subdev/instmem.h |  1 +
  nvkm/subdev/instmem/gk20a.c   | 70 +++
  4 files changed, 73 insertions(+), 1 deletion(-)
  create mode 100644 nvkm/subdev/instmem/gk20a.c

diff --git a/drm/Kbuild b/drm/Kbuild
index 6461e3565afe..ea40cd653c7c 100644
--- a/drm/Kbuild
+++ b/drm/Kbuild
@@ -176,6 +176,7 @@ nouveau-y += core/subdev/instmem/base.o
  nouveau-y += core/subdev/instmem/nv04.o
  nouveau-y += core/subdev/instmem/nv40.o
  nouveau-y += core/subdev/instmem/nv50.o
+nouveau-y += core/subdev/instmem/gk20a.o
  nouveau-y += core/subdev/ltc/base.o
  nouveau-y += core/subdev/ltc/gf100.o
  nouveau-y += core/subdev/ltc/gk104.o
diff --git a/nvkm/engine/device/nve0.c b/nvkm/engine/device/nve0.c
index 732922690653..fcbdc5259c7c 100644
--- a/nvkm/engine/device/nve0.c
+++ b/nvkm/engine/device/nve0.c
@@ -170,7 +170,7 @@ nve0_identify(struct nouveau_device *device)
 device->oclass[NVDEV_SUBDEV_FB ] =  gk20a_fb_oclass;
 device->oclass[NVDEV_SUBDEV_LTC] =  gk104_ltc_oclass;
 device->oclass[NVDEV_SUBDEV_IBUS   ] = _ibus_oclass;
-   device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+   device->oclass[NVDEV_SUBDEV_INSTMEM] = gk20a_instmem_oclass;
 device->oclass[NVDEV_SUBDEV_VM ] = _vmmgr_oclass;
 device->oclass[NVDEV_SUBDEV_BAR] = _bar_oclass;
 device->oclass[NVDEV_ENGINE_DMAOBJ ] =  nvd0_dmaeng_oclass;
diff --git a/nvkm/include/subdev/instmem.h b/nvkm/include/subdev/instmem.h
index c1df26f3230c..6264660bedce 100644
--- a/nvkm/include/subdev/instmem.h
+++ b/nvkm/include/subdev/instmem.h
@@ -48,5 +48,6 @@ nouveau_instmem(void *obj)
  extern struct nouveau_oclass *nv04_instmem_oclass;
  extern struct nouveau_oclass *nv40_instmem_oclass;
  extern struct nouveau_oclass *nv50_instmem_oclass;
+extern struct nouveau_oclass *gk20a_instmem_oclass;

  #endif
diff --git a/nvkm/subdev/instmem/gk20a.c b/nvkm/subdev/instmem/gk20a.c
new file mode 100644
index ..5e072d6e743f
--- /dev/null
+++ b/nvkm/subdev/instmem/gk20a.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "nv50.h"

I'm confused... what exactly depends on nv50_instmem_priv here? Why
not just create a gk20a_instmem_priv and leave the nv50 one alone?

You're right. Will fix in the next version.



+#include "priv.h"
+
+static int
+gk20a_instmem_fini(struct nouveau_object *object, bool suspend)
+{
+   struct nouveau_instmem *imem = (void *)object;
+
+   return nouveau_subdev_fini(>base, suspend);
+}
+
+static int
+gk20a_instmem_init(struct nouveau_object *object)
+{
+   struct nouveau_instmem *imem = (void *)object;
+
+   return nouveau_subdev_init(>base);
+}

I think the style is to just link those up directly in the class
definition when they're trivial like that, i.e. point them at
_nouveau_subdev_init and such.

Thanks for the hint. Will fix. :)




+
+static int
+gk20a_instmem_ctor(struct nouveau_object *parent, struct nouveau_object 
*engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+   struct nv50_instmem_priv *priv;
+   int ret;
+
+   ret = nouveau_instmem_create(parent, engine, oclass, );
+   *pobject = nv_object(priv);
+   if (ret)
+   return ret;
+
+   spin_lock_init(>lock);
+   return 0;
+}
+
+struct nouveau_oclass *
+gk20a_instmem_oclass = &(struct nouveau_instmem_impl) 

[PATCH] ARM: EXYNOS: Add exynos3250 suspend-to-ram support

2014-12-23 Thread Chanwoo Choi
This patch adds the support for suspend-to-ram feature of Exynos3250 SoC.
Exynos3250 don't contain the L2 cache.

The measured power-consumption in suspend state:
- before entering suspend : 31mA
- in suspend state : 16mA

Cc: Kukjin Kim 
Signed-off-by: Chanwoo Choi 
Acked-by: Kyungmin Park 
---
This patch is based on v3.19-rc1 and is tested on Exynos3250-based Rinato board.

 arch/arm/mach-exynos/regs-pmu.h |  3 ++
 arch/arm/mach-exynos/suspend.c  | 77 +
 2 files changed, 80 insertions(+)

diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index b5f4406..eb461e1 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -160,12 +160,14 @@
 #define EXYNOS5_L2RSTDISABLE_VALUE BIT(3)
 
 #define S5P_PAD_RET_MAUDIO_OPTION  0x3028
+#define S5P_PAD_RET_MMC2_OPTION0x30c8
 #define S5P_PAD_RET_GPIO_OPTION0x3108
 #define S5P_PAD_RET_UART_OPTION0x3128
 #define S5P_PAD_RET_MMCA_OPTION0x3148
 #define S5P_PAD_RET_MMCB_OPTION0x3168
 #define S5P_PAD_RET_EBIA_OPTION0x3188
 #define S5P_PAD_RET_EBIB_OPTION0x31A8
+#define S5P_PAD_RET_SPI_OPTION 0x31c8
 
 #define S5P_PS_HOLD_CONTROL0x330C
 #define S5P_PS_HOLD_EN (1 << 31)
@@ -326,6 +328,7 @@
(EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80))
 
 #define EXYNOS3_ARM_COMMON_OPTION  0x2408
+#define EXYNOS3_ARM_L2_OPTION  0x2608
 #define EXYNOS3_TOP_PWR_OPTION 0x2C48
 #define EXYNOS3_CORE_TOP_PWR_OPTION0x2CA8
 #define EXYNOS3_XUSBXTI_DURATION   0x341C
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index f8e7dcd..d6feef3 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -91,6 +91,12 @@ static unsigned int exynos_pmu_spare3;
 
 static u32 exynos_irqwake_intmask = 0x;
 
+static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
+   { 73, BIT(1) }, /* RTC alarm */
+   { 74, BIT(2) }, /* RTC tick */
+   { /* sentinel */ },
+};
+
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
@@ -114,6 +120,19 @@ unsigned int exynos_release_ret_regs[] = {
REG_TABLE_END,
 };
 
+unsigned int exynos3250_release_ret_regs[] = {
+   S5P_PAD_RET_MAUDIO_OPTION,
+   S5P_PAD_RET_GPIO_OPTION,
+   S5P_PAD_RET_UART_OPTION,
+   S5P_PAD_RET_MMCA_OPTION,
+   S5P_PAD_RET_MMCB_OPTION,
+   S5P_PAD_RET_EBIA_OPTION,
+   S5P_PAD_RET_EBIB_OPTION,
+   S5P_PAD_RET_MMC2_OPTION,
+   S5P_PAD_RET_SPI_OPTION,
+   REG_TABLE_END,
+};
+
 unsigned int exynos5420_release_ret_regs[] = {
EXYNOS_PAD_RET_DRAM_OPTION,
EXYNOS_PAD_RET_MAUDIO_OPTION,
@@ -173,6 +192,12 @@ static int exynos_cpu_suspend(unsigned long arg)
return exynos_cpu_do_idle();
 }
 
+static int exynos3250_cpu_suspend(unsigned long arg)
+{
+   flush_cache_all();
+   return exynos_cpu_do_idle();
+}
+
 static int exynos5420_cpu_suspend(unsigned long arg)
 {
/* MCPM works with HW CPU identifiers */
@@ -230,6 +255,23 @@ static void exynos_pm_prepare(void)
pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
 }
 
+static void exynos3250_pm_prepare(void)
+{
+   unsigned int tmp;
+
+   /* Set wake-up mask registers */
+   exynos_pm_set_wakeup_mask();
+
+   tmp = pmu_raw_readl(EXYNOS3_ARM_L2_OPTION);
+   tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
+   pmu_raw_writel(tmp, EXYNOS3_ARM_L2_OPTION);
+
+   exynos_pm_enter_sleep_mode();
+
+   /* ensure at least INFORM0 has the resume address */
+   pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
+}
+
 static void exynos5420_pm_prepare(void)
 {
unsigned int tmp;
@@ -344,6 +386,28 @@ early_wakeup:
pmu_raw_writel(0x0, S5P_INFORM1);
 }
 
+static void exynos3250_pm_resume(void)
+{
+   u32 cpuid = read_cpuid_part();
+
+   if (exynos_pm_central_resume())
+   goto early_wakeup;
+
+   /* For release retention */
+   exynos_pm_release_retention();
+
+   pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
+
+   if (call_firmware_op(resume) == -ENOSYS
+   && cpuid == ARM_CPU_PART_CORTEX_A9)
+   exynos_cpu_restore_register();
+
+early_wakeup:
+
+   /* Clear SLEEP mode set in INFORM1 */
+   pmu_raw_writel(0x0, S5P_INFORM1);
+}
+
 static void exynos5420_prepare_pm_resume(void)
 {
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
@@ -483,6 +547,16 @@ static const struct platform_suspend_ops 
exynos_suspend_ops = {
.valid  = suspend_valid_only_mem,
 };
 
+static const 

  1   2   3   4   5   6   7   8   9   10   >