[PATCH v3 11/14] nubus: Rename struct nubus_dev

2017-12-04 Thread Finn Thain
It is misleading to call a functional resource a "device". In adopting
the Linux Driver Model, the struct device will be embedded in struct
nubus_board. That will compound the terminlogy problem because drivers
will bind with boards, not with functional resources. Avoid this by
renaming struct nubus_dev as struct nubus_rsrc. "Functional resource"
is the vendor's terminology so this helps avoid confusion.

Cc: Bartlomiej Zolnierkiewicz 
Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/net/ethernet/8390/mac8390.c |  26 
 drivers/net/ethernet/natsemi/macsonic.c |  22 +++
 drivers/nubus/nubus.c   | 105 
 drivers/nubus/proc.c|  15 ++---
 drivers/video/fbdev/macfb.c |   2 +-
 include/linux/nubus.h   |  30 +
 6 files changed, 98 insertions(+), 102 deletions(-)

diff --git a/drivers/net/ethernet/8390/mac8390.c 
b/drivers/net/ethernet/8390/mac8390.c
index 9497f18eaba0..929ff6419621 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -123,7 +123,8 @@ enum mac8390_access {
 };
 
 extern int mac8390_memtest(struct net_device *dev);
-static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev,
+static int mac8390_initdev(struct net_device *dev,
+  struct nubus_rsrc *ndev,
   enum mac8390_type type);
 
 static int mac8390_open(struct net_device *dev);
@@ -169,11 +170,11 @@ static void word_memcpy_tocard(unsigned long tp, const 
void *fp, int count);
 static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
 static u32 mac8390_msg_enable;
 
-static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
+static enum mac8390_type __init mac8390_ident(struct nubus_rsrc *fres)
 {
-   switch (dev->dr_sw) {
+   switch (fres->dr_sw) {
case NUBUS_DRSW_3COM:
-   switch (dev->dr_hw) {
+   switch (fres->dr_hw) {
case NUBUS_DRHW_APPLE_SONIC_NB:
case NUBUS_DRHW_APPLE_SONIC_LC:
case NUBUS_DRHW_SONNET:
@@ -184,7 +185,7 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
break;
 
case NUBUS_DRSW_APPLE:
-   switch (dev->dr_hw) {
+   switch (fres->dr_hw) {
case NUBUS_DRHW_ASANTE_LC:
return MAC8390_NONE;
case NUBUS_DRHW_CABLETRON:
@@ -201,7 +202,7 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
case NUBUS_DRSW_TECHWORKS:
case NUBUS_DRSW_DAYNA2:
case NUBUS_DRSW_DAYNA_LC:
-   if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+   if (fres->dr_hw == NUBUS_DRHW_CABLETRON)
return MAC8390_CABLETRON;
else
return MAC8390_APPLE;
@@ -212,7 +213,7 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
break;
 
case NUBUS_DRSW_KINETICS:
-   switch (dev->dr_hw) {
+   switch (fres->dr_hw) {
case NUBUS_DRHW_INTERLAN:
return MAC8390_INTERLAN;
default:
@@ -225,8 +226,8 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
 * These correspond to Dayna Sonic cards
 * which use the macsonic driver
 */
-   if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
-   dev->dr_hw == NUBUS_DRHW_INTERLAN)
+   if (fres->dr_hw == NUBUS_DRHW_SMC9194 ||
+   fres->dr_hw == NUBUS_DRHW_INTERLAN)
return MAC8390_NONE;
else
return MAC8390_DAYNA;
@@ -289,7 +290,8 @@ static int __init mac8390_memsize(unsigned long membase)
return i * 0x1000;
 }
 
-static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
+static bool __init mac8390_init(struct net_device *dev,
+   struct nubus_rsrc *ndev,
enum mac8390_type cardtype)
 {
struct nubus_dir dir;
@@ -394,7 +396,7 @@ static bool __init mac8390_init(struct net_device *dev, 
struct nubus_dev *ndev,
 struct net_device * __init mac8390_probe(int unit)
 {
struct net_device *dev;
-   struct nubus_dev *ndev = NULL;
+   struct nubus_rsrc *ndev = NULL;
int err = -ENODEV;
struct ei_device *ei_local;
 
@@ -489,7 +491,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
 };
 
 static int __init mac8390_initdev(struct net_device *dev,
- struct nubus_dev *ndev,
+ struct nubus_rsrc *ndev,
  enum mac8390_type type)
 {
static u32 fwrd4_offsets[16] = {
diff --git 

[PATCH v3 11/14] nubus: Rename struct nubus_dev

2017-12-04 Thread Finn Thain
It is misleading to call a functional resource a "device". In adopting
the Linux Driver Model, the struct device will be embedded in struct
nubus_board. That will compound the terminlogy problem because drivers
will bind with boards, not with functional resources. Avoid this by
renaming struct nubus_dev as struct nubus_rsrc. "Functional resource"
is the vendor's terminology so this helps avoid confusion.

Cc: Bartlomiej Zolnierkiewicz 
Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/net/ethernet/8390/mac8390.c |  26 
 drivers/net/ethernet/natsemi/macsonic.c |  22 +++
 drivers/nubus/nubus.c   | 105 
 drivers/nubus/proc.c|  15 ++---
 drivers/video/fbdev/macfb.c |   2 +-
 include/linux/nubus.h   |  30 +
 6 files changed, 98 insertions(+), 102 deletions(-)

diff --git a/drivers/net/ethernet/8390/mac8390.c 
b/drivers/net/ethernet/8390/mac8390.c
index 9497f18eaba0..929ff6419621 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -123,7 +123,8 @@ enum mac8390_access {
 };
 
 extern int mac8390_memtest(struct net_device *dev);
-static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev,
+static int mac8390_initdev(struct net_device *dev,
+  struct nubus_rsrc *ndev,
   enum mac8390_type type);
 
 static int mac8390_open(struct net_device *dev);
@@ -169,11 +170,11 @@ static void word_memcpy_tocard(unsigned long tp, const 
void *fp, int count);
 static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
 static u32 mac8390_msg_enable;
 
-static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
+static enum mac8390_type __init mac8390_ident(struct nubus_rsrc *fres)
 {
-   switch (dev->dr_sw) {
+   switch (fres->dr_sw) {
case NUBUS_DRSW_3COM:
-   switch (dev->dr_hw) {
+   switch (fres->dr_hw) {
case NUBUS_DRHW_APPLE_SONIC_NB:
case NUBUS_DRHW_APPLE_SONIC_LC:
case NUBUS_DRHW_SONNET:
@@ -184,7 +185,7 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
break;
 
case NUBUS_DRSW_APPLE:
-   switch (dev->dr_hw) {
+   switch (fres->dr_hw) {
case NUBUS_DRHW_ASANTE_LC:
return MAC8390_NONE;
case NUBUS_DRHW_CABLETRON:
@@ -201,7 +202,7 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
case NUBUS_DRSW_TECHWORKS:
case NUBUS_DRSW_DAYNA2:
case NUBUS_DRSW_DAYNA_LC:
-   if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+   if (fres->dr_hw == NUBUS_DRHW_CABLETRON)
return MAC8390_CABLETRON;
else
return MAC8390_APPLE;
@@ -212,7 +213,7 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
break;
 
case NUBUS_DRSW_KINETICS:
-   switch (dev->dr_hw) {
+   switch (fres->dr_hw) {
case NUBUS_DRHW_INTERLAN:
return MAC8390_INTERLAN;
default:
@@ -225,8 +226,8 @@ static enum mac8390_type __init mac8390_ident(struct 
nubus_dev *dev)
 * These correspond to Dayna Sonic cards
 * which use the macsonic driver
 */
-   if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
-   dev->dr_hw == NUBUS_DRHW_INTERLAN)
+   if (fres->dr_hw == NUBUS_DRHW_SMC9194 ||
+   fres->dr_hw == NUBUS_DRHW_INTERLAN)
return MAC8390_NONE;
else
return MAC8390_DAYNA;
@@ -289,7 +290,8 @@ static int __init mac8390_memsize(unsigned long membase)
return i * 0x1000;
 }
 
-static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
+static bool __init mac8390_init(struct net_device *dev,
+   struct nubus_rsrc *ndev,
enum mac8390_type cardtype)
 {
struct nubus_dir dir;
@@ -394,7 +396,7 @@ static bool __init mac8390_init(struct net_device *dev, 
struct nubus_dev *ndev,
 struct net_device * __init mac8390_probe(int unit)
 {
struct net_device *dev;
-   struct nubus_dev *ndev = NULL;
+   struct nubus_rsrc *ndev = NULL;
int err = -ENODEV;
struct ei_device *ei_local;
 
@@ -489,7 +491,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
 };
 
 static int __init mac8390_initdev(struct net_device *dev,
- struct nubus_dev *ndev,
+ struct nubus_rsrc *ndev,
  enum mac8390_type type)
 {
static u32 fwrd4_offsets[16] = {
diff --git a/drivers/net/ethernet/natsemi/macsonic.c 

Re: [PATCH v3 10/16] iommu: introduce device fault report API

2017-12-04 Thread Lu Baolu
Hi,

On 11/18/2017 02:55 AM, Jacob Pan wrote:
> Traditionally, device specific faults are detected and handled within
> their own device drivers. When IOMMU is enabled, faults such as DMA
> related transactions are detected by IOMMU. There is no generic
> reporting mechanism to report faults back to the in-kernel device
> driver or the guest OS in case of assigned devices.
>
> Faults detected by IOMMU is based on the transaction's source ID which
> can be reported at per device basis, regardless of the device type is a
> PCI device or not.
>
> The fault types include recoverable (e.g. page request) and
> unrecoverable faults(e.g. access error). In most cases, faults can be
> handled by IOMMU drivers internally. The primary use cases are as
> follows:
> 1. page request fault originated from an SVM capable device that is
> assigned to guest via vIOMMU. In this case, the first level page tables
> are owned by the guest. Page request must be propagated to the guest to
> let guest OS fault in the pages then send page response. In this
> mechanism, the direct receiver of IOMMU fault notification is VFIO,
> which can relay notification events to QEMU or other user space
> software.
>
> 2. faults need more subtle handling by device drivers. Other than
> simply invoke reset function, there are needs to let device driver
> handle the fault with a smaller impact.
>
> This patchset is intended to create a generic fault report API such
> that it can scale as follows:
> - all IOMMU types
> - PCI and non-PCI devices
> - recoverable and unrecoverable faults
> - VFIO and other other in kernel users
> - DMA & IRQ remapping (TBD)
> The original idea was brought up by David Woodhouse and discussions
> summarized at https://lwn.net/Articles/608914/.
>
> Signed-off-by: Jacob Pan 
> Signed-off-by: Ashok Raj 
> ---
>  drivers/iommu/iommu.c | 63 
> ++-
>  include/linux/iommu.h | 36 +
>  2 files changed, 98 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 829e9e9..97b7990 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -581,6 +581,12 @@ int iommu_group_add_device(struct iommu_group *group, 
> struct device *dev)
>   goto err_free_name;
>   }
>  
> + dev->iommu_param = kzalloc(sizeof(struct iommu_fault_param), 
> GFP_KERNEL);
> + if (!dev->iommu_param) {
> + ret = -ENOMEM;
> + goto err_free_name;
> + }
> +
>   kobject_get(group->devices_kobj);
>  
>   dev->iommu_group = group;
> @@ -657,7 +663,7 @@ void iommu_group_remove_device(struct device *dev)
>   sysfs_remove_link(>kobj, "iommu_group");
>  
>   trace_remove_device_from_group(group->id, dev);
> -
> + kfree(dev->iommu_param);
>   kfree(device->name);
>   kfree(device);
>   dev->iommu_group = NULL;
> @@ -791,6 +797,61 @@ int iommu_group_unregister_notifier(struct iommu_group 
> *group,
>  }
>  EXPORT_SYMBOL_GPL(iommu_group_unregister_notifier);
>  
> +int iommu_register_device_fault_handler(struct device *dev,
> + iommu_dev_fault_handler_t handler,
> + void *data)
> +{
> + struct iommu_param *idata = dev->iommu_param;
> +
> + /*
> +  * Device iommu_param should have been allocated when device is
> +  * added to its iommu_group.
> +  */
> + if (!idata)
> + return -EINVAL;
> + /* Only allow one fault handler registered for each device */
> + if (idata->fault_param)
> + return -EBUSY;
> + get_device(dev);
> + idata->fault_param =
> + kzalloc(sizeof(struct iommu_fault_param), GFP_KERNEL);
> + if (!idata->fault_param)
> + return -ENOMEM;
> + idata->fault_param->handler = handler;
> + idata->fault_param->data = data;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(iommu_register_device_fault_handler);
> +
> +int iommu_unregister_device_fault_handler(struct device *dev)
> +{
> + struct iommu_param *idata = dev->iommu_param;
> +
> + if (!idata)
> + return -EINVAL;
> +
> + kfree(idata->fault_param);
> + idata->fault_param = NULL;
> + put_device(dev);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(iommu_unregister_device_fault_handler);
> +
> +
> +int iommu_report_device_fault(struct device *dev, struct iommu_fault_event 
> *evt)
> +{
> + /* we only report device fault if there is a handler registered */
> + if (!dev->iommu_param || !dev->iommu_param->fault_param ||
> + !dev->iommu_param->fault_param->handler)

Can this replaced by:

if (!iommu_has_device_fault_handler(dev))

?

Best regards,
Lu Baolu

> + return -ENOSYS;
> +
> + return dev->iommu_param->fault_param->handler(evt,
> + 
> dev->iommu_param->fault_param->data);

Re: [PATCH v3 10/16] iommu: introduce device fault report API

2017-12-04 Thread Lu Baolu
Hi,

On 11/18/2017 02:55 AM, Jacob Pan wrote:
> Traditionally, device specific faults are detected and handled within
> their own device drivers. When IOMMU is enabled, faults such as DMA
> related transactions are detected by IOMMU. There is no generic
> reporting mechanism to report faults back to the in-kernel device
> driver or the guest OS in case of assigned devices.
>
> Faults detected by IOMMU is based on the transaction's source ID which
> can be reported at per device basis, regardless of the device type is a
> PCI device or not.
>
> The fault types include recoverable (e.g. page request) and
> unrecoverable faults(e.g. access error). In most cases, faults can be
> handled by IOMMU drivers internally. The primary use cases are as
> follows:
> 1. page request fault originated from an SVM capable device that is
> assigned to guest via vIOMMU. In this case, the first level page tables
> are owned by the guest. Page request must be propagated to the guest to
> let guest OS fault in the pages then send page response. In this
> mechanism, the direct receiver of IOMMU fault notification is VFIO,
> which can relay notification events to QEMU or other user space
> software.
>
> 2. faults need more subtle handling by device drivers. Other than
> simply invoke reset function, there are needs to let device driver
> handle the fault with a smaller impact.
>
> This patchset is intended to create a generic fault report API such
> that it can scale as follows:
> - all IOMMU types
> - PCI and non-PCI devices
> - recoverable and unrecoverable faults
> - VFIO and other other in kernel users
> - DMA & IRQ remapping (TBD)
> The original idea was brought up by David Woodhouse and discussions
> summarized at https://lwn.net/Articles/608914/.
>
> Signed-off-by: Jacob Pan 
> Signed-off-by: Ashok Raj 
> ---
>  drivers/iommu/iommu.c | 63 
> ++-
>  include/linux/iommu.h | 36 +
>  2 files changed, 98 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 829e9e9..97b7990 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -581,6 +581,12 @@ int iommu_group_add_device(struct iommu_group *group, 
> struct device *dev)
>   goto err_free_name;
>   }
>  
> + dev->iommu_param = kzalloc(sizeof(struct iommu_fault_param), 
> GFP_KERNEL);
> + if (!dev->iommu_param) {
> + ret = -ENOMEM;
> + goto err_free_name;
> + }
> +
>   kobject_get(group->devices_kobj);
>  
>   dev->iommu_group = group;
> @@ -657,7 +663,7 @@ void iommu_group_remove_device(struct device *dev)
>   sysfs_remove_link(>kobj, "iommu_group");
>  
>   trace_remove_device_from_group(group->id, dev);
> -
> + kfree(dev->iommu_param);
>   kfree(device->name);
>   kfree(device);
>   dev->iommu_group = NULL;
> @@ -791,6 +797,61 @@ int iommu_group_unregister_notifier(struct iommu_group 
> *group,
>  }
>  EXPORT_SYMBOL_GPL(iommu_group_unregister_notifier);
>  
> +int iommu_register_device_fault_handler(struct device *dev,
> + iommu_dev_fault_handler_t handler,
> + void *data)
> +{
> + struct iommu_param *idata = dev->iommu_param;
> +
> + /*
> +  * Device iommu_param should have been allocated when device is
> +  * added to its iommu_group.
> +  */
> + if (!idata)
> + return -EINVAL;
> + /* Only allow one fault handler registered for each device */
> + if (idata->fault_param)
> + return -EBUSY;
> + get_device(dev);
> + idata->fault_param =
> + kzalloc(sizeof(struct iommu_fault_param), GFP_KERNEL);
> + if (!idata->fault_param)
> + return -ENOMEM;
> + idata->fault_param->handler = handler;
> + idata->fault_param->data = data;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(iommu_register_device_fault_handler);
> +
> +int iommu_unregister_device_fault_handler(struct device *dev)
> +{
> + struct iommu_param *idata = dev->iommu_param;
> +
> + if (!idata)
> + return -EINVAL;
> +
> + kfree(idata->fault_param);
> + idata->fault_param = NULL;
> + put_device(dev);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(iommu_unregister_device_fault_handler);
> +
> +
> +int iommu_report_device_fault(struct device *dev, struct iommu_fault_event 
> *evt)
> +{
> + /* we only report device fault if there is a handler registered */
> + if (!dev->iommu_param || !dev->iommu_param->fault_param ||
> + !dev->iommu_param->fault_param->handler)

Can this replaced by:

if (!iommu_has_device_fault_handler(dev))

?

Best regards,
Lu Baolu

> + return -ENOSYS;
> +
> + return dev->iommu_param->fault_param->handler(evt,
> + 
> dev->iommu_param->fault_param->data);
> +}
> 

[PATCH v3 06/14] nubus: Call proc_mkdir() not more than once per slot directory

2017-12-04 Thread Finn Thain
This patch fixes the following WARNING.

proc_dir_entry 'nubus/a' already registered
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Tainted: GW   
4.13.0-00036-gd57552077387 #1
Stack from 01c1bd9c:
01c1bd9c 003c2c8b 01c1bdc0 0001b0fe  00322f4a 01c43a20 01c43b0c
01c8c420 01c1bde8 0001b1b8 003a4ac3 0148 000faa26 0009 
01c1bde0 003a4b6c 01c1bdfc 01c1be20 000faa26 003a4ac3 0148 003a4b6c
01c43a71 01c8c471 01c1 00326430 0043d00c 0005 01c71a00 0020bce0
00322964 01c1be38 000fac04 01c43a20 01c8c420 01c1bee0 01c8c420 01c1be50
000fac4c 01c1bee0  01c43a20  01c1bee8 0020bd26 01c1bee0
Call Trace: [<0001b0fe>] __warn+0xae/0xde
 [<00322f4a>] memcmp+0x0/0x5c
 [<0001b1b8>] warn_slowpath_fmt+0x2e/0x36
 [<000faa26>] proc_register+0xbe/0xd8
 [<000faa26>] proc_register+0xbe/0xd8
 [<00326430>] sprintf+0x0/0x20
 [<0020bce0>] nubus_proc_attach_device+0x0/0x1b8
 [<00322964>] strcpy+0x0/0x22
 [<000fac04>] proc_mkdir_data+0x64/0x96
 [<000fac4c>] proc_mkdir+0x16/0x1c
 [<0020bd26>] nubus_proc_attach_device+0x46/0x1b8
 [<0020bce0>] nubus_proc_attach_device+0x0/0x1b8
 [<00322964>] strcpy+0x0/0x22
 [<1ba6>] kernel_pg_dir+0xba6/0x1000
 [<004339a2>] proc_bus_nubus_add_devices+0x1a/0x2e
 [<000faa40>] proc_create_data+0x0/0xf2
 [<0003297c>] parse_args+0x0/0x2d4
 [<00433a08>] nubus_proc_init+0x52/0x5a
 [<00433944>] nubus_init+0x0/0x44
 [<00433982>] nubus_init+0x3e/0x44
 [<20dc>] do_one_initcall+0x38/0x196
 [<20a4>] do_one_initcall+0x0/0x196
 [<0003297c>] parse_args+0x0/0x2d4
 [<00322964>] strcpy+0x0/0x22
 [<00040004>] __up_read+0xe/0x40
 [<004231d4>] repair_env_string+0x0/0x7a
 [<0042312e>] kernel_init_freeable+0xee/0x194
 [<00423146>] kernel_init_freeable+0x106/0x194
 [<00433944>] nubus_init+0x0/0x44
 [<000a6000>] kfree+0x0/0x156
 [<0032768c>] kernel_init+0x0/0xda
 [<00327698>] kernel_init+0xc/0xda
 [<0032768c>] kernel_init+0x0/0xda
 [<2a90>] ret_from_kernel_thread+0xc/0x14
---[ end trace 14a6d619908ea253 ]---
[ cut here ]

This gets repeated with each additional functional reasource.

The problem here is the call to proc_mkdir() when the directory already
exists. Each nubus_board gets a directory, such as /proc/bus/nubus/s/
where s is the hex slot number. Therefore, store the 'procdir' pointer
in struct nubus_board instead of struct nubus_dev.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/proc.c  | 6 +-
 include/linux/nubus.h | 5 +++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index fc20dbcd3b9a..91211192f36f 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -134,9 +134,13 @@ int nubus_proc_attach_device(struct nubus_dev *dev)
return -1;
}

+   if (dev->board->procdir)
+   return 0;
+
/* Create a directory */
snprintf(name, sizeof(name), "%x", dev->board->slot);
-   e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir);
+   e = proc_mkdir(name, proc_bus_nubus_dir);
+   dev->board->procdir = e;
if (!e)
return -ENOMEM;
 
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index bffd09a07326..474f304485ec 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -53,13 +53,14 @@ struct nubus_board {
unsigned char rev;
unsigned char format;
unsigned char lanes;
+
+   /* Directory entry in /proc/bus/nubus */
+   struct proc_dir_entry *procdir;
 };
 
 struct nubus_dev {
/* Next link in device list */
struct nubus_dev* next;
-   /* Directory entry in /proc/bus/nubus */
-   struct proc_dir_entry* procdir;
 
/* The functional resource ID of this device */
unsigned char resid;
-- 
2.13.6



[PATCH v3 07/14] nubus: Remove redundant code

2017-12-04 Thread Finn Thain
Eliminate unused values from struct nubus_dev to save wasted memory
(a Radius PrecisionColor 24X card has about 95 functional resources
and up to six such cards may be fitted). Also remove redundant static
variable initialization, an unreachable !MACH_IS_MAC conditional,
the unused nubus_find_device() function, the bogus get_nubus_list()
prototype and the pointless card_present temporary variable.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 57 ---
 drivers/nubus/proc.c  |  2 --
 include/linux/nubus.h | 17 +--
 3 files changed, 23 insertions(+), 53 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 2919a5c7321a..041c2be7407f 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -282,23 +282,6 @@ EXPORT_SYMBOL(nubus_rewinddir);
 /* Driver interface functions, more or less like in pci.c */
 
 struct nubus_dev*
-nubus_find_device(unsigned short category, unsigned short type,
- unsigned short dr_hw, unsigned short dr_sw,
- const struct nubus_dev *from)
-{
-   struct nubus_dev *itor = from ? from->next : nubus_devices;
-
-   while (itor) {
-   if (itor->category == category && itor->type == type &&
-   itor->dr_hw == dr_hw && itor->dr_sw == dr_sw)
-   return itor;
-   itor = itor->next;
-   }
-   return NULL;
-}
-EXPORT_SYMBOL(nubus_find_device);
-
-struct nubus_dev*
 nubus_find_type(unsigned short category, unsigned short type,
const struct nubus_dev *from)
 {
@@ -469,8 +452,10 @@ nubus_get_functional_resource(struct nubus_board *board, 
int slot,
}
case NUBUS_RESID_NAME:
{
-   nubus_get_rsrc_str(dev->name, , sizeof(dev->name));
-   pr_debug("name: %s\n", dev->name);
+   char name[64];
+
+   nubus_get_rsrc_str(name, , sizeof(name));
+   pr_debug("name: %s\n", name);
break;
}
case NUBUS_RESID_DRVRDIR:
@@ -479,32 +464,39 @@ nubus_get_functional_resource(struct nubus_board *board, 
int slot,
   use this :-) */
struct nubus_dir drvr_dir;
struct nubus_dirent drvr_ent;
+   unsigned char *driver;
 
nubus_get_subdir(, _dir);
nubus_readdir(_dir, _ent);
-   dev->driver = nubus_dirptr(_ent);
-   pr_debug("driver at: 0x%p\n", dev->driver);
+   driver = nubus_dirptr(_ent);
+   pr_debug("driver at: 0x%p\n", driver);
break;
}
case NUBUS_RESID_MINOR_BASEOS:
+   {
/* We will need this in order to support
   multiple framebuffers.  It might be handy
   for Ethernet as well */
-   nubus_get_rsrc_mem(>iobase, , 4);
-   pr_debug("memory offset: 0x%08lx\n", dev->iobase);
+   u32 base_offset;
+
+   nubus_get_rsrc_mem(_offset, , 4);
+   pr_debug("memory offset: 0x%08x\n", base_offset);
break;
+   }
case NUBUS_RESID_MINOR_LENGTH:
+   {
/* Ditto */
-   nubus_get_rsrc_mem(>iosize, , 4);
-   pr_debug("memory length: 0x%08lx\n", dev->iosize);
+   u32 length;
+
+   nubus_get_rsrc_mem(, , 4);
+   pr_debug("memory length: 0x%08x\n", length);
break;
+   }
case NUBUS_RESID_FLAGS:
-   dev->flags = ent.data;
-   pr_debug("flags: 0x%06x\n", dev->flags);
+   pr_debug("flags: 0x%06x\n", ent.data);
break;
case NUBUS_RESID_HWDEVID:
-   dev->hwdevid = ent.data;
-   pr_debug("hwdevid: 0x%06x\n", dev->hwdevid);
+   pr_debug("hwdevid: 0x%06x\n", ent.data);
break;
default:
/* Local/Private resources have their own
@@ -796,11 +788,8 @@ static void __init nubus_probe_slot(int slot)
 
rp = nubus_rom_addr(slot);
for (i = 4; i; i--) {
-   int card_present;
-
rp--;
-   card_present = hwreg_present(rp);
-   if (!card_present)
+   if (!hwreg_present(rp))
continue;
 
dp = *rp;
@@ -837,8 

[PATCH v3 06/14] nubus: Call proc_mkdir() not more than once per slot directory

2017-12-04 Thread Finn Thain
This patch fixes the following WARNING.

proc_dir_entry 'nubus/a' already registered
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Tainted: GW   
4.13.0-00036-gd57552077387 #1
Stack from 01c1bd9c:
01c1bd9c 003c2c8b 01c1bdc0 0001b0fe  00322f4a 01c43a20 01c43b0c
01c8c420 01c1bde8 0001b1b8 003a4ac3 0148 000faa26 0009 
01c1bde0 003a4b6c 01c1bdfc 01c1be20 000faa26 003a4ac3 0148 003a4b6c
01c43a71 01c8c471 01c1 00326430 0043d00c 0005 01c71a00 0020bce0
00322964 01c1be38 000fac04 01c43a20 01c8c420 01c1bee0 01c8c420 01c1be50
000fac4c 01c1bee0  01c43a20  01c1bee8 0020bd26 01c1bee0
Call Trace: [<0001b0fe>] __warn+0xae/0xde
 [<00322f4a>] memcmp+0x0/0x5c
 [<0001b1b8>] warn_slowpath_fmt+0x2e/0x36
 [<000faa26>] proc_register+0xbe/0xd8
 [<000faa26>] proc_register+0xbe/0xd8
 [<00326430>] sprintf+0x0/0x20
 [<0020bce0>] nubus_proc_attach_device+0x0/0x1b8
 [<00322964>] strcpy+0x0/0x22
 [<000fac04>] proc_mkdir_data+0x64/0x96
 [<000fac4c>] proc_mkdir+0x16/0x1c
 [<0020bd26>] nubus_proc_attach_device+0x46/0x1b8
 [<0020bce0>] nubus_proc_attach_device+0x0/0x1b8
 [<00322964>] strcpy+0x0/0x22
 [<1ba6>] kernel_pg_dir+0xba6/0x1000
 [<004339a2>] proc_bus_nubus_add_devices+0x1a/0x2e
 [<000faa40>] proc_create_data+0x0/0xf2
 [<0003297c>] parse_args+0x0/0x2d4
 [<00433a08>] nubus_proc_init+0x52/0x5a
 [<00433944>] nubus_init+0x0/0x44
 [<00433982>] nubus_init+0x3e/0x44
 [<20dc>] do_one_initcall+0x38/0x196
 [<20a4>] do_one_initcall+0x0/0x196
 [<0003297c>] parse_args+0x0/0x2d4
 [<00322964>] strcpy+0x0/0x22
 [<00040004>] __up_read+0xe/0x40
 [<004231d4>] repair_env_string+0x0/0x7a
 [<0042312e>] kernel_init_freeable+0xee/0x194
 [<00423146>] kernel_init_freeable+0x106/0x194
 [<00433944>] nubus_init+0x0/0x44
 [<000a6000>] kfree+0x0/0x156
 [<0032768c>] kernel_init+0x0/0xda
 [<00327698>] kernel_init+0xc/0xda
 [<0032768c>] kernel_init+0x0/0xda
 [<2a90>] ret_from_kernel_thread+0xc/0x14
---[ end trace 14a6d619908ea253 ]---
[ cut here ]

This gets repeated with each additional functional reasource.

The problem here is the call to proc_mkdir() when the directory already
exists. Each nubus_board gets a directory, such as /proc/bus/nubus/s/
where s is the hex slot number. Therefore, store the 'procdir' pointer
in struct nubus_board instead of struct nubus_dev.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/proc.c  | 6 +-
 include/linux/nubus.h | 5 +++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index fc20dbcd3b9a..91211192f36f 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -134,9 +134,13 @@ int nubus_proc_attach_device(struct nubus_dev *dev)
return -1;
}

+   if (dev->board->procdir)
+   return 0;
+
/* Create a directory */
snprintf(name, sizeof(name), "%x", dev->board->slot);
-   e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir);
+   e = proc_mkdir(name, proc_bus_nubus_dir);
+   dev->board->procdir = e;
if (!e)
return -ENOMEM;
 
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index bffd09a07326..474f304485ec 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -53,13 +53,14 @@ struct nubus_board {
unsigned char rev;
unsigned char format;
unsigned char lanes;
+
+   /* Directory entry in /proc/bus/nubus */
+   struct proc_dir_entry *procdir;
 };
 
 struct nubus_dev {
/* Next link in device list */
struct nubus_dev* next;
-   /* Directory entry in /proc/bus/nubus */
-   struct proc_dir_entry* procdir;
 
/* The functional resource ID of this device */
unsigned char resid;
-- 
2.13.6



[PATCH v3 07/14] nubus: Remove redundant code

2017-12-04 Thread Finn Thain
Eliminate unused values from struct nubus_dev to save wasted memory
(a Radius PrecisionColor 24X card has about 95 functional resources
and up to six such cards may be fitted). Also remove redundant static
variable initialization, an unreachable !MACH_IS_MAC conditional,
the unused nubus_find_device() function, the bogus get_nubus_list()
prototype and the pointless card_present temporary variable.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 57 ---
 drivers/nubus/proc.c  |  2 --
 include/linux/nubus.h | 17 +--
 3 files changed, 23 insertions(+), 53 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 2919a5c7321a..041c2be7407f 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -282,23 +282,6 @@ EXPORT_SYMBOL(nubus_rewinddir);
 /* Driver interface functions, more or less like in pci.c */
 
 struct nubus_dev*
-nubus_find_device(unsigned short category, unsigned short type,
- unsigned short dr_hw, unsigned short dr_sw,
- const struct nubus_dev *from)
-{
-   struct nubus_dev *itor = from ? from->next : nubus_devices;
-
-   while (itor) {
-   if (itor->category == category && itor->type == type &&
-   itor->dr_hw == dr_hw && itor->dr_sw == dr_sw)
-   return itor;
-   itor = itor->next;
-   }
-   return NULL;
-}
-EXPORT_SYMBOL(nubus_find_device);
-
-struct nubus_dev*
 nubus_find_type(unsigned short category, unsigned short type,
const struct nubus_dev *from)
 {
@@ -469,8 +452,10 @@ nubus_get_functional_resource(struct nubus_board *board, 
int slot,
}
case NUBUS_RESID_NAME:
{
-   nubus_get_rsrc_str(dev->name, , sizeof(dev->name));
-   pr_debug("name: %s\n", dev->name);
+   char name[64];
+
+   nubus_get_rsrc_str(name, , sizeof(name));
+   pr_debug("name: %s\n", name);
break;
}
case NUBUS_RESID_DRVRDIR:
@@ -479,32 +464,39 @@ nubus_get_functional_resource(struct nubus_board *board, 
int slot,
   use this :-) */
struct nubus_dir drvr_dir;
struct nubus_dirent drvr_ent;
+   unsigned char *driver;
 
nubus_get_subdir(, _dir);
nubus_readdir(_dir, _ent);
-   dev->driver = nubus_dirptr(_ent);
-   pr_debug("driver at: 0x%p\n", dev->driver);
+   driver = nubus_dirptr(_ent);
+   pr_debug("driver at: 0x%p\n", driver);
break;
}
case NUBUS_RESID_MINOR_BASEOS:
+   {
/* We will need this in order to support
   multiple framebuffers.  It might be handy
   for Ethernet as well */
-   nubus_get_rsrc_mem(>iobase, , 4);
-   pr_debug("memory offset: 0x%08lx\n", dev->iobase);
+   u32 base_offset;
+
+   nubus_get_rsrc_mem(_offset, , 4);
+   pr_debug("memory offset: 0x%08x\n", base_offset);
break;
+   }
case NUBUS_RESID_MINOR_LENGTH:
+   {
/* Ditto */
-   nubus_get_rsrc_mem(>iosize, , 4);
-   pr_debug("memory length: 0x%08lx\n", dev->iosize);
+   u32 length;
+
+   nubus_get_rsrc_mem(, , 4);
+   pr_debug("memory length: 0x%08x\n", length);
break;
+   }
case NUBUS_RESID_FLAGS:
-   dev->flags = ent.data;
-   pr_debug("flags: 0x%06x\n", dev->flags);
+   pr_debug("flags: 0x%06x\n", ent.data);
break;
case NUBUS_RESID_HWDEVID:
-   dev->hwdevid = ent.data;
-   pr_debug("hwdevid: 0x%06x\n", dev->hwdevid);
+   pr_debug("hwdevid: 0x%06x\n", ent.data);
break;
default:
/* Local/Private resources have their own
@@ -796,11 +788,8 @@ static void __init nubus_probe_slot(int slot)
 
rp = nubus_rom_addr(slot);
for (i = 4; i; i--) {
-   int card_present;
-
rp--;
-   card_present = hwreg_present(rp);
-   if (!card_present)
+   if (!hwreg_present(rp))
continue;
 
dp = *rp;
@@ -837,8 +826,6 @@ static int __init nubus_init(void)
  

[PATCH v3 12/14] nubus: Adopt standard linked list implementation

2017-12-04 Thread Finn Thain
This increases code re-use and improves readability.

Cc: Bartlomiej Zolnierkiewicz 
Signed-off-by: Finn Thain 
Tested-by: Stan Johnson 
---
 drivers/net/ethernet/8390/mac8390.c |  7 +++--
 drivers/net/ethernet/cirrus/mac89x0.c   |  6 +++--
 drivers/net/ethernet/natsemi/macsonic.c |  8 +++---
 drivers/nubus/nubus.c   | 45 -
 drivers/nubus/proc.c| 11 +++-
 drivers/video/fbdev/macfb.c |  8 +++---
 include/linux/nubus.h   | 15 +--
 7 files changed, 40 insertions(+), 60 deletions(-)

diff --git a/drivers/net/ethernet/8390/mac8390.c 
b/drivers/net/ethernet/8390/mac8390.c
index 929ff6419621..2f91ce8dc614 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -416,8 +416,11 @@ struct net_device * __init mac8390_probe(int unit)
if (unit >= 0)
sprintf(dev->name, "eth%d", unit);
 
-   while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET,
-  ndev))) {
+   for_each_func_rsrc(ndev) {
+   if (ndev->category != NUBUS_CAT_NETWORK ||
+   ndev->type != NUBUS_TYPE_ETHERNET)
+   continue;
+
/* Have we seen it already? */
if (slots & (1 << ndev->board->slot))
continue;
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c 
b/drivers/net/ethernet/cirrus/mac89x0.c
index f910f0f386d6..977d4c2c759d 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -187,6 +187,7 @@ struct net_device * __init mac89x0_probe(int unit)
unsigned long ioaddr;
unsigned short sig;
int err = -ENODEV;
+   struct nubus_rsrc *fres;
 
if (!MACH_IS_MAC)
return ERR_PTR(-ENODEV);
@@ -207,8 +208,9 @@ struct net_device * __init mac89x0_probe(int unit)
/* We might have to parameterize this later */
slot = 0xE;
/* Get out now if there's a real NuBus card in slot E */
-   if (nubus_find_slot(slot, NULL) != NULL)
-   goto out;
+   for_each_func_rsrc(fres)
+   if (fres->board->slot == slot)
+   goto out;
 
/* The pseudo-ISA bits always live at offset 0x300 (gee,
wonder why...) */
diff --git a/drivers/net/ethernet/natsemi/macsonic.c 
b/drivers/net/ethernet/natsemi/macsonic.c
index 14f3fb50dc21..313fe5e0184b 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -464,9 +464,11 @@ static int mac_nubus_sonic_probe(struct net_device *dev)
int reg_offset, dma_bitmode;
 
/* Find the first SONIC that hasn't been initialized already */
-   while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
-  NUBUS_TYPE_ETHERNET, ndev)) != NULL)
-   {
+   for_each_func_rsrc(ndev) {
+   if (ndev->category != NUBUS_CAT_NETWORK ||
+   ndev->type != NUBUS_TYPE_ETHERNET)
+   continue;
+
/* Have we seen it already? */
if (slots & (1slot))
continue;
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 324f6e4407c8..380f320c050f 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -32,7 +32,7 @@
 
 /* Globals */
 
-struct nubus_rsrc *nubus_func_rsrcs;
+LIST_HEAD(nubus_func_rsrcs);
 struct nubus_board *nubus_boards;
 
 /* Meaning of "bytelanes":
@@ -305,33 +305,20 @@ EXPORT_SYMBOL(nubus_rewinddir);
 
 /* Driver interface functions, more or less like in pci.c */
 
-struct nubus_rsrc *nubus_find_type(unsigned short category, unsigned short 
type,
-   const struct nubus_rsrc *from)
+struct nubus_rsrc *nubus_first_rsrc_or_null(void)
 {
-   struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
-
-   while (itor) {
-   if (itor->category == category && itor->type == type)
-   return itor;
-   itor = itor->next;
-   }
-   return NULL;
+   return list_first_entry_or_null(_func_rsrcs, struct nubus_rsrc,
+   list);
 }
-EXPORT_SYMBOL(nubus_find_type);
+EXPORT_SYMBOL(nubus_first_rsrc_or_null);
 
-struct nubus_rsrc *nubus_find_slot(unsigned int slot,
-   const struct nubus_rsrc *from)
+struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
 {
-   struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
-
-   while (itor) {
-   if (itor->board->slot == slot)
-   return itor;
-   itor = itor->next;
-   }
-   return NULL;
+   if (list_is_last(>list, _func_rsrcs))
+   return NULL;
+   return list_next_entry(from, 

[PATCH v3 05/14] nubus: Validate slot resource IDs

2017-12-04 Thread Finn Thain
While we are here, include the slot number in the related error messages.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 2475b48c29d4..2919a5c7321a 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -616,7 +616,7 @@ static int __init nubus_get_board_resource(struct 
nubus_board *board, int slot,
nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
nbtdata[2] != 0 || nbtdata[3] != 0)
-   pr_err("this sResource is not a board 
resource!\n");
+   pr_err("Slot %X: sResource is not a board 
resource!\n", slot);
break;
}
case NUBUS_RESID_NAME:
@@ -671,6 +671,7 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
unsigned long dpat;
struct nubus_dir dir;
struct nubus_dirent ent;
+   int prev_resid = -1;
 
/* Move to the start of the format block */
rp = nubus_rom_addr(slot);
@@ -710,10 +711,10 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
 
/* Directory offset should be small and negative... */
if (!(board->doffset & 0x00FF))
-   pr_warn("Dodgy doffset!\n");
+   pr_warn("Slot %X: Dodgy doffset!\n", slot);
dpat = nubus_get_rom(, 4, bytelanes);
if (dpat != NUBUS_TEST_PATTERN)
-   pr_warn("Wrong test pattern %08lx!\n", dpat);
+   pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
 
/*
 *  I wonder how the CRC is meant to work -
@@ -739,12 +740,15 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
   for each of them. */
if (nubus_readdir(, ) == -1) {
/* We can't have this! */
-   pr_err("Board resource not found!\n");
+   pr_err("Slot %X: Board resource not found!\n", slot);
return NULL;
-   } else {
-   nubus_get_board_resource(board, slot, );
}
 
+   if (ent.type < 1 || ent.type > 127)
+   pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
+
+   nubus_get_board_resource(board, slot, );
+
while (nubus_readdir(, ) != -1) {
struct nubus_dev *dev;
struct nubus_dev **devp;
@@ -753,6 +757,15 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
if (dev == NULL)
continue;
 
+   /* Resources should appear in ascending ID order. This sanity
+* check prevents duplicate resource IDs.
+*/
+   if (dev->resid <= prev_resid) {
+   kfree(dev);
+   continue;
+   }
+   prev_resid = dev->resid;
+
/* We zeroed this out above */
if (board->first_dev == NULL)
board->first_dev = dev;
-- 
2.13.6



[PATCH 1/2] KVM: MMU: Fix infinite loop when there is no available mmu page

2017-12-04 Thread Wanpeng Li
From: Wanpeng Li 

The below test case can cause infinite loop in kvm when ept=0.

#include 
#include 
#include 
#include 
#include 
#include 
#include 

long r[5];
int main()
{
r[2] = open("/dev/kvm", O_RDONLY);
r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
ioctl(r[4], KVM_RUN, 0);
}

It doesn't setup the memory regions, mmu_alloc_shadow/direct_roots() in 
kvm return 1 when kvm fails to allocate root page table which can result 
in beblow infinite loop:

vcpu_run() {
for (;;) {
r = vcpu_enter_guest()::kvm_mmu_reload() returns 1 
if (r <= 0)
break;
if (need_resched())
cond_resched();
  }
}

This patch fixes it by returning -ENOSPC when there is no available kvm mmu 
page for root page table.

Cc: Paolo Bonzini 
Cc: Radim Krčmář 
Fixes: 26eeb53cf0f (KVM: MMU: Bail out immediately if there is no available mmu 
page)
Signed-off-by: Wanpeng Li 
---
 arch/x86/kvm/mmu.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c9aaa18..89da688 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3395,7 +3395,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if(make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, 0, 0,
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
@@ -3410,7 +3410,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
@@ -3450,7 +3450,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
@@ -3487,7 +3487,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, PT32_ROOT_LEVEL,
  0, ACC_ALL);
-- 
2.7.4



[PATCH v3 12/14] nubus: Adopt standard linked list implementation

2017-12-04 Thread Finn Thain
This increases code re-use and improves readability.

Cc: Bartlomiej Zolnierkiewicz 
Signed-off-by: Finn Thain 
Tested-by: Stan Johnson 
---
 drivers/net/ethernet/8390/mac8390.c |  7 +++--
 drivers/net/ethernet/cirrus/mac89x0.c   |  6 +++--
 drivers/net/ethernet/natsemi/macsonic.c |  8 +++---
 drivers/nubus/nubus.c   | 45 -
 drivers/nubus/proc.c| 11 +++-
 drivers/video/fbdev/macfb.c |  8 +++---
 include/linux/nubus.h   | 15 +--
 7 files changed, 40 insertions(+), 60 deletions(-)

diff --git a/drivers/net/ethernet/8390/mac8390.c 
b/drivers/net/ethernet/8390/mac8390.c
index 929ff6419621..2f91ce8dc614 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -416,8 +416,11 @@ struct net_device * __init mac8390_probe(int unit)
if (unit >= 0)
sprintf(dev->name, "eth%d", unit);
 
-   while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET,
-  ndev))) {
+   for_each_func_rsrc(ndev) {
+   if (ndev->category != NUBUS_CAT_NETWORK ||
+   ndev->type != NUBUS_TYPE_ETHERNET)
+   continue;
+
/* Have we seen it already? */
if (slots & (1 << ndev->board->slot))
continue;
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c 
b/drivers/net/ethernet/cirrus/mac89x0.c
index f910f0f386d6..977d4c2c759d 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -187,6 +187,7 @@ struct net_device * __init mac89x0_probe(int unit)
unsigned long ioaddr;
unsigned short sig;
int err = -ENODEV;
+   struct nubus_rsrc *fres;
 
if (!MACH_IS_MAC)
return ERR_PTR(-ENODEV);
@@ -207,8 +208,9 @@ struct net_device * __init mac89x0_probe(int unit)
/* We might have to parameterize this later */
slot = 0xE;
/* Get out now if there's a real NuBus card in slot E */
-   if (nubus_find_slot(slot, NULL) != NULL)
-   goto out;
+   for_each_func_rsrc(fres)
+   if (fres->board->slot == slot)
+   goto out;
 
/* The pseudo-ISA bits always live at offset 0x300 (gee,
wonder why...) */
diff --git a/drivers/net/ethernet/natsemi/macsonic.c 
b/drivers/net/ethernet/natsemi/macsonic.c
index 14f3fb50dc21..313fe5e0184b 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -464,9 +464,11 @@ static int mac_nubus_sonic_probe(struct net_device *dev)
int reg_offset, dma_bitmode;
 
/* Find the first SONIC that hasn't been initialized already */
-   while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
-  NUBUS_TYPE_ETHERNET, ndev)) != NULL)
-   {
+   for_each_func_rsrc(ndev) {
+   if (ndev->category != NUBUS_CAT_NETWORK ||
+   ndev->type != NUBUS_TYPE_ETHERNET)
+   continue;
+
/* Have we seen it already? */
if (slots & (1slot))
continue;
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 324f6e4407c8..380f320c050f 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -32,7 +32,7 @@
 
 /* Globals */
 
-struct nubus_rsrc *nubus_func_rsrcs;
+LIST_HEAD(nubus_func_rsrcs);
 struct nubus_board *nubus_boards;
 
 /* Meaning of "bytelanes":
@@ -305,33 +305,20 @@ EXPORT_SYMBOL(nubus_rewinddir);
 
 /* Driver interface functions, more or less like in pci.c */
 
-struct nubus_rsrc *nubus_find_type(unsigned short category, unsigned short 
type,
-   const struct nubus_rsrc *from)
+struct nubus_rsrc *nubus_first_rsrc_or_null(void)
 {
-   struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
-
-   while (itor) {
-   if (itor->category == category && itor->type == type)
-   return itor;
-   itor = itor->next;
-   }
-   return NULL;
+   return list_first_entry_or_null(_func_rsrcs, struct nubus_rsrc,
+   list);
 }
-EXPORT_SYMBOL(nubus_find_type);
+EXPORT_SYMBOL(nubus_first_rsrc_or_null);
 
-struct nubus_rsrc *nubus_find_slot(unsigned int slot,
-   const struct nubus_rsrc *from)
+struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
 {
-   struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
-
-   while (itor) {
-   if (itor->board->slot == slot)
-   return itor;
-   itor = itor->next;
-   }
-   return NULL;
+   if (list_is_last(>list, _func_rsrcs))
+   return NULL;
+   return list_next_entry(from, list);
 }
-EXPORT_SYMBOL(nubus_find_slot);

[PATCH v3 05/14] nubus: Validate slot resource IDs

2017-12-04 Thread Finn Thain
While we are here, include the slot number in the related error messages.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 2475b48c29d4..2919a5c7321a 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -616,7 +616,7 @@ static int __init nubus_get_board_resource(struct 
nubus_board *board, int slot,
nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
nbtdata[2] != 0 || nbtdata[3] != 0)
-   pr_err("this sResource is not a board 
resource!\n");
+   pr_err("Slot %X: sResource is not a board 
resource!\n", slot);
break;
}
case NUBUS_RESID_NAME:
@@ -671,6 +671,7 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
unsigned long dpat;
struct nubus_dir dir;
struct nubus_dirent ent;
+   int prev_resid = -1;
 
/* Move to the start of the format block */
rp = nubus_rom_addr(slot);
@@ -710,10 +711,10 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
 
/* Directory offset should be small and negative... */
if (!(board->doffset & 0x00FF))
-   pr_warn("Dodgy doffset!\n");
+   pr_warn("Slot %X: Dodgy doffset!\n", slot);
dpat = nubus_get_rom(, 4, bytelanes);
if (dpat != NUBUS_TEST_PATTERN)
-   pr_warn("Wrong test pattern %08lx!\n", dpat);
+   pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
 
/*
 *  I wonder how the CRC is meant to work -
@@ -739,12 +740,15 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
   for each of them. */
if (nubus_readdir(, ) == -1) {
/* We can't have this! */
-   pr_err("Board resource not found!\n");
+   pr_err("Slot %X: Board resource not found!\n", slot);
return NULL;
-   } else {
-   nubus_get_board_resource(board, slot, );
}
 
+   if (ent.type < 1 || ent.type > 127)
+   pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
+
+   nubus_get_board_resource(board, slot, );
+
while (nubus_readdir(, ) != -1) {
struct nubus_dev *dev;
struct nubus_dev **devp;
@@ -753,6 +757,15 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
if (dev == NULL)
continue;
 
+   /* Resources should appear in ascending ID order. This sanity
+* check prevents duplicate resource IDs.
+*/
+   if (dev->resid <= prev_resid) {
+   kfree(dev);
+   continue;
+   }
+   prev_resid = dev->resid;
+
/* We zeroed this out above */
if (board->first_dev == NULL)
board->first_dev = dev;
-- 
2.13.6



[PATCH 1/2] KVM: MMU: Fix infinite loop when there is no available mmu page

2017-12-04 Thread Wanpeng Li
From: Wanpeng Li 

The below test case can cause infinite loop in kvm when ept=0.

#include 
#include 
#include 
#include 
#include 
#include 
#include 

long r[5];
int main()
{
r[2] = open("/dev/kvm", O_RDONLY);
r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
ioctl(r[4], KVM_RUN, 0);
}

It doesn't setup the memory regions, mmu_alloc_shadow/direct_roots() in 
kvm return 1 when kvm fails to allocate root page table which can result 
in beblow infinite loop:

vcpu_run() {
for (;;) {
r = vcpu_enter_guest()::kvm_mmu_reload() returns 1 
if (r <= 0)
break;
if (need_resched())
cond_resched();
  }
}

This patch fixes it by returning -ENOSPC when there is no available kvm mmu 
page for root page table.

Cc: Paolo Bonzini 
Cc: Radim Krčmář 
Fixes: 26eeb53cf0f (KVM: MMU: Bail out immediately if there is no available mmu 
page)
Signed-off-by: Wanpeng Li 
---
 arch/x86/kvm/mmu.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c9aaa18..89da688 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3395,7 +3395,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if(make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, 0, 0,
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
@@ -3410,7 +3410,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
@@ -3450,7 +3450,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
@@ -3487,7 +3487,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
spin_lock(>kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(>kvm->mmu_lock);
-   return 1;
+   return -ENOSPC;
}
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, PT32_ROOT_LEVEL,
  0, ACC_ALL);
-- 
2.7.4



[PATCH 2/2] KVM: X86: Fix load RFLAGS w/o the fixed bit

2017-12-04 Thread Wanpeng Li
From: Wanpeng Li 

 *** Guest State ***
 CR0: actual=0x0030, shadow=0x6010, 
gh_mask=fff7
 CR4: actual=0x2050, shadow=0x, 
gh_mask=e871
 CR3 = 0xfffbc000
 RSP = 0x  RIP = 0x
 RFLAGS=0x DR7 = 0x0400
^^

The failed vmentry is triggered by the following testcase when ept=Y:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

long r[5];
int main()
{
r[2] = open("/dev/kvm", O_RDONLY);
r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
struct kvm_regs regs = {
.rflags = 0,
};
ioctl(r[4], KVM_SET_REGS, );
ioctl(r[4], KVM_RUN, 0);
}

X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1 
of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
This patch fixes it by catching userspace set RFLAGS w/o the fixes 
bit and bailing out immediately.

Suggested-by: Jim Mattson 
Cc: Paolo Bonzini 
Cc: Radim Krčmář 
Cc: Jim Mattson 
Signed-off-by: Wanpeng Li 
---
 virt/kvm/kvm_main.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c01cff0..7100833 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2602,6 +2602,11 @@ static long kvm_vcpu_ioctl(struct file *filp,
r = PTR_ERR(kvm_regs);
goto out;
}
+   r = -EINVAL;
+   if (!(kvm_regs->rflags & X86_EFLAGS_FIXED)) {
+   kfree(kvm_regs);
+   goto out;
+   }
r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
kfree(kvm_regs);
break;
-- 
2.7.4



[PATCH 2/2] KVM: X86: Fix load RFLAGS w/o the fixed bit

2017-12-04 Thread Wanpeng Li
From: Wanpeng Li 

 *** Guest State ***
 CR0: actual=0x0030, shadow=0x6010, 
gh_mask=fff7
 CR4: actual=0x2050, shadow=0x, 
gh_mask=e871
 CR3 = 0xfffbc000
 RSP = 0x  RIP = 0x
 RFLAGS=0x DR7 = 0x0400
^^

The failed vmentry is triggered by the following testcase when ept=Y:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

long r[5];
int main()
{
r[2] = open("/dev/kvm", O_RDONLY);
r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
struct kvm_regs regs = {
.rflags = 0,
};
ioctl(r[4], KVM_SET_REGS, );
ioctl(r[4], KVM_RUN, 0);
}

X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1 
of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
This patch fixes it by catching userspace set RFLAGS w/o the fixes 
bit and bailing out immediately.

Suggested-by: Jim Mattson 
Cc: Paolo Bonzini 
Cc: Radim Krčmář 
Cc: Jim Mattson 
Signed-off-by: Wanpeng Li 
---
 virt/kvm/kvm_main.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c01cff0..7100833 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2602,6 +2602,11 @@ static long kvm_vcpu_ioctl(struct file *filp,
r = PTR_ERR(kvm_regs);
goto out;
}
+   r = -EINVAL;
+   if (!(kvm_regs->rflags & X86_EFLAGS_FIXED)) {
+   kfree(kvm_regs);
+   goto out;
+   }
r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
kfree(kvm_regs);
break;
-- 
2.7.4



[PATCH v3 13/14] nubus: Add expansion_type values for various Mac models

2017-12-04 Thread Finn Thain
Add an expansion slot attribute to allow drivers to properly handle
cards like Comm Slot cards and PDS cards without declaration ROMs.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 arch/m68k/include/asm/macintosh.h   |   9 ++-
 arch/m68k/mac/config.c  | 110 +---
 drivers/net/ethernet/natsemi/macsonic.c |   8 +--
 3 files changed, 54 insertions(+), 73 deletions(-)

diff --git a/arch/m68k/include/asm/macintosh.h 
b/arch/m68k/include/asm/macintosh.h
index f42c27400dbc..9b840c03ebb7 100644
--- a/arch/m68k/include/asm/macintosh.h
+++ b/arch/m68k/include/asm/macintosh.h
@@ -33,7 +33,7 @@ struct mac_model
char ide_type;
char scc_type;
char ether_type;
-   char nubus_type;
+   char expansion_type;
char floppy_type;
 };
 
@@ -73,8 +73,11 @@ struct mac_model
 #define MAC_ETHER_SONIC1
 #define MAC_ETHER_MACE 2
 
-#define MAC_NO_NUBUS   0
-#define MAC_NUBUS  1
+#define MAC_EXP_NONE   0
+#define MAC_EXP_PDS1 /* Accepts only a PDS card */
+#define MAC_EXP_NUBUS  2 /* Accepts only NuBus card(s) */
+#define MAC_EXP_PDS_NUBUS  3 /* Accepts PDS card and/or NuBus card(s) */
+#define MAC_EXP_PDS_COMM   4 /* Accepts PDS card or Comm Slot card */
 
 #define MAC_FLOPPY_IWM 0
 #define MAC_FLOPPY_SWIM_ADDR1  1
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 16cd5cea5207..d3d435248a24 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -212,7 +212,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_IWM,
},
 
@@ -227,7 +227,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_IWM,
}, {
.ident  = MAC_MODEL_IIX,
@@ -236,7 +236,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_IICX,
@@ -245,7 +245,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_SE30,
@@ -254,7 +254,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_PDS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
},
 
@@ -272,7 +272,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_IIFX,
@@ -281,7 +281,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_IIFX,
.scc_type   = MAC_SCC_IOP,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_IOP,
}, {
.ident  = MAC_MODEL_IISI,
@@ -290,7 +290,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_IIVI,
@@ -299,7 +299,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = 

[PATCH v3 13/14] nubus: Add expansion_type values for various Mac models

2017-12-04 Thread Finn Thain
Add an expansion slot attribute to allow drivers to properly handle
cards like Comm Slot cards and PDS cards without declaration ROMs.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 arch/m68k/include/asm/macintosh.h   |   9 ++-
 arch/m68k/mac/config.c  | 110 +---
 drivers/net/ethernet/natsemi/macsonic.c |   8 +--
 3 files changed, 54 insertions(+), 73 deletions(-)

diff --git a/arch/m68k/include/asm/macintosh.h 
b/arch/m68k/include/asm/macintosh.h
index f42c27400dbc..9b840c03ebb7 100644
--- a/arch/m68k/include/asm/macintosh.h
+++ b/arch/m68k/include/asm/macintosh.h
@@ -33,7 +33,7 @@ struct mac_model
char ide_type;
char scc_type;
char ether_type;
-   char nubus_type;
+   char expansion_type;
char floppy_type;
 };
 
@@ -73,8 +73,11 @@ struct mac_model
 #define MAC_ETHER_SONIC1
 #define MAC_ETHER_MACE 2
 
-#define MAC_NO_NUBUS   0
-#define MAC_NUBUS  1
+#define MAC_EXP_NONE   0
+#define MAC_EXP_PDS1 /* Accepts only a PDS card */
+#define MAC_EXP_NUBUS  2 /* Accepts only NuBus card(s) */
+#define MAC_EXP_PDS_NUBUS  3 /* Accepts PDS card and/or NuBus card(s) */
+#define MAC_EXP_PDS_COMM   4 /* Accepts PDS card or Comm Slot card */
 
 #define MAC_FLOPPY_IWM 0
 #define MAC_FLOPPY_SWIM_ADDR1  1
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 16cd5cea5207..d3d435248a24 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -212,7 +212,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_IWM,
},
 
@@ -227,7 +227,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_IWM,
}, {
.ident  = MAC_MODEL_IIX,
@@ -236,7 +236,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_IICX,
@@ -245,7 +245,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_SE30,
@@ -254,7 +254,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_II,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_PDS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
},
 
@@ -272,7 +272,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_IIFX,
@@ -281,7 +281,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_IIFX,
.scc_type   = MAC_SCC_IOP,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_IOP,
}, {
.ident  = MAC_MODEL_IISI,
@@ -290,7 +290,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_OLD,
.scc_type   = MAC_SCC_II,
-   .nubus_type = MAC_NUBUS,
+   .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type= MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident  = MAC_MODEL_IIVI,
@@ -299,7 +299,7 @@ static struct mac_model mac_data_table[] = {
.via_type   = MAC_VIA_IICI,
.scsi_type  = MAC_SCSI_LC,
.scc_type   = 

[PATCH v3 14/14] nubus: Add support for the driver model

2017-12-04 Thread Finn Thain
This patch brings basic support for the Linux Driver Model to the
NuBus subsystem.

For flexibility, the matching of boards with drivers is left up to the
drivers. This is also the approach taken by NetBSD. A board may have
many functions, and drivers may have to consider many functional
resources and board resources in order to match a device.

This implementation does not bind drivers to resources (nor does it bind
many drivers to the same board). Apple's NuBus declaration ROM design
is flexible enough to allow that, but I don't see a need to support it
as we don't use the "slot zero" resources (in the main logic board ROM).

Eliminate the global nubus_boards linked list by rewriting the procfs
board iterator around bus_for_each_dev(). Hence the nubus device refcount
can be used to determine the lifespan of board objects.

Cc: Greg Kroah-Hartman 
Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 

---
The conversion of Mac network drivers from the Space.c convention to
the Driver Model takes place in a separate patch series, archived at
https://lkml.org/lkml/2017/11/11/25
That series motivates parts of this design, such as the definition of
'for_each_board_func_rsrc'.
---
 drivers/nubus/Makefile |   2 +-
 drivers/nubus/bus.c| 119 +
 drivers/nubus/nubus.c  |  24 +-
 drivers/nubus/proc.c   |  55 +--
 include/linux/nubus.h  |  33 --
 5 files changed, 163 insertions(+), 70 deletions(-)
 create mode 100644 drivers/nubus/bus.c

diff --git a/drivers/nubus/Makefile b/drivers/nubus/Makefile
index 21bda2031e7e..6d063cde39d1 100644
--- a/drivers/nubus/Makefile
+++ b/drivers/nubus/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the nubus specific drivers.
 #
 
-obj-y   := nubus.o
+obj-y := nubus.o bus.o
 
 obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/nubus/bus.c b/drivers/nubus/bus.c
new file mode 100644
index ..b5045e639b4d
--- /dev/null
+++ b/drivers/nubus/bus.c
@@ -0,0 +1,119 @@
+/*
+ * Bus implementation for the NuBus subsystem.
+ *
+ * Copyright (C) 2017 Finn Thain
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define to_nubus_board(d)   container_of(d, struct nubus_board, dev)
+#define to_nubus_driver(d)  container_of(d, struct nubus_driver, driver)
+
+static int nubus_bus_match(struct device *dev, struct device_driver *driver)
+{
+   return 1;
+}
+
+static int nubus_device_probe(struct device *dev)
+{
+   struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
+   int err = -ENODEV;
+
+   if (ndrv->probe)
+   err = ndrv->probe(to_nubus_board(dev));
+   return err;
+}
+
+static int nubus_device_remove(struct device *dev)
+{
+   struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
+   int err = -ENODEV;
+
+   if (dev->driver && ndrv->remove)
+   err = ndrv->remove(to_nubus_board(dev));
+   return err;
+}
+
+struct bus_type nubus_bus_type = {
+   .name   = "nubus",
+   .match  = nubus_bus_match,
+   .probe  = nubus_device_probe,
+   .remove = nubus_device_remove,
+};
+EXPORT_SYMBOL(nubus_bus_type);
+
+int nubus_driver_register(struct nubus_driver *ndrv)
+{
+   ndrv->driver.bus = _bus_type;
+   return driver_register(>driver);
+}
+EXPORT_SYMBOL(nubus_driver_register);
+
+void nubus_driver_unregister(struct nubus_driver *ndrv)
+{
+   driver_unregister(>driver);
+}
+EXPORT_SYMBOL(nubus_driver_unregister);
+
+static struct device nubus_parent = {
+   .init_name  = "nubus",
+};
+
+int __init nubus_bus_register(void)
+{
+   int err;
+
+   err = device_register(_parent);
+   if (err)
+   return err;
+
+   err = bus_register(_bus_type);
+   if (!err)
+   return 0;
+
+   device_unregister(_parent);
+   return err;
+}
+
+static void nubus_device_release(struct device *dev)
+{
+   struct nubus_board *board = to_nubus_board(dev);
+   struct nubus_rsrc *fres, *tmp;
+
+   list_for_each_entry_safe(fres, tmp, _func_rsrcs, list)
+   if (fres->board == board) {
+   list_del(>list);
+   kfree(fres);
+   }
+   kfree(board);
+}
+
+int nubus_device_register(struct nubus_board *board)
+{
+   board->dev.parent = _parent;
+   board->dev.release = nubus_device_release;
+   board->dev.bus = _bus_type;
+   dev_set_name(>dev, "slot.%X", board->slot);
+   return device_register(>dev);
+}
+
+static int nubus_print_device_name_fn(struct device *dev, void *data)
+{
+   struct nubus_board *board = to_nubus_board(dev);
+   struct seq_file *m = data;
+
+   seq_printf(m, "Slot %X: %s\n", board->slot, board->name);
+   return 0;
+}
+
+int nubus_proc_show(struct seq_file *m, void *data)
+{
+   return 

[PATCH v3 14/14] nubus: Add support for the driver model

2017-12-04 Thread Finn Thain
This patch brings basic support for the Linux Driver Model to the
NuBus subsystem.

For flexibility, the matching of boards with drivers is left up to the
drivers. This is also the approach taken by NetBSD. A board may have
many functions, and drivers may have to consider many functional
resources and board resources in order to match a device.

This implementation does not bind drivers to resources (nor does it bind
many drivers to the same board). Apple's NuBus declaration ROM design
is flexible enough to allow that, but I don't see a need to support it
as we don't use the "slot zero" resources (in the main logic board ROM).

Eliminate the global nubus_boards linked list by rewriting the procfs
board iterator around bus_for_each_dev(). Hence the nubus device refcount
can be used to determine the lifespan of board objects.

Cc: Greg Kroah-Hartman 
Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 

---
The conversion of Mac network drivers from the Space.c convention to
the Driver Model takes place in a separate patch series, archived at
https://lkml.org/lkml/2017/11/11/25
That series motivates parts of this design, such as the definition of
'for_each_board_func_rsrc'.
---
 drivers/nubus/Makefile |   2 +-
 drivers/nubus/bus.c| 119 +
 drivers/nubus/nubus.c  |  24 +-
 drivers/nubus/proc.c   |  55 +--
 include/linux/nubus.h  |  33 --
 5 files changed, 163 insertions(+), 70 deletions(-)
 create mode 100644 drivers/nubus/bus.c

diff --git a/drivers/nubus/Makefile b/drivers/nubus/Makefile
index 21bda2031e7e..6d063cde39d1 100644
--- a/drivers/nubus/Makefile
+++ b/drivers/nubus/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the nubus specific drivers.
 #
 
-obj-y   := nubus.o
+obj-y := nubus.o bus.o
 
 obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/nubus/bus.c b/drivers/nubus/bus.c
new file mode 100644
index ..b5045e639b4d
--- /dev/null
+++ b/drivers/nubus/bus.c
@@ -0,0 +1,119 @@
+/*
+ * Bus implementation for the NuBus subsystem.
+ *
+ * Copyright (C) 2017 Finn Thain
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define to_nubus_board(d)   container_of(d, struct nubus_board, dev)
+#define to_nubus_driver(d)  container_of(d, struct nubus_driver, driver)
+
+static int nubus_bus_match(struct device *dev, struct device_driver *driver)
+{
+   return 1;
+}
+
+static int nubus_device_probe(struct device *dev)
+{
+   struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
+   int err = -ENODEV;
+
+   if (ndrv->probe)
+   err = ndrv->probe(to_nubus_board(dev));
+   return err;
+}
+
+static int nubus_device_remove(struct device *dev)
+{
+   struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
+   int err = -ENODEV;
+
+   if (dev->driver && ndrv->remove)
+   err = ndrv->remove(to_nubus_board(dev));
+   return err;
+}
+
+struct bus_type nubus_bus_type = {
+   .name   = "nubus",
+   .match  = nubus_bus_match,
+   .probe  = nubus_device_probe,
+   .remove = nubus_device_remove,
+};
+EXPORT_SYMBOL(nubus_bus_type);
+
+int nubus_driver_register(struct nubus_driver *ndrv)
+{
+   ndrv->driver.bus = _bus_type;
+   return driver_register(>driver);
+}
+EXPORT_SYMBOL(nubus_driver_register);
+
+void nubus_driver_unregister(struct nubus_driver *ndrv)
+{
+   driver_unregister(>driver);
+}
+EXPORT_SYMBOL(nubus_driver_unregister);
+
+static struct device nubus_parent = {
+   .init_name  = "nubus",
+};
+
+int __init nubus_bus_register(void)
+{
+   int err;
+
+   err = device_register(_parent);
+   if (err)
+   return err;
+
+   err = bus_register(_bus_type);
+   if (!err)
+   return 0;
+
+   device_unregister(_parent);
+   return err;
+}
+
+static void nubus_device_release(struct device *dev)
+{
+   struct nubus_board *board = to_nubus_board(dev);
+   struct nubus_rsrc *fres, *tmp;
+
+   list_for_each_entry_safe(fres, tmp, _func_rsrcs, list)
+   if (fres->board == board) {
+   list_del(>list);
+   kfree(fres);
+   }
+   kfree(board);
+}
+
+int nubus_device_register(struct nubus_board *board)
+{
+   board->dev.parent = _parent;
+   board->dev.release = nubus_device_release;
+   board->dev.bus = _bus_type;
+   dev_set_name(>dev, "slot.%X", board->slot);
+   return device_register(>dev);
+}
+
+static int nubus_print_device_name_fn(struct device *dev, void *data)
+{
+   struct nubus_board *board = to_nubus_board(dev);
+   struct seq_file *m = data;
+
+   seq_printf(m, "Slot %X: %s\n", board->slot, board->name);
+   return 0;
+}
+
+int nubus_proc_show(struct seq_file *m, void *data)
+{
+   return bus_for_each_dev(_bus_type, NULL, m,
+   

[PATCH v3 03/14] nubus: Use static functions where possible

2017-12-04 Thread Finn Thain
This fixes a couple of warnings from 'make W=1':
drivers/nubus/nubus.c:790: warning: no previous prototype for 'nubus_probe_slot'
drivers/nubus/nubus.c:824: warning: no previous prototype for 'nubus_scan_bus'

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 4 ++--
 include/linux/nubus.h | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 566dc563e7e8..3c1d386a4640 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -793,7 +793,7 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
return board;
 }
 
-void __init nubus_probe_slot(int slot)
+static void __init nubus_probe_slot(int slot)
 {
unsigned char dp;
unsigned char *rp;
@@ -827,7 +827,7 @@ void __init nubus_probe_slot(int slot)
}
 }
 
-void __init nubus_scan_bus(void)
+static void __init nubus_scan_bus(void)
 {
int slot;
 
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index a6edf7838e22..bffd09a07326 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -92,7 +92,6 @@ extern struct nubus_dev* nubus_devices;
 extern struct nubus_board* nubus_boards;
 
 /* Generic NuBus interface functions, modelled after the PCI interface */
-void nubus_scan_bus(void);
 #ifdef CONFIG_PROC_FS
 extern void nubus_proc_init(void);
 #else
-- 
2.13.6



[PATCH v3 01/14] nubus: Avoid array underflow and overflow

2017-12-04 Thread Finn Thain
Check array indices. Avoid sprintf. Use buffers of sufficient size.
Use appropriate types for array length parameters.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 29 +
 drivers/nubus/proc.c  | 12 ++--
 include/linux/nubus.h | 10 --
 3 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index b793727cd4f7..566dc563e7e8 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -161,7 +161,7 @@ static unsigned char *nubus_dirptr(const struct 
nubus_dirent *nd)
pointed to with offsets) out of the card ROM. */
 
 void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
-   int len)
+unsigned int len)
 {
unsigned char *t = (unsigned char *)dest;
unsigned char *p = nubus_dirptr(dirent);
@@ -173,18 +173,22 @@ void nubus_get_rsrc_mem(void *dest, const struct 
nubus_dirent *dirent,
 }
 EXPORT_SYMBOL(nubus_get_rsrc_mem);
 
-void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent,
-   int len)
+void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
+unsigned int len)
 {
-   unsigned char *t = (unsigned char *)dest;
+   char *t = dest;
unsigned char *p = nubus_dirptr(dirent);
 
-   while (len) {
-   *t = nubus_get_rom(, 1, dirent->mask);
-   if (!*t++)
+   while (len > 1) {
+   unsigned char c = nubus_get_rom(, 1, dirent->mask);
+
+   if (!c)
break;
+   *t++ = c;
len--;
}
+   if (len > 0)
+   *t = '\0';
 }
 EXPORT_SYMBOL(nubus_get_rsrc_str);
 
@@ -468,7 +472,7 @@ nubus_get_functional_resource(struct nubus_board *board, 
int slot,
}
case NUBUS_RESID_NAME:
{
-   nubus_get_rsrc_str(dev->name, , 64);
+   nubus_get_rsrc_str(dev->name, , sizeof(dev->name));
pr_info("name: %s\n", dev->name);
break;
}
@@ -528,7 +532,7 @@ static int __init nubus_get_vidnames(struct nubus_board 
*board,
/* Don't know what this is yet */
u16 id;
/* Longest one I've seen so far is 26 characters */
-   char name[32];
+   char name[36];
};
 
pr_info("video modes supported:\n");
@@ -598,8 +602,8 @@ static int __init nubus_get_vendorinfo(struct nubus_board 
*board,
char name[64];
 
/* These are all strings, we think */
-   nubus_get_rsrc_str(name, , 64);
-   if (ent.type > 5)
+   nubus_get_rsrc_str(name, , sizeof(name));
+   if (ent.type < 1 || ent.type > 5)
ent.type = 5;
pr_info("%s: %s\n", vendor_fields[ent.type - 1], name);
}
@@ -633,7 +637,8 @@ static int __init nubus_get_board_resource(struct 
nubus_board *board, int slot,
break;
}
case NUBUS_RESID_NAME:
-   nubus_get_rsrc_str(board->name, , 64);
+   nubus_get_rsrc_str(board->name, ,
+  sizeof(board->name));
pr_info("name: %s\n", board->name);
break;
case NUBUS_RESID_ICON:
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index 004a122ac0ff..fc20dbcd3b9a 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -73,10 +73,10 @@ static void nubus_proc_subdir(struct nubus_dev* dev,
 
/* Some of these are directories, others aren't */
while (nubus_readdir(dir, ) != -1) {
-   char name[8];
+   char name[9];
struct proc_dir_entry* e;

-   sprintf(name, "%x", ent.type);
+   snprintf(name, sizeof(name), "%x", ent.type);
e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent,
_proc_subdir_fops);
if (!e)
@@ -95,11 +95,11 @@ static void nubus_proc_populate(struct nubus_dev* dev,
/* We know these are all directories (board resource + one or
   more functional resources) */
while (nubus_readdir(root, ) != -1) {
-   char name[8];
+   char name[9];
struct proc_dir_entry* e;
struct nubus_dir dir;

-   sprintf(name, "%x", ent.type);
+   snprintf(name, sizeof(name), "%x", ent.type);
e = proc_mkdir(name, parent);
if (!e) return;
 
@@ -119,7 +119,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev)
 {
struct proc_dir_entry 

[PATCH v3 03/14] nubus: Use static functions where possible

2017-12-04 Thread Finn Thain
This fixes a couple of warnings from 'make W=1':
drivers/nubus/nubus.c:790: warning: no previous prototype for 'nubus_probe_slot'
drivers/nubus/nubus.c:824: warning: no previous prototype for 'nubus_scan_bus'

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 4 ++--
 include/linux/nubus.h | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 566dc563e7e8..3c1d386a4640 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -793,7 +793,7 @@ static struct nubus_board * __init nubus_add_board(int 
slot, int bytelanes)
return board;
 }
 
-void __init nubus_probe_slot(int slot)
+static void __init nubus_probe_slot(int slot)
 {
unsigned char dp;
unsigned char *rp;
@@ -827,7 +827,7 @@ void __init nubus_probe_slot(int slot)
}
 }
 
-void __init nubus_scan_bus(void)
+static void __init nubus_scan_bus(void)
 {
int slot;
 
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index a6edf7838e22..bffd09a07326 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -92,7 +92,6 @@ extern struct nubus_dev* nubus_devices;
 extern struct nubus_board* nubus_boards;
 
 /* Generic NuBus interface functions, modelled after the PCI interface */
-void nubus_scan_bus(void);
 #ifdef CONFIG_PROC_FS
 extern void nubus_proc_init(void);
 #else
-- 
2.13.6



[PATCH v3 01/14] nubus: Avoid array underflow and overflow

2017-12-04 Thread Finn Thain
Check array indices. Avoid sprintf. Use buffers of sufficient size.
Use appropriate types for array length parameters.

Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 drivers/nubus/nubus.c | 29 +
 drivers/nubus/proc.c  | 12 ++--
 include/linux/nubus.h | 10 --
 3 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index b793727cd4f7..566dc563e7e8 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -161,7 +161,7 @@ static unsigned char *nubus_dirptr(const struct 
nubus_dirent *nd)
pointed to with offsets) out of the card ROM. */
 
 void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
-   int len)
+unsigned int len)
 {
unsigned char *t = (unsigned char *)dest;
unsigned char *p = nubus_dirptr(dirent);
@@ -173,18 +173,22 @@ void nubus_get_rsrc_mem(void *dest, const struct 
nubus_dirent *dirent,
 }
 EXPORT_SYMBOL(nubus_get_rsrc_mem);
 
-void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent,
-   int len)
+void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
+unsigned int len)
 {
-   unsigned char *t = (unsigned char *)dest;
+   char *t = dest;
unsigned char *p = nubus_dirptr(dirent);
 
-   while (len) {
-   *t = nubus_get_rom(, 1, dirent->mask);
-   if (!*t++)
+   while (len > 1) {
+   unsigned char c = nubus_get_rom(, 1, dirent->mask);
+
+   if (!c)
break;
+   *t++ = c;
len--;
}
+   if (len > 0)
+   *t = '\0';
 }
 EXPORT_SYMBOL(nubus_get_rsrc_str);
 
@@ -468,7 +472,7 @@ nubus_get_functional_resource(struct nubus_board *board, 
int slot,
}
case NUBUS_RESID_NAME:
{
-   nubus_get_rsrc_str(dev->name, , 64);
+   nubus_get_rsrc_str(dev->name, , sizeof(dev->name));
pr_info("name: %s\n", dev->name);
break;
}
@@ -528,7 +532,7 @@ static int __init nubus_get_vidnames(struct nubus_board 
*board,
/* Don't know what this is yet */
u16 id;
/* Longest one I've seen so far is 26 characters */
-   char name[32];
+   char name[36];
};
 
pr_info("video modes supported:\n");
@@ -598,8 +602,8 @@ static int __init nubus_get_vendorinfo(struct nubus_board 
*board,
char name[64];
 
/* These are all strings, we think */
-   nubus_get_rsrc_str(name, , 64);
-   if (ent.type > 5)
+   nubus_get_rsrc_str(name, , sizeof(name));
+   if (ent.type < 1 || ent.type > 5)
ent.type = 5;
pr_info("%s: %s\n", vendor_fields[ent.type - 1], name);
}
@@ -633,7 +637,8 @@ static int __init nubus_get_board_resource(struct 
nubus_board *board, int slot,
break;
}
case NUBUS_RESID_NAME:
-   nubus_get_rsrc_str(board->name, , 64);
+   nubus_get_rsrc_str(board->name, ,
+  sizeof(board->name));
pr_info("name: %s\n", board->name);
break;
case NUBUS_RESID_ICON:
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index 004a122ac0ff..fc20dbcd3b9a 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -73,10 +73,10 @@ static void nubus_proc_subdir(struct nubus_dev* dev,
 
/* Some of these are directories, others aren't */
while (nubus_readdir(dir, ) != -1) {
-   char name[8];
+   char name[9];
struct proc_dir_entry* e;

-   sprintf(name, "%x", ent.type);
+   snprintf(name, sizeof(name), "%x", ent.type);
e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent,
_proc_subdir_fops);
if (!e)
@@ -95,11 +95,11 @@ static void nubus_proc_populate(struct nubus_dev* dev,
/* We know these are all directories (board resource + one or
   more functional resources) */
while (nubus_readdir(root, ) != -1) {
-   char name[8];
+   char name[9];
struct proc_dir_entry* e;
struct nubus_dir dir;

-   sprintf(name, "%x", ent.type);
+   snprintf(name, sizeof(name), "%x", ent.type);
e = proc_mkdir(name, parent);
if (!e) return;
 
@@ -119,7 +119,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev)
 {
struct proc_dir_entry *e;
struct nubus_dir root;
-   char 

[PATCH v3 00/14] Modernization and fixes for NuBus subsystem

2017-12-04 Thread Finn Thain
This series begins with cleanups and fixes for the NuBus subsystem and
finishes with a patch to add support for the Linux Driver Model.
The next series, which requires this one, modernizes the NuBus drivers.

Changes since v1:
- Added the missing NULL check in nubus_device_remove().
- Squashed the two /proc/bus/nubus/s/ patches into one patch.
- Combined the two sets of /proc/bus/nubus file operations into one set.
- Used the name 'nubus_rsrc' instead of 'nubus_functional_resource'.
- Used the name 'nubus_device_register' instead of 'nubus_device_add'.
- Dropped the unused EXPORT_SYMBOL(nubus_seq_write_rsrc_mem).
- Replaced licensing text in the new file with SPDX-License-Identifier.

Changes since v2:
- Implemented an idiomatic device release function for nubus boards.
- Removed the global nubus_boards linked list.
- Removed nubus_board pointer from proc dir entry private data to improve
  modularity.
- Adopted the standard linked list implementation.
- Disambiguated unrecognized and empty resources under /proc/bus/nubus.
- Reduced redundancy in proc dir entry private data to save some memory.
- Replaced /proc/nubus custom seq file ops with single_open().


Finn Thain (14):
  nubus: Avoid array underflow and overflow
  nubus: Fix up header split
  nubus: Use static functions where possible
  nubus: Fix log spam
  nubus: Validate slot resource IDs
  nubus: Call proc_mkdir() not more than once per slot directory
  nubus: Remove redundant code
  nubus: Clean up whitespace
  nubus: Generalize block resource handling
  nubus: Rework /proc/bus/nubus/s/ implementation
  nubus: Rename struct nubus_dev
  nubus: Adopt standard linked list implementation
  nubus: Add expansion_type values for various Mac models
  nubus: Add support for the driver model

 arch/m68k/include/asm/macintosh.h   |   9 +-
 arch/m68k/mac/config.c  | 110 +++
 drivers/net/ethernet/8390/mac8390.c |  33 +-
 drivers/net/ethernet/cirrus/mac89x0.c   |   6 +-
 drivers/net/ethernet/natsemi/macsonic.c |  38 ++-
 drivers/nubus/Makefile  |   2 +-
 drivers/nubus/bus.c | 119 +++
 drivers/nubus/nubus.c   | 544 +---
 drivers/nubus/proc.c| 282 -
 drivers/video/fbdev/macfb.c |  10 +-
 include/linux/nubus.h   | 185 +++
 include/uapi/linux/nubus.h  |  23 --
 12 files changed, 763 insertions(+), 598 deletions(-)
 create mode 100644 drivers/nubus/bus.c

-- 
2.13.6



[PATCH v3 02/14] nubus: Fix up header split

2017-12-04 Thread Finn Thain
Due to the '#ifdef __KERNEL__' being located in the wrong place, some
definitions from the kernel API were placed in the UAPI header during
the scripted header split. Fix this. Also, remove the duplicate comment
which is only relevant to the UAPI header.

Fixes: 607ca46e97a1 ("UAPI: (Scripted) Disintegrate include/linux")
Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 include/linux/nubus.h  | 27 +++
 include/uapi/linux/nubus.h | 23 ---
 2 files changed, 23 insertions(+), 27 deletions(-)

diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index 18c300222362..a6edf7838e22 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -5,16 +5,28 @@
   Originally written by Alan Cox.
 
   Hacked to death by C. Scott Ananian and David Huggins-Daines.
-  
-  Some of the constants in here are from the corresponding
-  NetBSD/OpenBSD header file, by Allen Briggs.  We figured out the
-  rest of them on our own. */
+*/
+
 #ifndef LINUX_NUBUS_H
 #define LINUX_NUBUS_H
 
 #include 
 #include 
 
+struct nubus_dir {
+   unsigned char *base;
+   unsigned char *ptr;
+   int done;
+   int mask;
+};
+
+struct nubus_dirent {
+   unsigned char *base;
+   unsigned char type;
+   __u32 data; /* Actually 24 bits used */
+   int mask;
+};
+
 struct nubus_board {
struct nubus_board* next;
struct nubus_dev* first_dev;
@@ -130,4 +142,11 @@ void nubus_get_rsrc_mem(void *dest, const struct 
nubus_dirent *dirent,
 unsigned int len);
 void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
 unsigned int maxlen);
+
+/* Returns a pointer to the "standard" slot space. */
+static inline void *nubus_slot_addr(int slot)
+{
+   return (void *)(0xF000 | (slot << 24));
+}
+
 #endif /* LINUX_NUBUS_H */
diff --git a/include/uapi/linux/nubus.h b/include/uapi/linux/nubus.h
index f3776cc80f4d..48031e7858f1 100644
--- a/include/uapi/linux/nubus.h
+++ b/include/uapi/linux/nubus.h
@@ -221,27 +221,4 @@ enum nubus_display_res_id {
NUBUS_RESID_SIXTHMODE   = 0x0085
 };
 
-struct nubus_dir
-{
-   unsigned char *base;
-   unsigned char *ptr;
-   int done;
-   int mask;
-};
-
-struct nubus_dirent
-{
-   unsigned char *base;
-   unsigned char type;
-   __u32 data; /* Actually 24bits used */
-   int mask;
-};
-
-
-/* We'd like to get rid of this eventually.  Only daynaport.c uses it now. */
-static inline void *nubus_slot_addr(int slot)
-{
-   return (void *)(0xF000|(slot<<24));
-}
-
 #endif /* _UAPILINUX_NUBUS_H */
-- 
2.13.6



[PATCH v3 02/14] nubus: Fix up header split

2017-12-04 Thread Finn Thain
Due to the '#ifdef __KERNEL__' being located in the wrong place, some
definitions from the kernel API were placed in the UAPI header during
the scripted header split. Fix this. Also, remove the duplicate comment
which is only relevant to the UAPI header.

Fixes: 607ca46e97a1 ("UAPI: (Scripted) Disintegrate include/linux")
Tested-by: Stan Johnson 
Signed-off-by: Finn Thain 
---
 include/linux/nubus.h  | 27 +++
 include/uapi/linux/nubus.h | 23 ---
 2 files changed, 23 insertions(+), 27 deletions(-)

diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index 18c300222362..a6edf7838e22 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -5,16 +5,28 @@
   Originally written by Alan Cox.
 
   Hacked to death by C. Scott Ananian and David Huggins-Daines.
-  
-  Some of the constants in here are from the corresponding
-  NetBSD/OpenBSD header file, by Allen Briggs.  We figured out the
-  rest of them on our own. */
+*/
+
 #ifndef LINUX_NUBUS_H
 #define LINUX_NUBUS_H
 
 #include 
 #include 
 
+struct nubus_dir {
+   unsigned char *base;
+   unsigned char *ptr;
+   int done;
+   int mask;
+};
+
+struct nubus_dirent {
+   unsigned char *base;
+   unsigned char type;
+   __u32 data; /* Actually 24 bits used */
+   int mask;
+};
+
 struct nubus_board {
struct nubus_board* next;
struct nubus_dev* first_dev;
@@ -130,4 +142,11 @@ void nubus_get_rsrc_mem(void *dest, const struct 
nubus_dirent *dirent,
 unsigned int len);
 void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
 unsigned int maxlen);
+
+/* Returns a pointer to the "standard" slot space. */
+static inline void *nubus_slot_addr(int slot)
+{
+   return (void *)(0xF000 | (slot << 24));
+}
+
 #endif /* LINUX_NUBUS_H */
diff --git a/include/uapi/linux/nubus.h b/include/uapi/linux/nubus.h
index f3776cc80f4d..48031e7858f1 100644
--- a/include/uapi/linux/nubus.h
+++ b/include/uapi/linux/nubus.h
@@ -221,27 +221,4 @@ enum nubus_display_res_id {
NUBUS_RESID_SIXTHMODE   = 0x0085
 };
 
-struct nubus_dir
-{
-   unsigned char *base;
-   unsigned char *ptr;
-   int done;
-   int mask;
-};
-
-struct nubus_dirent
-{
-   unsigned char *base;
-   unsigned char type;
-   __u32 data; /* Actually 24bits used */
-   int mask;
-};
-
-
-/* We'd like to get rid of this eventually.  Only daynaport.c uses it now. */
-static inline void *nubus_slot_addr(int slot)
-{
-   return (void *)(0xF000|(slot<<24));
-}
-
 #endif /* _UAPILINUX_NUBUS_H */
-- 
2.13.6



[PATCH v3 00/14] Modernization and fixes for NuBus subsystem

2017-12-04 Thread Finn Thain
This series begins with cleanups and fixes for the NuBus subsystem and
finishes with a patch to add support for the Linux Driver Model.
The next series, which requires this one, modernizes the NuBus drivers.

Changes since v1:
- Added the missing NULL check in nubus_device_remove().
- Squashed the two /proc/bus/nubus/s/ patches into one patch.
- Combined the two sets of /proc/bus/nubus file operations into one set.
- Used the name 'nubus_rsrc' instead of 'nubus_functional_resource'.
- Used the name 'nubus_device_register' instead of 'nubus_device_add'.
- Dropped the unused EXPORT_SYMBOL(nubus_seq_write_rsrc_mem).
- Replaced licensing text in the new file with SPDX-License-Identifier.

Changes since v2:
- Implemented an idiomatic device release function for nubus boards.
- Removed the global nubus_boards linked list.
- Removed nubus_board pointer from proc dir entry private data to improve
  modularity.
- Adopted the standard linked list implementation.
- Disambiguated unrecognized and empty resources under /proc/bus/nubus.
- Reduced redundancy in proc dir entry private data to save some memory.
- Replaced /proc/nubus custom seq file ops with single_open().


Finn Thain (14):
  nubus: Avoid array underflow and overflow
  nubus: Fix up header split
  nubus: Use static functions where possible
  nubus: Fix log spam
  nubus: Validate slot resource IDs
  nubus: Call proc_mkdir() not more than once per slot directory
  nubus: Remove redundant code
  nubus: Clean up whitespace
  nubus: Generalize block resource handling
  nubus: Rework /proc/bus/nubus/s/ implementation
  nubus: Rename struct nubus_dev
  nubus: Adopt standard linked list implementation
  nubus: Add expansion_type values for various Mac models
  nubus: Add support for the driver model

 arch/m68k/include/asm/macintosh.h   |   9 +-
 arch/m68k/mac/config.c  | 110 +++
 drivers/net/ethernet/8390/mac8390.c |  33 +-
 drivers/net/ethernet/cirrus/mac89x0.c   |   6 +-
 drivers/net/ethernet/natsemi/macsonic.c |  38 ++-
 drivers/nubus/Makefile  |   2 +-
 drivers/nubus/bus.c | 119 +++
 drivers/nubus/nubus.c   | 544 +---
 drivers/nubus/proc.c| 282 -
 drivers/video/fbdev/macfb.c |  10 +-
 include/linux/nubus.h   | 185 +++
 include/uapi/linux/nubus.h  |  23 --
 12 files changed, 763 insertions(+), 598 deletions(-)
 create mode 100644 drivers/nubus/bus.c

-- 
2.13.6



Re: [PATCH v2 0/4] lockdep/crossrelease: Apply crossrelease to page locks

2017-12-04 Thread Byungchul Park

On 12/5/2017 2:46 PM, Byungchul Park wrote:

On 12/5/2017 2:30 PM, Matthew Wilcox wrote:

On Mon, Dec 04, 2017 at 02:16:19PM +0900, Byungchul Park wrote:

For now, wait_for_completion() / complete() works with lockdep, add
lock_page() / unlock_page() and its family to lockdep support.

Changes from v1
  - Move lockdep_map_cross outside of page_ext to make it flexible
  - Prevent allocating lockdep_map per page by default
  - Add a boot parameter allowing the allocation for debugging

Byungchul Park (4):
   lockdep: Apply crossrelease to PG_locked locks
   lockdep: Apply lock_acquire(release) on __Set(__Clear)PageLocked
   lockdep: Move data of CONFIG_LOCKDEP_PAGELOCK from page to page_ext
   lockdep: Add a boot parameter enabling to track page locks using
 lockdep and disable it by default


I don't like the way you've structured this patch series; first adding
the lockdep map to struct page, then moving it to page_ext.


Hello,

I will make them into one patch.


I've thought it more.

Actually I did it because I thought I'd better make it into two
patches since it makes reviewers easier to review. It doesn't matter
which one I choose, but I prefer to split it.

But, if you are strongly against it, then I will follow you.

--
Thanks,
Byungchul


Re: [PATCH v2 0/4] lockdep/crossrelease: Apply crossrelease to page locks

2017-12-04 Thread Byungchul Park

On 12/5/2017 2:46 PM, Byungchul Park wrote:

On 12/5/2017 2:30 PM, Matthew Wilcox wrote:

On Mon, Dec 04, 2017 at 02:16:19PM +0900, Byungchul Park wrote:

For now, wait_for_completion() / complete() works with lockdep, add
lock_page() / unlock_page() and its family to lockdep support.

Changes from v1
  - Move lockdep_map_cross outside of page_ext to make it flexible
  - Prevent allocating lockdep_map per page by default
  - Add a boot parameter allowing the allocation for debugging

Byungchul Park (4):
   lockdep: Apply crossrelease to PG_locked locks
   lockdep: Apply lock_acquire(release) on __Set(__Clear)PageLocked
   lockdep: Move data of CONFIG_LOCKDEP_PAGELOCK from page to page_ext
   lockdep: Add a boot parameter enabling to track page locks using
 lockdep and disable it by default


I don't like the way you've structured this patch series; first adding
the lockdep map to struct page, then moving it to page_ext.


Hello,

I will make them into one patch.


I've thought it more.

Actually I did it because I thought I'd better make it into two
patches since it makes reviewers easier to review. It doesn't matter
which one I choose, but I prefer to split it.

But, if you are strongly against it, then I will follow you.

--
Thanks,
Byungchul


Re: Regression in e1000e since Kernel 4.14.3

2017-12-04 Thread Greg KH
On Tue, Dec 05, 2017 at 07:18:34AM +0100, Greg KH wrote:
> On Tue, Dec 05, 2017 at 12:47:10AM +0100, Gabriel C wrote:
> > On 04.12.2017 23:10, rwar...@gmx.de wrote:
> > 
> > > Hallo
> > > 
> > > someone and I got an regression with e1000e since kernel 4.14.3 and it 
> > > seems there is 4.14.4 on the way without a fix.
> > > 
> > > 
> > > bug report is here:
> > > 
> > > https://bugzilla.kernel.org/show_bug.cgi?id=198047
> > 
> > ( added stable and netdev to CC )
> > 
> > Yes I have a box with e1000e and it seems something at least breaks NM 
> > after 4.14.3.
> 
> Again, can people try 4.14.5-rc1?  It should be resolved there.

Oops, that would be 4.14.4-rc1.  Any why do you say above that is on the
way without a fix, did you test it?

thanks,

greg k-h


Re: Regression in e1000e since Kernel 4.14.3

2017-12-04 Thread Greg KH
On Tue, Dec 05, 2017 at 07:18:34AM +0100, Greg KH wrote:
> On Tue, Dec 05, 2017 at 12:47:10AM +0100, Gabriel C wrote:
> > On 04.12.2017 23:10, rwar...@gmx.de wrote:
> > 
> > > Hallo
> > > 
> > > someone and I got an regression with e1000e since kernel 4.14.3 and it 
> > > seems there is 4.14.4 on the way without a fix.
> > > 
> > > 
> > > bug report is here:
> > > 
> > > https://bugzilla.kernel.org/show_bug.cgi?id=198047
> > 
> > ( added stable and netdev to CC )
> > 
> > Yes I have a box with e1000e and it seems something at least breaks NM 
> > after 4.14.3.
> 
> Again, can people try 4.14.5-rc1?  It should be resolved there.

Oops, that would be 4.14.4-rc1.  Any why do you say above that is on the
way without a fix, did you test it?

thanks,

greg k-h


Re: PROBLEM: Asus C201 video mode problems on HDMI hotplug (regression)

2017-12-04 Thread Nick Bowler
On 2017-12-04 13:33 -0500, Nick Bowler wrote:
> On 2017-12-04 10:04 +, Jose Abreu wrote:
> > Hmmm, my first thought was that audio is being configured first
> > because of the phy lock wait time, I've seen this happening before.
> >
> > Lets try this:
> > - Disable all alsa clients (e.g. pulseaudio, ...) so that no one
> > tries to configure audio.
> > - Plug out/in the cable until the issue appears
> > - When the issue appears use aplay to play audio through the HDMI
> > output
> > - Repeat several times with different audio rates and with no
> > resample (you can use the plughw interface in aplay).
> 
> OK, I will give it a try later this evening.

Using the above sequence on unpatched 4.15-rc1 it seems there is no
sound when starting audio output after the pink bar is visible.

However I am not confident of the results here, restarting aplay
with different sample rates (or even restarting with the same rate)
is causing some weird effects on my setup so I want to check the test
setup with some different source devices.

Cheers,
  Nick


Re: PROBLEM: Asus C201 video mode problems on HDMI hotplug (regression)

2017-12-04 Thread Nick Bowler
On 2017-12-04 13:33 -0500, Nick Bowler wrote:
> On 2017-12-04 10:04 +, Jose Abreu wrote:
> > Hmmm, my first thought was that audio is being configured first
> > because of the phy lock wait time, I've seen this happening before.
> >
> > Lets try this:
> > - Disable all alsa clients (e.g. pulseaudio, ...) so that no one
> > tries to configure audio.
> > - Plug out/in the cable until the issue appears
> > - When the issue appears use aplay to play audio through the HDMI
> > output
> > - Repeat several times with different audio rates and with no
> > resample (you can use the plughw interface in aplay).
> 
> OK, I will give it a try later this evening.

Using the above sequence on unpatched 4.15-rc1 it seems there is no
sound when starting audio output after the pink bar is visible.

However I am not confident of the results here, restarting aplay
with different sample rates (or even restarting with the same rate)
is causing some weird effects on my setup so I want to check the test
setup with some different source devices.

Cheers,
  Nick


Re: Regression in e1000e since Kernel 4.14.3

2017-12-04 Thread Greg KH
On Tue, Dec 05, 2017 at 12:47:10AM +0100, Gabriel C wrote:
> On 04.12.2017 23:10, rwar...@gmx.de wrote:
> 
> > Hallo
> > 
> > someone and I got an regression with e1000e since kernel 4.14.3 and it 
> > seems there is 4.14.4 on the way without a fix.
> > 
> > 
> > bug report is here:
> > 
> > https://bugzilla.kernel.org/show_bug.cgi?id=198047
> 
> ( added stable and netdev to CC )
> 
> Yes I have a box with e1000e and it seems something at least breaks NM after 
> 4.14.3.

Again, can people try 4.14.5-rc1?  It should be resolved there.

thanks,

greg k-h


Re: Regression in e1000e since Kernel 4.14.3

2017-12-04 Thread Greg KH
On Tue, Dec 05, 2017 at 12:47:10AM +0100, Gabriel C wrote:
> On 04.12.2017 23:10, rwar...@gmx.de wrote:
> 
> > Hallo
> > 
> > someone and I got an regression with e1000e since kernel 4.14.3 and it 
> > seems there is 4.14.4 on the way without a fix.
> > 
> > 
> > bug report is here:
> > 
> > https://bugzilla.kernel.org/show_bug.cgi?id=198047
> 
> ( added stable and netdev to CC )
> 
> Yes I have a box with e1000e and it seems something at least breaks NM after 
> 4.14.3.

Again, can people try 4.14.5-rc1?  It should be resolved there.

thanks,

greg k-h


Re: [PATCH] thermal: tegra: delete unneeded of_node_put

2017-12-04 Thread Julia Lawall


On Mon, 4 Dec 2017, Eduardo Valentin wrote:

> On Mon, Jul 17, 2017 at 04:42:38PM +0200, Julia Lawall wrote:
> >
> >
> > On Mon, 17 Jul 2017, Jon Hunter wrote:
> >
> > >
> > > On 15/07/17 09:42, Julia Lawall wrote:
> > > > Device node iterators perform an of_node_put on each iteration, so 
> > > > putting
> > > > an of_node_put before a continue results in a double put.
> > > >
> > > > The semantic match that finds this problem is as follows
> > > > (http://coccinelle.lip6.fr):
> > > >
> > > > // 
> > > > @@
> > > > expression e1;
> > > > local idexpression child;
> > > > iterator name for_each_child_of_node;
> > > > @@
> > > >
> > > >  for_each_child_of_node(e1,child) {
> > > >... when != of_node_get(child)
> > > > *  of_node_put(child);
> > > >...
> > > > *  continue;
> > > > }
> > > > // 
> > > >
> > > > Furthermore, the call to thermal_of_cooling_device_register immediately
> > > > calls __thermal_cooling_device_register with the same arguments.  The
> > > > latter function stores the device node argument, which is the second
> > > > argument of for_each_child_of_node, in the returned 
> > > > thermal_cooling_device
> > > > structure.  This returned structure is then stored in the cdev field of
> > > > stc.  Thus it seems that the second argument of for_each_child_of_node
> > > > escapes the scope of the for_each_child_of_node, so an explicit 
> > > > of_node_get
> > > > on success of thermal_of_cooling_device_register is also needed.
> > > >
> > > > Signed-off-by: Julia Lawall 
> > > >
> > > > ---
> > > >  drivers/thermal/tegra/soctherm.c |2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/thermal/tegra/soctherm.c 
> > > > b/drivers/thermal/tegra/soctherm.c
> > > > index 7d2db23..10f4fdd 100644
> > > > --- a/drivers/thermal/tegra/soctherm.c
> > > > +++ b/drivers/thermal/tegra/soctherm.c
> > > > @@ -1014,7 +1014,6 @@ static void soctherm_init_hw_throt_cdev(struct 
> > > > platform_device *pdev)
> > > > tcd = thermal_of_cooling_device_register(np_stcc,
> > > >  (char *)name, 
> > > > ts,
> > > >  
> > > > _cooling_ops);
> > > > -   of_node_put(np_stcc);
> > > > if (IS_ERR_OR_NULL(tcd)) {
> > > > dev_err(dev,
> > > > "throttle-cfg: %s: failed to register 
> > > > cooling device\n",
> > > > @@ -1022,6 +1021,7 @@ static void soctherm_init_hw_throt_cdev(struct 
> > > > platform_device *pdev)
> > > > continue;
> > > > }
> > > >
> > > > +   of_node_get(np_stcc);
> > > > stc->cdev = tcd;
> > > > stc->init = true;
> > > > }
> > >
> > > Thanks for fixing this. However, I am wondering if it is better for the
> > > 'of_node_get' to be placed within the
> > > thermal_of_cooling_device_register() function as it seems a bit odd if
> > > the caller needs to know that this is being stored for later use.
> > >
> > > Also, taking a quick look, I see a couple other drivers calling
> > > thermal_of_cooling_device_register() and they are also not calling
> > > of_node_get on success. So it maybe easier to fix placing it in the
> > > thermal_of_cooling_device_register() function.
> >
> > I'm not an expert, but I had the impression that from some call sites, the
> > get would have been done already, because the argument is already stored
> > in some structure.  I can check more exhaustively.
>
> Julia, I agree with Jon here. Better if fixed in the API itself. Are you
> still planning on sending a fix for this?

This has fallen off my stack, and I'mnot sure that Ican get to it in the
short term.

julia


Re: [PATCH] thermal: tegra: delete unneeded of_node_put

2017-12-04 Thread Julia Lawall


On Mon, 4 Dec 2017, Eduardo Valentin wrote:

> On Mon, Jul 17, 2017 at 04:42:38PM +0200, Julia Lawall wrote:
> >
> >
> > On Mon, 17 Jul 2017, Jon Hunter wrote:
> >
> > >
> > > On 15/07/17 09:42, Julia Lawall wrote:
> > > > Device node iterators perform an of_node_put on each iteration, so 
> > > > putting
> > > > an of_node_put before a continue results in a double put.
> > > >
> > > > The semantic match that finds this problem is as follows
> > > > (http://coccinelle.lip6.fr):
> > > >
> > > > // 
> > > > @@
> > > > expression e1;
> > > > local idexpression child;
> > > > iterator name for_each_child_of_node;
> > > > @@
> > > >
> > > >  for_each_child_of_node(e1,child) {
> > > >... when != of_node_get(child)
> > > > *  of_node_put(child);
> > > >...
> > > > *  continue;
> > > > }
> > > > // 
> > > >
> > > > Furthermore, the call to thermal_of_cooling_device_register immediately
> > > > calls __thermal_cooling_device_register with the same arguments.  The
> > > > latter function stores the device node argument, which is the second
> > > > argument of for_each_child_of_node, in the returned 
> > > > thermal_cooling_device
> > > > structure.  This returned structure is then stored in the cdev field of
> > > > stc.  Thus it seems that the second argument of for_each_child_of_node
> > > > escapes the scope of the for_each_child_of_node, so an explicit 
> > > > of_node_get
> > > > on success of thermal_of_cooling_device_register is also needed.
> > > >
> > > > Signed-off-by: Julia Lawall 
> > > >
> > > > ---
> > > >  drivers/thermal/tegra/soctherm.c |2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/thermal/tegra/soctherm.c 
> > > > b/drivers/thermal/tegra/soctherm.c
> > > > index 7d2db23..10f4fdd 100644
> > > > --- a/drivers/thermal/tegra/soctherm.c
> > > > +++ b/drivers/thermal/tegra/soctherm.c
> > > > @@ -1014,7 +1014,6 @@ static void soctherm_init_hw_throt_cdev(struct 
> > > > platform_device *pdev)
> > > > tcd = thermal_of_cooling_device_register(np_stcc,
> > > >  (char *)name, 
> > > > ts,
> > > >  
> > > > _cooling_ops);
> > > > -   of_node_put(np_stcc);
> > > > if (IS_ERR_OR_NULL(tcd)) {
> > > > dev_err(dev,
> > > > "throttle-cfg: %s: failed to register 
> > > > cooling device\n",
> > > > @@ -1022,6 +1021,7 @@ static void soctherm_init_hw_throt_cdev(struct 
> > > > platform_device *pdev)
> > > > continue;
> > > > }
> > > >
> > > > +   of_node_get(np_stcc);
> > > > stc->cdev = tcd;
> > > > stc->init = true;
> > > > }
> > >
> > > Thanks for fixing this. However, I am wondering if it is better for the
> > > 'of_node_get' to be placed within the
> > > thermal_of_cooling_device_register() function as it seems a bit odd if
> > > the caller needs to know that this is being stored for later use.
> > >
> > > Also, taking a quick look, I see a couple other drivers calling
> > > thermal_of_cooling_device_register() and they are also not calling
> > > of_node_get on success. So it maybe easier to fix placing it in the
> > > thermal_of_cooling_device_register() function.
> >
> > I'm not an expert, but I had the impression that from some call sites, the
> > get would have been done already, because the argument is already stored
> > in some structure.  I can check more exhaustively.
>
> Julia, I agree with Jon here. Better if fixed in the API itself. Are you
> still planning on sending a fix for this?

This has fallen off my stack, and I'mnot sure that Ican get to it in the
short term.

julia


[PATCH v6 01/11] perf util: Define a structure for per-thread shadow stats

2017-12-04 Thread Jin Yao
Perf has a set of static variables to record the runtime shadow
metrics stats.

While if we want to record the runtime shadow stats for per-thread,
it will be the limitation. This patch creates a structure and the
next patches will use this structure to update the runtime shadow
stats for per-thread.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 11 ---
 tools/perf/util/stat.h| 43 ++-
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 57ec225..93aac27 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -9,17 +9,6 @@
 #include "expr.h"
 #include "metricgroup.h"
 
-enum {
-   CTX_BIT_USER= 1 << 0,
-   CTX_BIT_KERNEL  = 1 << 1,
-   CTX_BIT_HV  = 1 << 2,
-   CTX_BIT_HOST= 1 << 3,
-   CTX_BIT_IDLE= 1 << 4,
-   CTX_BIT_MAX = 1 << 5,
-};
-
-#define NUM_CTX CTX_BIT_MAX
-
 /*
  * AGGR_GLOBAL: Use CPU 0
  * AGGR_SOCKET: Use first CPU of socket
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index eefca5c..c685c41 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include "xyarray.h"
+#include "rblist.h"
 
 struct stats
 {
@@ -43,6 +44,47 @@ enum aggr_mode {
AGGR_UNSET,
 };
 
+enum {
+   CTX_BIT_USER= 1 << 0,
+   CTX_BIT_KERNEL  = 1 << 1,
+   CTX_BIT_HV  = 1 << 2,
+   CTX_BIT_HOST= 1 << 3,
+   CTX_BIT_IDLE= 1 << 4,
+   CTX_BIT_MAX = 1 << 5,
+};
+
+#define NUM_CTX CTX_BIT_MAX
+
+enum stat_type {
+   STAT_NONE = 0,
+   STAT_NSECS,
+   STAT_CYCLES,
+   STAT_STALLED_CYCLES_FRONT,
+   STAT_STALLED_CYCLES_BACK,
+   STAT_BRANCHES,
+   STAT_CACHEREFS,
+   STAT_L1_DCACHE,
+   STAT_L1_ICACHE,
+   STAT_LL_CACHE,
+   STAT_ITLB_CACHE,
+   STAT_DTLB_CACHE,
+   STAT_CYCLES_IN_TX,
+   STAT_TRANSACTION,
+   STAT_ELISION,
+   STAT_TOPDOWN_TOTAL_SLOTS,
+   STAT_TOPDOWN_SLOTS_ISSUED,
+   STAT_TOPDOWN_SLOTS_RETIRED,
+   STAT_TOPDOWN_FETCH_BUBBLES,
+   STAT_TOPDOWN_RECOVERY_BUBBLES,
+   STAT_SMI_NUM,
+   STAT_APERF,
+   STAT_MAX
+};
+
+struct runtime_stat {
+   struct rblist value_list;
+};
+
 struct perf_stat_config {
enum aggr_mode  aggr_mode;
boolscale;
@@ -92,7 +134,6 @@ struct perf_stat_output_ctx {
bool force_header;
 };
 
-struct rblist;
 void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
   double avg, int cpu,
   struct perf_stat_output_ctx *out,
-- 
2.7.4



[PATCH v6 04/11] perf util: Update per-thread shadow stats

2017-12-04 Thread Jin Yao
The functions perf_stat__update_shadow_stats() is called
to update the shadow stats on a set of static variables.

But the static variables are the limitations to be extended
to support per-thread shadow stats.

This patch lets the perf_stat__update_shadow_stats() support
to update the shadow stats on a input parameter 'stat' and
uses update_runtime_stat() to update the stats. It will not
directly update the static variables as before.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-script.c   |  3 +-
 tools/perf/builtin-stat.c |  3 +-
 tools/perf/util/stat-shadow.c | 86 +--
 tools/perf/util/stat.c|  8 ++--
 tools/perf/util/stat.h|  2 +-
 5 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 39d8b55..81b3950 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1548,7 +1548,8 @@ static void perf_sample__fprint_metric(struct perf_script 
*script,
val = sample->period * evsel->scale;
perf_stat__update_shadow_stats(evsel,
   val,
-  sample->cpu);
+  sample->cpu,
+  _stat);
evsel_script(evsel)->val = val;
if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
for_each_group_member (ev2, evsel->leader) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a027b47..3f4a2c2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1214,7 +1214,8 @@ static void aggr_update_shadow(void)
val += perf_counts(counter->counts, cpu, 
0)->val;
}
perf_stat__update_shadow_stats(counter, val,
-  
first_shadow_cpu(counter, id));
+   first_shadow_cpu(counter, id),
+   _stat);
}
}
 }
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index e60c321..11c921d 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -116,19 +116,29 @@ static void saved_value_delete(struct rblist *rblist 
__maybe_unused,
 
 static struct saved_value *saved_value_lookup(struct perf_evsel *evsel,
  int cpu,
- bool create)
+ bool create,
+ enum stat_type type,
+ int ctx,
+ struct runtime_stat *stat)
 {
+   struct rblist *rblist;
struct rb_node *nd;
struct saved_value dm = {
.cpu = cpu,
.evsel = evsel,
+   .type = type,
+   .ctx = ctx,
+   .stat = stat,
};
-   nd = rblist__find(_saved_values, );
+
+   rblist = >value_list;
+
+   nd = rblist__find(rblist, );
if (nd)
return container_of(nd, struct saved_value, rb_node);
if (create) {
-   rblist__add_node(_saved_values, );
-   nd = rblist__find(_saved_values, );
+   rblist__add_node(rblist, );
+   nd = rblist__find(rblist, );
if (nd)
return container_of(nd, struct saved_value, rb_node);
}
@@ -217,13 +227,24 @@ void perf_stat__reset_shadow_stats(void)
}
 }
 
+static void update_runtime_stat(struct runtime_stat *stat,
+   enum stat_type type,
+   int ctx, int cpu, u64 count)
+{
+   struct saved_value *v = saved_value_lookup(NULL, cpu, true,
+  type, ctx, stat);
+
+   if (v)
+   update_stats(>stats, count);
+}
+
 /*
  * Update various tracking values we maintain to print
  * more semantic information such as miss/hit ratios,
  * instruction rates, etc:
  */
 void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
-   int cpu)
+   int cpu, struct runtime_stat *stat)
 {
int ctx = evsel_context(counter);
 
@@ -231,50 +252,58 @@ void perf_stat__update_shadow_stats(struct perf_evsel 
*counter, u64 count,
 
if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) ||
perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK))
-   update_stats(_nsecs_stats[cpu], count);
+   update_runtime_stat(stat, STAT_NSECS, 0, cpu, count);
else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-   update_stats(_cycles_stats[ctx][cpu], count);
+   

[PATCH v6 01/11] perf util: Define a structure for per-thread shadow stats

2017-12-04 Thread Jin Yao
Perf has a set of static variables to record the runtime shadow
metrics stats.

While if we want to record the runtime shadow stats for per-thread,
it will be the limitation. This patch creates a structure and the
next patches will use this structure to update the runtime shadow
stats for per-thread.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 11 ---
 tools/perf/util/stat.h| 43 ++-
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 57ec225..93aac27 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -9,17 +9,6 @@
 #include "expr.h"
 #include "metricgroup.h"
 
-enum {
-   CTX_BIT_USER= 1 << 0,
-   CTX_BIT_KERNEL  = 1 << 1,
-   CTX_BIT_HV  = 1 << 2,
-   CTX_BIT_HOST= 1 << 3,
-   CTX_BIT_IDLE= 1 << 4,
-   CTX_BIT_MAX = 1 << 5,
-};
-
-#define NUM_CTX CTX_BIT_MAX
-
 /*
  * AGGR_GLOBAL: Use CPU 0
  * AGGR_SOCKET: Use first CPU of socket
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index eefca5c..c685c41 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include "xyarray.h"
+#include "rblist.h"
 
 struct stats
 {
@@ -43,6 +44,47 @@ enum aggr_mode {
AGGR_UNSET,
 };
 
+enum {
+   CTX_BIT_USER= 1 << 0,
+   CTX_BIT_KERNEL  = 1 << 1,
+   CTX_BIT_HV  = 1 << 2,
+   CTX_BIT_HOST= 1 << 3,
+   CTX_BIT_IDLE= 1 << 4,
+   CTX_BIT_MAX = 1 << 5,
+};
+
+#define NUM_CTX CTX_BIT_MAX
+
+enum stat_type {
+   STAT_NONE = 0,
+   STAT_NSECS,
+   STAT_CYCLES,
+   STAT_STALLED_CYCLES_FRONT,
+   STAT_STALLED_CYCLES_BACK,
+   STAT_BRANCHES,
+   STAT_CACHEREFS,
+   STAT_L1_DCACHE,
+   STAT_L1_ICACHE,
+   STAT_LL_CACHE,
+   STAT_ITLB_CACHE,
+   STAT_DTLB_CACHE,
+   STAT_CYCLES_IN_TX,
+   STAT_TRANSACTION,
+   STAT_ELISION,
+   STAT_TOPDOWN_TOTAL_SLOTS,
+   STAT_TOPDOWN_SLOTS_ISSUED,
+   STAT_TOPDOWN_SLOTS_RETIRED,
+   STAT_TOPDOWN_FETCH_BUBBLES,
+   STAT_TOPDOWN_RECOVERY_BUBBLES,
+   STAT_SMI_NUM,
+   STAT_APERF,
+   STAT_MAX
+};
+
+struct runtime_stat {
+   struct rblist value_list;
+};
+
 struct perf_stat_config {
enum aggr_mode  aggr_mode;
boolscale;
@@ -92,7 +134,6 @@ struct perf_stat_output_ctx {
bool force_header;
 };
 
-struct rblist;
 void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
   double avg, int cpu,
   struct perf_stat_output_ctx *out,
-- 
2.7.4



[PATCH v6 04/11] perf util: Update per-thread shadow stats

2017-12-04 Thread Jin Yao
The functions perf_stat__update_shadow_stats() is called
to update the shadow stats on a set of static variables.

But the static variables are the limitations to be extended
to support per-thread shadow stats.

This patch lets the perf_stat__update_shadow_stats() support
to update the shadow stats on a input parameter 'stat' and
uses update_runtime_stat() to update the stats. It will not
directly update the static variables as before.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-script.c   |  3 +-
 tools/perf/builtin-stat.c |  3 +-
 tools/perf/util/stat-shadow.c | 86 +--
 tools/perf/util/stat.c|  8 ++--
 tools/perf/util/stat.h|  2 +-
 5 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 39d8b55..81b3950 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1548,7 +1548,8 @@ static void perf_sample__fprint_metric(struct perf_script 
*script,
val = sample->period * evsel->scale;
perf_stat__update_shadow_stats(evsel,
   val,
-  sample->cpu);
+  sample->cpu,
+  _stat);
evsel_script(evsel)->val = val;
if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
for_each_group_member (ev2, evsel->leader) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a027b47..3f4a2c2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1214,7 +1214,8 @@ static void aggr_update_shadow(void)
val += perf_counts(counter->counts, cpu, 
0)->val;
}
perf_stat__update_shadow_stats(counter, val,
-  
first_shadow_cpu(counter, id));
+   first_shadow_cpu(counter, id),
+   _stat);
}
}
 }
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index e60c321..11c921d 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -116,19 +116,29 @@ static void saved_value_delete(struct rblist *rblist 
__maybe_unused,
 
 static struct saved_value *saved_value_lookup(struct perf_evsel *evsel,
  int cpu,
- bool create)
+ bool create,
+ enum stat_type type,
+ int ctx,
+ struct runtime_stat *stat)
 {
+   struct rblist *rblist;
struct rb_node *nd;
struct saved_value dm = {
.cpu = cpu,
.evsel = evsel,
+   .type = type,
+   .ctx = ctx,
+   .stat = stat,
};
-   nd = rblist__find(_saved_values, );
+
+   rblist = >value_list;
+
+   nd = rblist__find(rblist, );
if (nd)
return container_of(nd, struct saved_value, rb_node);
if (create) {
-   rblist__add_node(_saved_values, );
-   nd = rblist__find(_saved_values, );
+   rblist__add_node(rblist, );
+   nd = rblist__find(rblist, );
if (nd)
return container_of(nd, struct saved_value, rb_node);
}
@@ -217,13 +227,24 @@ void perf_stat__reset_shadow_stats(void)
}
 }
 
+static void update_runtime_stat(struct runtime_stat *stat,
+   enum stat_type type,
+   int ctx, int cpu, u64 count)
+{
+   struct saved_value *v = saved_value_lookup(NULL, cpu, true,
+  type, ctx, stat);
+
+   if (v)
+   update_stats(>stats, count);
+}
+
 /*
  * Update various tracking values we maintain to print
  * more semantic information such as miss/hit ratios,
  * instruction rates, etc:
  */
 void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
-   int cpu)
+   int cpu, struct runtime_stat *stat)
 {
int ctx = evsel_context(counter);
 
@@ -231,50 +252,58 @@ void perf_stat__update_shadow_stats(struct perf_evsel 
*counter, u64 count,
 
if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) ||
perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK))
-   update_stats(_nsecs_stats[cpu], count);
+   update_runtime_stat(stat, STAT_NSECS, 0, cpu, count);
else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-   update_stats(_cycles_stats[ctx][cpu], count);
+   update_runtime_stat(stat, 

[PATCH v6 02/11] perf stat: Extend rbtree to support per-thread shadow stats

2017-12-04 Thread Jin Yao
Previously the rbtree was used to link generic metrics.

This patches adds new ctx/type/stat into rbtree keys because we
will use this rbtree to maintain shadow metrics to replace original
a couple of static arrays for supporting per-thread shadow stats.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 93aac27..528be3e 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -45,7 +45,10 @@ struct stats walltime_nsecs_stats;
 struct saved_value {
struct rb_node rb_node;
struct perf_evsel *evsel;
+   enum stat_type type;
+   int ctx;
int cpu;
+   struct runtime_stat *stat;
struct stats stats;
 };
 
@@ -58,6 +61,30 @@ static int saved_value_cmp(struct rb_node *rb_node, const 
void *entry)
 
if (a->cpu != b->cpu)
return a->cpu - b->cpu;
+
+   /*
+* Previously the rbtree was used to link generic metrics.
+* The keys were evsel/cpu. Now the rbtree is extended to support
+* per-thread shadow stats. For shadow stats case, the keys
+* are cpu/type/ctx/stat (evsel is NULL). For generic metrics
+* case, the keys are still evsel/cpu (type/ctx/stat are 0 or NULL).
+*/
+   if (a->type != b->type)
+   return a->type - b->type;
+
+   if (a->ctx != b->ctx)
+   return a->ctx - b->ctx;
+
+   if (a->evsel == NULL && b->evsel == NULL) {
+   if (a->stat == b->stat)
+   return 0;
+
+   if ((char *)a->stat < (char *)b->stat)
+   return -1;
+
+   return 1;
+   }
+
if (a->evsel == b->evsel)
return 0;
if ((char *)a->evsel < (char *)b->evsel)
-- 
2.7.4



[PATCH v6 05/11] perf util: Print per-thread shadow stats

2017-12-04 Thread Jin Yao
The function perf_stat__print_shadow_statss() is called
to print the shadow stats on a set of static variables.

But the static variables are the limitations to support
per-thread shadow stats.

This patch lets the perf_stat__print_shadow_stats() support
to print the shadow stats from a input parameter 'stat'.

It will not directly get value from static variable. Instead,
it now uses runtime_stat_avg() and runtime_stat_n() to get and
compute the values.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-script.c   |   3 +-
 tools/perf/builtin-stat.c |  24 +++--
 tools/perf/util/stat-shadow.c | 209 ++
 tools/perf/util/stat.h|   3 +-
 4 files changed, 152 insertions(+), 87 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 81b3950..fac6f05 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1557,7 +1557,8 @@ static void perf_sample__fprint_metric(struct perf_script 
*script,
  evsel_script(ev2)->val,
  sample->cpu,
  ,
- NULL);
+ NULL,
+ _stat);
}
evsel_script(evsel->leader)->gnum = 0;
}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3f4a2c2..1edc082 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1097,7 +1097,8 @@ static void abs_printout(int id, int nr, struct 
perf_evsel *evsel, double avg)
 }
 
 static void printout(int id, int nr, struct perf_evsel *counter, double uval,
-char *prefix, u64 run, u64 ena, double noise)
+char *prefix, u64 run, u64 ena, double noise,
+struct runtime_stat *stat)
 {
struct perf_stat_output_ctx out;
struct outstate os = {
@@ -1190,7 +1191,8 @@ static void printout(int id, int nr, struct perf_evsel 
*counter, double uval,
 
perf_stat__print_shadow_stats(counter, uval,
first_shadow_cpu(counter, id),
-   , _events);
+   , _events,
+   stat);
if (!csv_output && !metric_only) {
print_noise(counter, noise);
print_running(run, ena);
@@ -1335,7 +1337,8 @@ static void print_aggr(char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(id, nr, counter, uval, prefix, run, ena, 1.0);
+   printout(id, nr, counter, uval, prefix, run, ena, 1.0,
+_stat);
if (!metric_only)
fputc('\n', output);
}
@@ -1365,7 +1368,8 @@ static void print_aggr_thread(struct perf_evsel *counter, 
char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(thread, 0, counter, uval, prefix, run, ena, 1.0);
+   printout(thread, 0, counter, uval, prefix, run, ena, 1.0,
+_stat);
fputc('\n', output);
}
 }
@@ -1402,7 +1406,8 @@ static void print_counter_aggr(struct perf_evsel 
*counter, char *prefix)
fprintf(output, "%s", prefix);
 
uval = cd.avg * counter->scale;
-   printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, 
cd.avg);
+   printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
+cd.avg, _stat);
if (!metric_only)
fprintf(output, "\n");
 }
@@ -1441,7 +1446,8 @@ static void print_counter(struct perf_evsel *counter, 
char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0);
+   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+_stat);
 
fputc('\n', output);
}
@@ -1473,7 +1479,8 @@ static void print_no_aggr_metric(char *prefix)
run = perf_counts(counter->counts, cpu, 0)->run;
 
uval = val * counter->scale;
-   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0);
+   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+_stat);
}
fputc('\n', stat_config.output);
}
@@ -1529,7 +1536,8 @@ static void print_metric_headers(const char *prefix, bool 
no_indent)
perf_stat__print_shadow_stats(counter, 0,
   

[PATCH v6 06/11] perf util: Remove a set of shadow stats static variables

2017-12-04 Thread Jin Yao
In previous patches, we have reconstructed the code and let
it not access the static variables directly.

This patch removes these static variables.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 68 ++-
 tools/perf/util/stat.h|  1 +
 2 files changed, 16 insertions(+), 53 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 0d34d5e..3b929fb 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -16,28 +16,6 @@
  * AGGR_NONE: Use matching CPU
  * AGGR_THREAD: Not supported?
  */
-static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
-static struct stats runtime_cycles_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_stalled_cycles_front_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_stalled_cycles_back_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_branches_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_cacherefs_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_l1_dcache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_l1_icache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_ll_cache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_itlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_total_slots[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_smi_num_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_aperf_stats[NUM_CTX][MAX_NR_CPUS];
-static struct rblist runtime_saved_values;
 static bool have_frontend_stalled;
 
 struct runtime_stat rt_stat;
@@ -163,10 +141,6 @@ void runtime_stat__exit(struct runtime_stat *stat)
 void perf_stat__init_shadow_stats(void)
 {
have_frontend_stalled = pmu_have_event("cpu", 
"stalled-cycles-frontend");
-   rblist__init(_saved_values);
-   runtime_saved_values.node_cmp = saved_value_cmp;
-   runtime_saved_values.node_new = saved_value_new;
-   runtime_saved_values.node_delete = saved_value_delete;
runtime_stat__init(_stat);
 }
 
@@ -188,36 +162,13 @@ static int evsel_context(struct perf_evsel *evsel)
return ctx;
 }
 
-void perf_stat__reset_shadow_stats(void)
+static void reset_stat(struct runtime_stat *stat)
 {
+   struct rblist *rblist;
struct rb_node *pos, *next;
 
-   memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats));
-   memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
-   memset(runtime_stalled_cycles_front_stats, 0, 
sizeof(runtime_stalled_cycles_front_stats));
-   memset(runtime_stalled_cycles_back_stats, 0, 
sizeof(runtime_stalled_cycles_back_stats));
-   memset(runtime_branches_stats, 0, sizeof(runtime_branches_stats));
-   memset(runtime_cacherefs_stats, 0, sizeof(runtime_cacherefs_stats));
-   memset(runtime_l1_dcache_stats, 0, sizeof(runtime_l1_dcache_stats));
-   memset(runtime_l1_icache_stats, 0, sizeof(runtime_l1_icache_stats));
-   memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
-   memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
-   memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
-   memset(runtime_cycles_in_tx_stats, 0,
-   sizeof(runtime_cycles_in_tx_stats));
-   memset(runtime_transaction_stats, 0,
-   sizeof(runtime_transaction_stats));
-   memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
-   memset(_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
-   memset(runtime_topdown_total_slots, 0, 
sizeof(runtime_topdown_total_slots));
-   memset(runtime_topdown_slots_retired, 0, 
sizeof(runtime_topdown_slots_retired));
-   memset(runtime_topdown_slots_issued, 0, 
sizeof(runtime_topdown_slots_issued));
-   memset(runtime_topdown_fetch_bubbles, 0, 
sizeof(runtime_topdown_fetch_bubbles));
-   memset(runtime_topdown_recovery_bubbles, 0, 
sizeof(runtime_topdown_recovery_bubbles));
-   memset(runtime_smi_num_stats, 0, sizeof(runtime_smi_num_stats));
-   memset(runtime_aperf_stats, 0, sizeof(runtime_aperf_stats));
-
-   next = rb_first(_saved_values.entries);
+   rblist = >value_list;
+   next = rb_first(>entries);
while (next) {
pos = next;
next = rb_next(pos);
@@ -227,6 +178,17 @@ void 

[PATCH v6 02/11] perf stat: Extend rbtree to support per-thread shadow stats

2017-12-04 Thread Jin Yao
Previously the rbtree was used to link generic metrics.

This patches adds new ctx/type/stat into rbtree keys because we
will use this rbtree to maintain shadow metrics to replace original
a couple of static arrays for supporting per-thread shadow stats.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 93aac27..528be3e 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -45,7 +45,10 @@ struct stats walltime_nsecs_stats;
 struct saved_value {
struct rb_node rb_node;
struct perf_evsel *evsel;
+   enum stat_type type;
+   int ctx;
int cpu;
+   struct runtime_stat *stat;
struct stats stats;
 };
 
@@ -58,6 +61,30 @@ static int saved_value_cmp(struct rb_node *rb_node, const 
void *entry)
 
if (a->cpu != b->cpu)
return a->cpu - b->cpu;
+
+   /*
+* Previously the rbtree was used to link generic metrics.
+* The keys were evsel/cpu. Now the rbtree is extended to support
+* per-thread shadow stats. For shadow stats case, the keys
+* are cpu/type/ctx/stat (evsel is NULL). For generic metrics
+* case, the keys are still evsel/cpu (type/ctx/stat are 0 or NULL).
+*/
+   if (a->type != b->type)
+   return a->type - b->type;
+
+   if (a->ctx != b->ctx)
+   return a->ctx - b->ctx;
+
+   if (a->evsel == NULL && b->evsel == NULL) {
+   if (a->stat == b->stat)
+   return 0;
+
+   if ((char *)a->stat < (char *)b->stat)
+   return -1;
+
+   return 1;
+   }
+
if (a->evsel == b->evsel)
return 0;
if ((char *)a->evsel < (char *)b->evsel)
-- 
2.7.4



[PATCH v6 05/11] perf util: Print per-thread shadow stats

2017-12-04 Thread Jin Yao
The function perf_stat__print_shadow_statss() is called
to print the shadow stats on a set of static variables.

But the static variables are the limitations to support
per-thread shadow stats.

This patch lets the perf_stat__print_shadow_stats() support
to print the shadow stats from a input parameter 'stat'.

It will not directly get value from static variable. Instead,
it now uses runtime_stat_avg() and runtime_stat_n() to get and
compute the values.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-script.c   |   3 +-
 tools/perf/builtin-stat.c |  24 +++--
 tools/perf/util/stat-shadow.c | 209 ++
 tools/perf/util/stat.h|   3 +-
 4 files changed, 152 insertions(+), 87 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 81b3950..fac6f05 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1557,7 +1557,8 @@ static void perf_sample__fprint_metric(struct perf_script 
*script,
  evsel_script(ev2)->val,
  sample->cpu,
  ,
- NULL);
+ NULL,
+ _stat);
}
evsel_script(evsel->leader)->gnum = 0;
}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3f4a2c2..1edc082 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1097,7 +1097,8 @@ static void abs_printout(int id, int nr, struct 
perf_evsel *evsel, double avg)
 }
 
 static void printout(int id, int nr, struct perf_evsel *counter, double uval,
-char *prefix, u64 run, u64 ena, double noise)
+char *prefix, u64 run, u64 ena, double noise,
+struct runtime_stat *stat)
 {
struct perf_stat_output_ctx out;
struct outstate os = {
@@ -1190,7 +1191,8 @@ static void printout(int id, int nr, struct perf_evsel 
*counter, double uval,
 
perf_stat__print_shadow_stats(counter, uval,
first_shadow_cpu(counter, id),
-   , _events);
+   , _events,
+   stat);
if (!csv_output && !metric_only) {
print_noise(counter, noise);
print_running(run, ena);
@@ -1335,7 +1337,8 @@ static void print_aggr(char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(id, nr, counter, uval, prefix, run, ena, 1.0);
+   printout(id, nr, counter, uval, prefix, run, ena, 1.0,
+_stat);
if (!metric_only)
fputc('\n', output);
}
@@ -1365,7 +1368,8 @@ static void print_aggr_thread(struct perf_evsel *counter, 
char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(thread, 0, counter, uval, prefix, run, ena, 1.0);
+   printout(thread, 0, counter, uval, prefix, run, ena, 1.0,
+_stat);
fputc('\n', output);
}
 }
@@ -1402,7 +1406,8 @@ static void print_counter_aggr(struct perf_evsel 
*counter, char *prefix)
fprintf(output, "%s", prefix);
 
uval = cd.avg * counter->scale;
-   printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, 
cd.avg);
+   printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
+cd.avg, _stat);
if (!metric_only)
fprintf(output, "\n");
 }
@@ -1441,7 +1446,8 @@ static void print_counter(struct perf_evsel *counter, 
char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0);
+   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+_stat);
 
fputc('\n', output);
}
@@ -1473,7 +1479,8 @@ static void print_no_aggr_metric(char *prefix)
run = perf_counts(counter->counts, cpu, 0)->run;
 
uval = val * counter->scale;
-   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0);
+   printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+_stat);
}
fputc('\n', stat_config.output);
}
@@ -1529,7 +1536,8 @@ static void print_metric_headers(const char *prefix, bool 
no_indent)
perf_stat__print_shadow_stats(counter, 0,

[PATCH v6 06/11] perf util: Remove a set of shadow stats static variables

2017-12-04 Thread Jin Yao
In previous patches, we have reconstructed the code and let
it not access the static variables directly.

This patch removes these static variables.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 68 ++-
 tools/perf/util/stat.h|  1 +
 2 files changed, 16 insertions(+), 53 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 0d34d5e..3b929fb 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -16,28 +16,6 @@
  * AGGR_NONE: Use matching CPU
  * AGGR_THREAD: Not supported?
  */
-static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
-static struct stats runtime_cycles_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_stalled_cycles_front_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_stalled_cycles_back_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_branches_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_cacherefs_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_l1_dcache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_l1_icache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_ll_cache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_itlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_total_slots[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_smi_num_stats[NUM_CTX][MAX_NR_CPUS];
-static struct stats runtime_aperf_stats[NUM_CTX][MAX_NR_CPUS];
-static struct rblist runtime_saved_values;
 static bool have_frontend_stalled;
 
 struct runtime_stat rt_stat;
@@ -163,10 +141,6 @@ void runtime_stat__exit(struct runtime_stat *stat)
 void perf_stat__init_shadow_stats(void)
 {
have_frontend_stalled = pmu_have_event("cpu", 
"stalled-cycles-frontend");
-   rblist__init(_saved_values);
-   runtime_saved_values.node_cmp = saved_value_cmp;
-   runtime_saved_values.node_new = saved_value_new;
-   runtime_saved_values.node_delete = saved_value_delete;
runtime_stat__init(_stat);
 }
 
@@ -188,36 +162,13 @@ static int evsel_context(struct perf_evsel *evsel)
return ctx;
 }
 
-void perf_stat__reset_shadow_stats(void)
+static void reset_stat(struct runtime_stat *stat)
 {
+   struct rblist *rblist;
struct rb_node *pos, *next;
 
-   memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats));
-   memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
-   memset(runtime_stalled_cycles_front_stats, 0, 
sizeof(runtime_stalled_cycles_front_stats));
-   memset(runtime_stalled_cycles_back_stats, 0, 
sizeof(runtime_stalled_cycles_back_stats));
-   memset(runtime_branches_stats, 0, sizeof(runtime_branches_stats));
-   memset(runtime_cacherefs_stats, 0, sizeof(runtime_cacherefs_stats));
-   memset(runtime_l1_dcache_stats, 0, sizeof(runtime_l1_dcache_stats));
-   memset(runtime_l1_icache_stats, 0, sizeof(runtime_l1_icache_stats));
-   memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
-   memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
-   memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
-   memset(runtime_cycles_in_tx_stats, 0,
-   sizeof(runtime_cycles_in_tx_stats));
-   memset(runtime_transaction_stats, 0,
-   sizeof(runtime_transaction_stats));
-   memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
-   memset(_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
-   memset(runtime_topdown_total_slots, 0, 
sizeof(runtime_topdown_total_slots));
-   memset(runtime_topdown_slots_retired, 0, 
sizeof(runtime_topdown_slots_retired));
-   memset(runtime_topdown_slots_issued, 0, 
sizeof(runtime_topdown_slots_issued));
-   memset(runtime_topdown_fetch_bubbles, 0, 
sizeof(runtime_topdown_fetch_bubbles));
-   memset(runtime_topdown_recovery_bubbles, 0, 
sizeof(runtime_topdown_recovery_bubbles));
-   memset(runtime_smi_num_stats, 0, sizeof(runtime_smi_num_stats));
-   memset(runtime_aperf_stats, 0, sizeof(runtime_aperf_stats));
-
-   next = rb_first(_saved_values.entries);
+   rblist = >value_list;
+   next = rb_first(>entries);
while (next) {
pos = next;
next = rb_next(pos);
@@ -227,6 +178,17 @@ void perf_stat__reset_shadow_stats(void)
}
 }
 
+void 

[PATCH v6 09/11] perf util: Enumerate all threads from /proc

2017-12-04 Thread Jin Yao
This patch calls thread_map__new_all_cpus() to enumerate all
threads from /proc if per-thread flag is enabled.

Signed-off-by: Jin Yao 
---
 tools/perf/tests/thread-map.c | 2 +-
 tools/perf/util/evlist.c  | 3 ++-
 tools/perf/util/thread_map.c  | 5 -
 tools/perf/util/thread_map.h  | 2 +-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index dbcb6a1..4de1939 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -105,7 +105,7 @@ int test__thread_map_remove(struct test *test 
__maybe_unused, int subtest __mayb
TEST_ASSERT_VAL("failed to allocate map string",
asprintf(, "%d,%d", getpid(), getppid()) >= 0);
 
-   threads = thread_map__new_str(str, NULL, 0);
+   threads = thread_map__new_str(str, NULL, 0, false);
 
TEST_ASSERT_VAL("failed to allocate thread_map",
threads);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 68c1f95..9c396ac 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1100,7 +1100,8 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, 
struct target *target)
struct cpu_map *cpus;
struct thread_map *threads;
 
-   threads = thread_map__new_str(target->pid, target->tid, target->uid);
+   threads = thread_map__new_str(target->pid, target->tid, target->uid,
+ target->per_thread);
 
if (!threads)
return -1;
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 2b65385..3e1038f 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -323,7 +323,7 @@ struct thread_map *thread_map__new_by_tid_str(const char 
*tid_str)
 }
 
 struct thread_map *thread_map__new_str(const char *pid, const char *tid,
-  uid_t uid)
+  uid_t uid, bool per_thread)
 {
if (pid)
return thread_map__new_by_pid_str(pid);
@@ -331,6 +331,9 @@ struct thread_map *thread_map__new_str(const char *pid, 
const char *tid,
if (!tid && uid != UINT_MAX)
return thread_map__new_by_uid(uid);
 
+   if (per_thread)
+   return thread_map__new_all_cpus();
+
return thread_map__new_by_tid_str(tid);
 }
 
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 07a765f..0a806b9 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -31,7 +31,7 @@ struct thread_map *thread_map__get(struct thread_map *map);
 void thread_map__put(struct thread_map *map);
 
 struct thread_map *thread_map__new_str(const char *pid,
-   const char *tid, uid_t uid);
+   const char *tid, uid_t uid, bool per_thread);
 
 struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
 
-- 
2.7.4



[PATCH v6 03/11] perf util: Create the runtime_stat init/exit function

2017-12-04 Thread Jin Yao
It mainly initializes and releases the rblist which is
defined in struct runtime_stat.

For the original rblist 'runtime_saved_values', it's still
kept there for keeping the patch bisectable.

The rblist 'runtime_saved_values' will be removed in later
patch at switching time.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 17 +
 tools/perf/util/stat.h|  3 +++
 2 files changed, 20 insertions(+)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 528be3e..e60c321 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -40,6 +40,7 @@ static struct stats runtime_aperf_stats[NUM_CTX][MAX_NR_CPUS];
 static struct rblist runtime_saved_values;
 static bool have_frontend_stalled;
 
+struct runtime_stat rt_stat;
 struct stats walltime_nsecs_stats;
 
 struct saved_value {
@@ -134,6 +135,21 @@ static struct saved_value *saved_value_lookup(struct 
perf_evsel *evsel,
return NULL;
 }
 
+void runtime_stat__init(struct runtime_stat *stat)
+{
+   struct rblist *rblist = >value_list;
+
+   rblist__init(rblist);
+   rblist->node_cmp = saved_value_cmp;
+   rblist->node_new = saved_value_new;
+   rblist->node_delete = saved_value_delete;
+}
+
+void runtime_stat__exit(struct runtime_stat *stat)
+{
+   rblist__exit(>value_list);
+}
+
 void perf_stat__init_shadow_stats(void)
 {
have_frontend_stalled = pmu_have_event("cpu", 
"stalled-cycles-frontend");
@@ -141,6 +157,7 @@ void perf_stat__init_shadow_stats(void)
runtime_saved_values.node_cmp = saved_value_cmp;
runtime_saved_values.node_new = saved_value_new;
runtime_saved_values.node_delete = saved_value_delete;
+   runtime_stat__init(_stat);
 }
 
 static int evsel_context(struct perf_evsel *evsel)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index c685c41..5a0ebdc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -117,12 +117,15 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 
 void perf_stat_evsel_id_init(struct perf_evsel *evsel);
 
+extern struct runtime_stat rt_stat;
 extern struct stats walltime_nsecs_stats;
 
 typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit,
   const char *fmt, double val);
 typedef void (*new_line_t )(void *ctx);
 
+void runtime_stat__init(struct runtime_stat *stat);
+void runtime_stat__exit(struct runtime_stat *stat);
 void perf_stat__init_shadow_stats(void);
 void perf_stat__reset_shadow_stats(void);
 void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
-- 
2.7.4



[PATCH v6 09/11] perf util: Enumerate all threads from /proc

2017-12-04 Thread Jin Yao
This patch calls thread_map__new_all_cpus() to enumerate all
threads from /proc if per-thread flag is enabled.

Signed-off-by: Jin Yao 
---
 tools/perf/tests/thread-map.c | 2 +-
 tools/perf/util/evlist.c  | 3 ++-
 tools/perf/util/thread_map.c  | 5 -
 tools/perf/util/thread_map.h  | 2 +-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index dbcb6a1..4de1939 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -105,7 +105,7 @@ int test__thread_map_remove(struct test *test 
__maybe_unused, int subtest __mayb
TEST_ASSERT_VAL("failed to allocate map string",
asprintf(, "%d,%d", getpid(), getppid()) >= 0);
 
-   threads = thread_map__new_str(str, NULL, 0);
+   threads = thread_map__new_str(str, NULL, 0, false);
 
TEST_ASSERT_VAL("failed to allocate thread_map",
threads);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 68c1f95..9c396ac 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1100,7 +1100,8 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, 
struct target *target)
struct cpu_map *cpus;
struct thread_map *threads;
 
-   threads = thread_map__new_str(target->pid, target->tid, target->uid);
+   threads = thread_map__new_str(target->pid, target->tid, target->uid,
+ target->per_thread);
 
if (!threads)
return -1;
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 2b65385..3e1038f 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -323,7 +323,7 @@ struct thread_map *thread_map__new_by_tid_str(const char 
*tid_str)
 }
 
 struct thread_map *thread_map__new_str(const char *pid, const char *tid,
-  uid_t uid)
+  uid_t uid, bool per_thread)
 {
if (pid)
return thread_map__new_by_pid_str(pid);
@@ -331,6 +331,9 @@ struct thread_map *thread_map__new_str(const char *pid, 
const char *tid,
if (!tid && uid != UINT_MAX)
return thread_map__new_by_uid(uid);
 
+   if (per_thread)
+   return thread_map__new_all_cpus();
+
return thread_map__new_by_tid_str(tid);
 }
 
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 07a765f..0a806b9 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -31,7 +31,7 @@ struct thread_map *thread_map__get(struct thread_map *map);
 void thread_map__put(struct thread_map *map);
 
 struct thread_map *thread_map__new_str(const char *pid,
-   const char *tid, uid_t uid);
+   const char *tid, uid_t uid, bool per_thread);
 
 struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
 
-- 
2.7.4



[PATCH v6 03/11] perf util: Create the runtime_stat init/exit function

2017-12-04 Thread Jin Yao
It mainly initializes and releases the rblist which is
defined in struct runtime_stat.

For the original rblist 'runtime_saved_values', it's still
kept there for keeping the patch bisectable.

The rblist 'runtime_saved_values' will be removed in later
patch at switching time.

Signed-off-by: Jin Yao 
---
 tools/perf/util/stat-shadow.c | 17 +
 tools/perf/util/stat.h|  3 +++
 2 files changed, 20 insertions(+)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 528be3e..e60c321 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -40,6 +40,7 @@ static struct stats runtime_aperf_stats[NUM_CTX][MAX_NR_CPUS];
 static struct rblist runtime_saved_values;
 static bool have_frontend_stalled;
 
+struct runtime_stat rt_stat;
 struct stats walltime_nsecs_stats;
 
 struct saved_value {
@@ -134,6 +135,21 @@ static struct saved_value *saved_value_lookup(struct 
perf_evsel *evsel,
return NULL;
 }
 
+void runtime_stat__init(struct runtime_stat *stat)
+{
+   struct rblist *rblist = >value_list;
+
+   rblist__init(rblist);
+   rblist->node_cmp = saved_value_cmp;
+   rblist->node_new = saved_value_new;
+   rblist->node_delete = saved_value_delete;
+}
+
+void runtime_stat__exit(struct runtime_stat *stat)
+{
+   rblist__exit(>value_list);
+}
+
 void perf_stat__init_shadow_stats(void)
 {
have_frontend_stalled = pmu_have_event("cpu", 
"stalled-cycles-frontend");
@@ -141,6 +157,7 @@ void perf_stat__init_shadow_stats(void)
runtime_saved_values.node_cmp = saved_value_cmp;
runtime_saved_values.node_new = saved_value_new;
runtime_saved_values.node_delete = saved_value_delete;
+   runtime_stat__init(_stat);
 }
 
 static int evsel_context(struct perf_evsel *evsel)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index c685c41..5a0ebdc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -117,12 +117,15 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 
 void perf_stat_evsel_id_init(struct perf_evsel *evsel);
 
+extern struct runtime_stat rt_stat;
 extern struct stats walltime_nsecs_stats;
 
 typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit,
   const char *fmt, double val);
 typedef void (*new_line_t )(void *ctx);
 
+void runtime_stat__init(struct runtime_stat *stat);
+void runtime_stat__exit(struct runtime_stat *stat);
 void perf_stat__init_shadow_stats(void);
 void perf_stat__reset_shadow_stats(void);
 void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
-- 
2.7.4



[PATCH v6 00/11] perf stat: Enable '--per-thread' on all thread

2017-12-04 Thread Jin Yao
v6:
---
Update according to Arnaldo's comments.

1. In 'perf util: Define a structure for runtime shadow stats'
Remove '#include "evsel.h"'

2. In 'perf stat: Extend rbtree to support per-thread shadow stats'
Change patch subject to 'perf stat: Extend rbtree to support per-thread shadow 
stats'.

3. Split the 'perf util: Update and print per-thread shadow stats' to 2 patches.
  perf util: Update per-thread shadow stats
  perf util: Print per-thread shadow stats

4. Rebase to latest perf/core branch
Because 3 patches have been merged yet so remove them in this patch series.

Update the patch 'perf util: Enumerate all threads from /proc' in rebase.

v5:
---
Update according to Arnaldo's comments.

Try to replace '_reset' with '_exit' and '_free' with '_delete'.

1. In 'perf util: Create rblist__exit() function', 
rblist__reset() -> rblist__exit()

2. In 'perf util: Create the runtime_stat init/exit function'
runtime_stat__free() -> runtime_stat__exit()

I don't change the name to runtime_stat__delete() because
it doesn't free the object in this function. So maybe '__exit'
is better.

3. In 'perf stat: Allocate shadow stats buffer for threads'
runtime_stat_alloc() -> runtime_stat_new()
runtime_stat_free() -> runtime_stat_delete()

v4:
---
Update according to Jiri's comments. The major modification is:

Move struct perf_stat_config::*stats|stats_num to
'perf stat: Allocate shadow stats buffer for threads'.

I also move the code of updating/printing per-thread stats
from 'perf util: Update and print per-thread shadow stats'
and 'perf stat: Allocate shadow stats buffer for threads'
to a new patch 'perf stat: Update or print per-thread stats'.
That should be more clear for patch reading.

Impacted patch:
---
  perf util: Define a structure for runtime shadow stats
  perf util: Update and print per-thread shadow stats
  perf stat: Allocate shadow stats buffer for threads
  perf stat: Update or print per-thread stats
  perf stat: Resort '--per-thread' result

v3:
---
Update according to Jiri's comments. The major modifications are:

1. Fix the crash issue when performing the git bisect.
   Move the removing of runtime_saved_values to the switching point
   (perf util: Remove a set of shadow stats static variables).

2. Still add struct perf_stat_config::*stats|stats_num in earlier
   patch because 'stats' will be used in
   'perf util: Update and print per-thread shadow stats'.
   If it's moved to 'perf stat: Allocate shadow stats buffer for threads',
   the compilation would be failed.

3. v = container_of(rb_node,
struct saved_value,
rb_node);

   Let this code to be one line.

Impacted patch:
---
  perf util: Add rbtree node_delete ops
  perf util: Create the runtime_stat init/free function
  perf util: Update and print per-thread shadow stats
  perf util: Remove a set of shadow stats static variables

v2:
---
Update according to Jiri's comments. The major modifications are:

1. Remove unnecessary memset for runtime_stat and
   walltime_nsecs_stats.

2. Remove init_saved_rblist/free_saved_rblist and move the codes
   to runtime_stat__init/runtime_stat__free.

3. Change function name from perf_stat__init_runtime_stat/
   perf_stat__free_runtime_stat to runtime_stat__init/
   runtime_stat__free

4. Create a new patch 'perf util: Extend rbtree to support shadow stats'
   to add new ctx/type/stat into rbtree keys for supporting per-thread
   shadow stats. It also comment in here on the cases where evsel is
   defined and when not.

5. Pass _stat directly to perf_stat__update_shadow_stats, replace
   original parameter NULL.

6. Move the code of shadow stat updating for per-thread case to config->stats
   allocation/usage patch.

7. Add BUG_ON(!rb_node) in saved_value_delete.

8. s/stat_num/stats_num/ or s/stats/stat/ in struct perf_stat_config.

9. Rebase to latest perf/core branch.

Impacted patch:
---
  perf util: Define a structure for runtime shadow metrics stats
  perf util: Extend rbtree to support shadow stats
  perf util: Add rbtree node_delete ops
  perf util: Update and print per-thread shadow stats
  perf stat: Allocate shadow stats buffer for threads
  perf stat: Remove --per-thread pid/tid limitation
  perf stat: Resort '--per-thread' result

Initial post:
-

perf stat --per-thread is useful to break down data per thread.
But it currently requires specifying --pid/--tid to limit it to a process.

For analysis it would be useful to do it globally for the whole system.

1. Currently, if we perform 'perf stat --per-thread' without pid/tid,
perf returns error:

root@skl:/tmp# perf stat --per-thread
The --per-thread option is only available when monitoring via -p -t options.
-p, --pidstat events on existing process id
-t, --tidstat events on existing thread id

2. With this patch series, it returns data per thread with shadow metrics.
   (run "vmstat 1" in following example)

root@skl:/tmp# 

[PATCH v6 11/11] perf stat: Resort '--per-thread' result

2017-12-04 Thread Jin Yao
There are many threads reported if we enable '--per-thread'
globally.

1. Most of the threads are not counted or counting value 0.
This patch removes these threads.

2. We also resort the threads in display according to the
counting value. It's useful for user to see the hottest
threads easily.

For example, the new results would be:

root@skl:/tmp# perf stat --per-thread
^C
 Performance counter stats for 'system wide':

perf-24165  4.302433  cpu-clock (msec)  #   
 0.001 CPUs utilized
  vmstat-23127  1.562215  cpu-clock (msec)  #   
 0.000 CPUs utilized
  irqbalance-2780   0.827851  cpu-clock (msec)  #   
 0.000 CPUs utilized
sshd-23111  0.278308  cpu-clock (msec)  #   
 0.000 CPUs utilized
thermald-2841   0.230880  cpu-clock (msec)  #   
 0.000 CPUs utilized
sshd-23058  0.207306  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/0:2-19991  0.133983  cpu-clock (msec)  #   
 0.000 CPUs utilized
   kworker/u16:1-18249  0.125636  cpu-clock (msec)  #   
 0.000 CPUs utilized
   rcu_sched-8  0.085533  cpu-clock (msec)  #   
 0.000 CPUs utilized
   kworker/u16:2-23146  0.077139  cpu-clock (msec)  #   
 0.000 CPUs utilized
   gmain-2700   0.041789  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/4:1-15354  0.028370  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/6:0-17528  0.023895  cpu-clock (msec)  #   
 0.000 CPUs utilized
kworker/4:1H-1887   0.013209  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/5:2-31362  0.011627  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/0-11 0.010892  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/3:2-12870  0.010220  cpu-clock (msec)  #   
 0.000 CPUs utilized
 ksoftirqd/0-7  0.008869  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/1-14 0.008476  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/7-50 0.002944  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/3-26 0.002893  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/4-32 0.002759  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/2-20 0.002429  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/6-44 0.001491  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/5-38 0.001477  cpu-clock (msec)  #   
 0.000 CPUs utilized
   rcu_sched-810  context-switches  #   
 0.117 M/sec
   kworker/u16:1-18249 7  context-switches  #   
 0.056 M/sec
sshd-23111 4  context-switches  #   
 0.014 M/sec
  vmstat-23127 4  context-switches  #   
 0.003 M/sec
perf-24165 4  context-switches  #   
 0.930 K/sec
 kworker/0:2-19991 3  context-switches  #   
 0.022 M/sec
   kworker/u16:2-23146 3  context-switches  #   
 0.039 M/sec
 kworker/4:1-15354 2  context-switches  #   
 0.070 M/sec
 kworker/6:0-17528 2  context-switches  #   
 0.084 M/sec
sshd-23058 2  context-switches  #   
 0.010 M/sec
 ksoftirqd/0-7 1  context-switches  #   
 0.113 M/sec
  watchdog/0-111  context-switches  #   
 0.092 M/sec
  watchdog/1-141  context-switches  #   
 0.118 M/sec
  watchdog/2-201  context-switches  #   
 0.412 M/sec
  watchdog/3-261  context-switches  #   
 0.346 M/sec
  watchdog/4-321  context-switches  #   
 0.362 M/sec
  watchdog/5-381  context-switches  #   
 0.677 M/sec
  watchdog/6-441  context-switches  #   
 0.671 M/sec
  watchdog/7-501  context-switches  #   
 0.340 M/sec
kworker/4:1H-1887  1  context-switches  #   
 0.076 M/sec
thermald-2841  1  context-switches  #   
 0.004 M/sec
   gmain-2700  1  

[PATCH v6 08/11] perf stat: Update or print per-thread stats

2017-12-04 Thread Jin Yao
If the stats pointer in stat_config structure is not null, it will
update the per-thread stats or print the per-thread stats on this
buffer.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-stat.c |  9 +++--
 tools/perf/util/stat.c| 11 ---
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8ff3348..23d5618 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1373,8 +1373,13 @@ static void print_aggr_thread(struct perf_evsel 
*counter, char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(thread, 0, counter, uval, prefix, run, ena, 1.0,
-_stat);
+
+   if (stat_config.stats)
+   printout(thread, 0, counter, uval, prefix, run, ena,
+1.0, _config.stats[thread]);
+   else
+   printout(thread, 0, counter, uval, prefix, run, ena,
+1.0, _stat);
fputc('\n', output);
}
 }
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 78abfd4..32235657 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -280,9 +280,14 @@ process_counter_values(struct perf_stat_config *config, 
struct perf_evsel *evsel
if (config->aggr_mode == AGGR_NONE)
perf_stat__update_shadow_stats(evsel, count->val, cpu,
   _stat);
-   if (config->aggr_mode == AGGR_THREAD)
-   perf_stat__update_shadow_stats(evsel, count->val, 0,
-  _stat);
+   if (config->aggr_mode == AGGR_THREAD) {
+   if (config->stats)
+   perf_stat__update_shadow_stats(evsel,
+   count->val, 0, >stats[thread]);
+   else
+   perf_stat__update_shadow_stats(evsel,
+   count->val, 0, _stat);
+   }
break;
case AGGR_GLOBAL:
aggr->val += count->val;
-- 
2.7.4



[PATCH v6 00/11] perf stat: Enable '--per-thread' on all thread

2017-12-04 Thread Jin Yao
v6:
---
Update according to Arnaldo's comments.

1. In 'perf util: Define a structure for runtime shadow stats'
Remove '#include "evsel.h"'

2. In 'perf stat: Extend rbtree to support per-thread shadow stats'
Change patch subject to 'perf stat: Extend rbtree to support per-thread shadow 
stats'.

3. Split the 'perf util: Update and print per-thread shadow stats' to 2 patches.
  perf util: Update per-thread shadow stats
  perf util: Print per-thread shadow stats

4. Rebase to latest perf/core branch
Because 3 patches have been merged yet so remove them in this patch series.

Update the patch 'perf util: Enumerate all threads from /proc' in rebase.

v5:
---
Update according to Arnaldo's comments.

Try to replace '_reset' with '_exit' and '_free' with '_delete'.

1. In 'perf util: Create rblist__exit() function', 
rblist__reset() -> rblist__exit()

2. In 'perf util: Create the runtime_stat init/exit function'
runtime_stat__free() -> runtime_stat__exit()

I don't change the name to runtime_stat__delete() because
it doesn't free the object in this function. So maybe '__exit'
is better.

3. In 'perf stat: Allocate shadow stats buffer for threads'
runtime_stat_alloc() -> runtime_stat_new()
runtime_stat_free() -> runtime_stat_delete()

v4:
---
Update according to Jiri's comments. The major modification is:

Move struct perf_stat_config::*stats|stats_num to
'perf stat: Allocate shadow stats buffer for threads'.

I also move the code of updating/printing per-thread stats
from 'perf util: Update and print per-thread shadow stats'
and 'perf stat: Allocate shadow stats buffer for threads'
to a new patch 'perf stat: Update or print per-thread stats'.
That should be more clear for patch reading.

Impacted patch:
---
  perf util: Define a structure for runtime shadow stats
  perf util: Update and print per-thread shadow stats
  perf stat: Allocate shadow stats buffer for threads
  perf stat: Update or print per-thread stats
  perf stat: Resort '--per-thread' result

v3:
---
Update according to Jiri's comments. The major modifications are:

1. Fix the crash issue when performing the git bisect.
   Move the removing of runtime_saved_values to the switching point
   (perf util: Remove a set of shadow stats static variables).

2. Still add struct perf_stat_config::*stats|stats_num in earlier
   patch because 'stats' will be used in
   'perf util: Update and print per-thread shadow stats'.
   If it's moved to 'perf stat: Allocate shadow stats buffer for threads',
   the compilation would be failed.

3. v = container_of(rb_node,
struct saved_value,
rb_node);

   Let this code to be one line.

Impacted patch:
---
  perf util: Add rbtree node_delete ops
  perf util: Create the runtime_stat init/free function
  perf util: Update and print per-thread shadow stats
  perf util: Remove a set of shadow stats static variables

v2:
---
Update according to Jiri's comments. The major modifications are:

1. Remove unnecessary memset for runtime_stat and
   walltime_nsecs_stats.

2. Remove init_saved_rblist/free_saved_rblist and move the codes
   to runtime_stat__init/runtime_stat__free.

3. Change function name from perf_stat__init_runtime_stat/
   perf_stat__free_runtime_stat to runtime_stat__init/
   runtime_stat__free

4. Create a new patch 'perf util: Extend rbtree to support shadow stats'
   to add new ctx/type/stat into rbtree keys for supporting per-thread
   shadow stats. It also comment in here on the cases where evsel is
   defined and when not.

5. Pass _stat directly to perf_stat__update_shadow_stats, replace
   original parameter NULL.

6. Move the code of shadow stat updating for per-thread case to config->stats
   allocation/usage patch.

7. Add BUG_ON(!rb_node) in saved_value_delete.

8. s/stat_num/stats_num/ or s/stats/stat/ in struct perf_stat_config.

9. Rebase to latest perf/core branch.

Impacted patch:
---
  perf util: Define a structure for runtime shadow metrics stats
  perf util: Extend rbtree to support shadow stats
  perf util: Add rbtree node_delete ops
  perf util: Update and print per-thread shadow stats
  perf stat: Allocate shadow stats buffer for threads
  perf stat: Remove --per-thread pid/tid limitation
  perf stat: Resort '--per-thread' result

Initial post:
-

perf stat --per-thread is useful to break down data per thread.
But it currently requires specifying --pid/--tid to limit it to a process.

For analysis it would be useful to do it globally for the whole system.

1. Currently, if we perform 'perf stat --per-thread' without pid/tid,
perf returns error:

root@skl:/tmp# perf stat --per-thread
The --per-thread option is only available when monitoring via -p -t options.
-p, --pidstat events on existing process id
-t, --tidstat events on existing thread id

2. With this patch series, it returns data per thread with shadow metrics.
   (run "vmstat 1" in following example)

root@skl:/tmp# 

[PATCH v6 11/11] perf stat: Resort '--per-thread' result

2017-12-04 Thread Jin Yao
There are many threads reported if we enable '--per-thread'
globally.

1. Most of the threads are not counted or counting value 0.
This patch removes these threads.

2. We also resort the threads in display according to the
counting value. It's useful for user to see the hottest
threads easily.

For example, the new results would be:

root@skl:/tmp# perf stat --per-thread
^C
 Performance counter stats for 'system wide':

perf-24165  4.302433  cpu-clock (msec)  #   
 0.001 CPUs utilized
  vmstat-23127  1.562215  cpu-clock (msec)  #   
 0.000 CPUs utilized
  irqbalance-2780   0.827851  cpu-clock (msec)  #   
 0.000 CPUs utilized
sshd-23111  0.278308  cpu-clock (msec)  #   
 0.000 CPUs utilized
thermald-2841   0.230880  cpu-clock (msec)  #   
 0.000 CPUs utilized
sshd-23058  0.207306  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/0:2-19991  0.133983  cpu-clock (msec)  #   
 0.000 CPUs utilized
   kworker/u16:1-18249  0.125636  cpu-clock (msec)  #   
 0.000 CPUs utilized
   rcu_sched-8  0.085533  cpu-clock (msec)  #   
 0.000 CPUs utilized
   kworker/u16:2-23146  0.077139  cpu-clock (msec)  #   
 0.000 CPUs utilized
   gmain-2700   0.041789  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/4:1-15354  0.028370  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/6:0-17528  0.023895  cpu-clock (msec)  #   
 0.000 CPUs utilized
kworker/4:1H-1887   0.013209  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/5:2-31362  0.011627  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/0-11 0.010892  cpu-clock (msec)  #   
 0.000 CPUs utilized
 kworker/3:2-12870  0.010220  cpu-clock (msec)  #   
 0.000 CPUs utilized
 ksoftirqd/0-7  0.008869  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/1-14 0.008476  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/7-50 0.002944  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/3-26 0.002893  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/4-32 0.002759  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/2-20 0.002429  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/6-44 0.001491  cpu-clock (msec)  #   
 0.000 CPUs utilized
  watchdog/5-38 0.001477  cpu-clock (msec)  #   
 0.000 CPUs utilized
   rcu_sched-810  context-switches  #   
 0.117 M/sec
   kworker/u16:1-18249 7  context-switches  #   
 0.056 M/sec
sshd-23111 4  context-switches  #   
 0.014 M/sec
  vmstat-23127 4  context-switches  #   
 0.003 M/sec
perf-24165 4  context-switches  #   
 0.930 K/sec
 kworker/0:2-19991 3  context-switches  #   
 0.022 M/sec
   kworker/u16:2-23146 3  context-switches  #   
 0.039 M/sec
 kworker/4:1-15354 2  context-switches  #   
 0.070 M/sec
 kworker/6:0-17528 2  context-switches  #   
 0.084 M/sec
sshd-23058 2  context-switches  #   
 0.010 M/sec
 ksoftirqd/0-7 1  context-switches  #   
 0.113 M/sec
  watchdog/0-111  context-switches  #   
 0.092 M/sec
  watchdog/1-141  context-switches  #   
 0.118 M/sec
  watchdog/2-201  context-switches  #   
 0.412 M/sec
  watchdog/3-261  context-switches  #   
 0.346 M/sec
  watchdog/4-321  context-switches  #   
 0.362 M/sec
  watchdog/5-381  context-switches  #   
 0.677 M/sec
  watchdog/6-441  context-switches  #   
 0.671 M/sec
  watchdog/7-501  context-switches  #   
 0.340 M/sec
kworker/4:1H-1887  1  context-switches  #   
 0.076 M/sec
thermald-2841  1  context-switches  #   
 0.004 M/sec
   gmain-2700  1  

[PATCH v6 08/11] perf stat: Update or print per-thread stats

2017-12-04 Thread Jin Yao
If the stats pointer in stat_config structure is not null, it will
update the per-thread stats or print the per-thread stats on this
buffer.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-stat.c |  9 +++--
 tools/perf/util/stat.c| 11 ---
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8ff3348..23d5618 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1373,8 +1373,13 @@ static void print_aggr_thread(struct perf_evsel 
*counter, char *prefix)
fprintf(output, "%s", prefix);
 
uval = val * counter->scale;
-   printout(thread, 0, counter, uval, prefix, run, ena, 1.0,
-_stat);
+
+   if (stat_config.stats)
+   printout(thread, 0, counter, uval, prefix, run, ena,
+1.0, _config.stats[thread]);
+   else
+   printout(thread, 0, counter, uval, prefix, run, ena,
+1.0, _stat);
fputc('\n', output);
}
 }
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 78abfd4..32235657 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -280,9 +280,14 @@ process_counter_values(struct perf_stat_config *config, 
struct perf_evsel *evsel
if (config->aggr_mode == AGGR_NONE)
perf_stat__update_shadow_stats(evsel, count->val, cpu,
   _stat);
-   if (config->aggr_mode == AGGR_THREAD)
-   perf_stat__update_shadow_stats(evsel, count->val, 0,
-  _stat);
+   if (config->aggr_mode == AGGR_THREAD) {
+   if (config->stats)
+   perf_stat__update_shadow_stats(evsel,
+   count->val, 0, >stats[thread]);
+   else
+   perf_stat__update_shadow_stats(evsel,
+   count->val, 0, _stat);
+   }
break;
case AGGR_GLOBAL:
aggr->val += count->val;
-- 
2.7.4



[PATCH v6 10/11] perf stat: Remove --per-thread pid/tid limitation

2017-12-04 Thread Jin Yao
Currently, if we execute 'perf stat --per-thread' without specifying
pid/tid, perf will return error.

root@skl:/tmp# perf stat --per-thread
The --per-thread option is only available when monitoring via -p -t options.
-p, --pidstat events on existing process id
-t, --tidstat events on existing thread id

This patch removes this limitation. If no pid/tid specified, it returns
all threads (get threads from /proc).

Note that it doesn't support cpu_list yet so if it's a cpu_list case,
then skip.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-stat.c | 23 +++
 tools/perf/util/target.h  |  7 +++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 23d5618..167c35c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -277,7 +277,7 @@ static int create_perf_stat_counter(struct perf_evsel 
*evsel)
attr->enable_on_exec = 1;
}
 
-   if (target__has_cpu())
+   if (target__has_cpu() && !target__has_per_thread())
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
 
return perf_evsel__open_per_thread(evsel, evsel_list->threads);
@@ -340,7 +340,7 @@ static int read_counter(struct perf_evsel *counter)
int nthreads = thread_map__nr(evsel_list->threads);
int ncpus, cpu, thread;
 
-   if (target__has_cpu())
+   if (target__has_cpu() && !target__has_per_thread())
ncpus = perf_evsel__nr_cpus(counter);
else
ncpus = 1;
@@ -2744,12 +2744,16 @@ int cmd_stat(int argc, const char **argv)
run_count = 1;
}
 
-   if ((stat_config.aggr_mode == AGGR_THREAD) && 
!target__has_task()) {
-   fprintf(stderr, "The --per-thread option is only available "
-   "when monitoring via -p -t options.\n");
-   parse_options_usage(NULL, stat_options, "p", 1);
-   parse_options_usage(NULL, stat_options, "t", 1);
-   goto out;
+   if ((stat_config.aggr_mode == AGGR_THREAD) &&
+   !target__has_task()) {
+   if (!target.system_wide || target.cpu_list) {
+   fprintf(stderr, "The --per-thread option is only "
+   "available when monitoring via -p -t -a "
+   "options or only --per-thread.\n");
+   parse_options_usage(NULL, stat_options, "p", 1);
+   parse_options_usage(NULL, stat_options, "t", 1);
+   goto out;
+   }
}
 
/*
@@ -2773,6 +2777,9 @@ int cmd_stat(int argc, const char **argv)
 
target__validate();
 
+   if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
+   target.per_thread = true;
+
if (perf_evlist__create_maps(evsel_list, ) < 0) {
if (target__has_task()) {
pr_err("Problems finding threads of monitor\n");
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 446aa7a..6ef01a8 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -64,6 +64,11 @@ static inline bool target__none(struct target *target)
return !target__has_task(target) && !target__has_cpu(target);
 }
 
+static inline bool target__has_per_thread(struct target *target)
+{
+   return target->system_wide && target->per_thread;
+}
+
 static inline bool target__uses_dummy_map(struct target *target)
 {
bool use_dummy = false;
@@ -73,6 +78,8 @@ static inline bool target__uses_dummy_map(struct target 
*target)
else if (target__has_task(target) ||
 (!target__has_cpu(target) && !target->uses_mmap))
use_dummy = true;
+   else if (target__has_per_thread(target))
+   use_dummy = true;
 
return use_dummy;
 }
-- 
2.7.4



[PATCH v6 07/11] perf stat: Allocate shadow stats buffer for threads

2017-12-04 Thread Jin Yao
After perf_evlist__create_maps() being executed, we can get all
threads from /proc. And via thread_map__nr(), we can also get
the number of threads.

With the number of threads, the patch allocates a buffer which
will record the shadow stats for these threads.

The buffer pointer is saved in stat_config.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-stat.c | 46 +-
 tools/perf/util/stat.h|  2 ++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1edc082..8ff3348 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -214,8 +214,13 @@ static inline void diff_timespec(struct timespec *r, 
struct timespec *a,
 
 static void perf_stat__reset_stats(void)
 {
+   int i;
+
perf_evlist__reset_stats(evsel_list);
perf_stat__reset_shadow_stats();
+
+   for (i = 0; i < stat_config.stats_num; i++)
+   perf_stat__reset_shadow_per_stat(_config.stats[i]);
 }
 
 static int create_perf_stat_counter(struct perf_evsel *evsel)
@@ -2496,6 +2501,35 @@ int process_cpu_map_event(struct perf_tool *tool,
return set_maps(st);
 }
 
+static int runtime_stat_new(struct perf_stat_config *config, int nthreads)
+{
+   int i;
+
+   config->stats = calloc(nthreads, sizeof(struct runtime_stat));
+   if (!config->stats)
+   return -1;
+
+   config->stats_num = nthreads;
+
+   for (i = 0; i < nthreads; i++)
+   runtime_stat__init(>stats[i]);
+
+   return 0;
+}
+
+static void runtime_stat_delete(struct perf_stat_config *config)
+{
+   int i;
+
+   if (!config->stats)
+   return;
+
+   for (i = 0; i < config->stats_num; i++)
+   runtime_stat__exit(>stats[i]);
+
+   free(config->stats);
+}
+
 static const char * const stat_report_usage[] = {
"perf stat report []",
NULL,
@@ -2751,8 +2785,15 @@ int cmd_stat(int argc, const char **argv)
 * Initialize thread_map with comm names,
 * so we could print it out on output.
 */
-   if (stat_config.aggr_mode == AGGR_THREAD)
+   if (stat_config.aggr_mode == AGGR_THREAD) {
thread_map__read_comms(evsel_list->threads);
+   if (target.system_wide) {
+   if (runtime_stat_new(_config,
+   thread_map__nr(evsel_list->threads))) {
+   goto out;
+   }
+   }
+   }
 
if (interval && interval < 100) {
if (interval < 10) {
@@ -2842,5 +2883,8 @@ int cmd_stat(int argc, const char **argv)
sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
 
perf_evlist__delete(evsel_list);
+
+   runtime_stat_delete(_config);
+
return status;
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 27d7a18..06475c4 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,8 @@ struct perf_stat_config {
boolscale;
FILE*output;
unsigned intinterval;
+   struct runtime_stat *stats;
+   int stats_num;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.7.4



[PATCH v6 10/11] perf stat: Remove --per-thread pid/tid limitation

2017-12-04 Thread Jin Yao
Currently, if we execute 'perf stat --per-thread' without specifying
pid/tid, perf will return error.

root@skl:/tmp# perf stat --per-thread
The --per-thread option is only available when monitoring via -p -t options.
-p, --pidstat events on existing process id
-t, --tidstat events on existing thread id

This patch removes this limitation. If no pid/tid specified, it returns
all threads (get threads from /proc).

Note that it doesn't support cpu_list yet so if it's a cpu_list case,
then skip.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-stat.c | 23 +++
 tools/perf/util/target.h  |  7 +++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 23d5618..167c35c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -277,7 +277,7 @@ static int create_perf_stat_counter(struct perf_evsel 
*evsel)
attr->enable_on_exec = 1;
}
 
-   if (target__has_cpu())
+   if (target__has_cpu() && !target__has_per_thread())
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
 
return perf_evsel__open_per_thread(evsel, evsel_list->threads);
@@ -340,7 +340,7 @@ static int read_counter(struct perf_evsel *counter)
int nthreads = thread_map__nr(evsel_list->threads);
int ncpus, cpu, thread;
 
-   if (target__has_cpu())
+   if (target__has_cpu() && !target__has_per_thread())
ncpus = perf_evsel__nr_cpus(counter);
else
ncpus = 1;
@@ -2744,12 +2744,16 @@ int cmd_stat(int argc, const char **argv)
run_count = 1;
}
 
-   if ((stat_config.aggr_mode == AGGR_THREAD) && 
!target__has_task()) {
-   fprintf(stderr, "The --per-thread option is only available "
-   "when monitoring via -p -t options.\n");
-   parse_options_usage(NULL, stat_options, "p", 1);
-   parse_options_usage(NULL, stat_options, "t", 1);
-   goto out;
+   if ((stat_config.aggr_mode == AGGR_THREAD) &&
+   !target__has_task()) {
+   if (!target.system_wide || target.cpu_list) {
+   fprintf(stderr, "The --per-thread option is only "
+   "available when monitoring via -p -t -a "
+   "options or only --per-thread.\n");
+   parse_options_usage(NULL, stat_options, "p", 1);
+   parse_options_usage(NULL, stat_options, "t", 1);
+   goto out;
+   }
}
 
/*
@@ -2773,6 +2777,9 @@ int cmd_stat(int argc, const char **argv)
 
target__validate();
 
+   if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
+   target.per_thread = true;
+
if (perf_evlist__create_maps(evsel_list, ) < 0) {
if (target__has_task()) {
pr_err("Problems finding threads of monitor\n");
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 446aa7a..6ef01a8 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -64,6 +64,11 @@ static inline bool target__none(struct target *target)
return !target__has_task(target) && !target__has_cpu(target);
 }
 
+static inline bool target__has_per_thread(struct target *target)
+{
+   return target->system_wide && target->per_thread;
+}
+
 static inline bool target__uses_dummy_map(struct target *target)
 {
bool use_dummy = false;
@@ -73,6 +78,8 @@ static inline bool target__uses_dummy_map(struct target 
*target)
else if (target__has_task(target) ||
 (!target__has_cpu(target) && !target->uses_mmap))
use_dummy = true;
+   else if (target__has_per_thread(target))
+   use_dummy = true;
 
return use_dummy;
 }
-- 
2.7.4



[PATCH v6 07/11] perf stat: Allocate shadow stats buffer for threads

2017-12-04 Thread Jin Yao
After perf_evlist__create_maps() being executed, we can get all
threads from /proc. And via thread_map__nr(), we can also get
the number of threads.

With the number of threads, the patch allocates a buffer which
will record the shadow stats for these threads.

The buffer pointer is saved in stat_config.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-stat.c | 46 +-
 tools/perf/util/stat.h|  2 ++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1edc082..8ff3348 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -214,8 +214,13 @@ static inline void diff_timespec(struct timespec *r, 
struct timespec *a,
 
 static void perf_stat__reset_stats(void)
 {
+   int i;
+
perf_evlist__reset_stats(evsel_list);
perf_stat__reset_shadow_stats();
+
+   for (i = 0; i < stat_config.stats_num; i++)
+   perf_stat__reset_shadow_per_stat(_config.stats[i]);
 }
 
 static int create_perf_stat_counter(struct perf_evsel *evsel)
@@ -2496,6 +2501,35 @@ int process_cpu_map_event(struct perf_tool *tool,
return set_maps(st);
 }
 
+static int runtime_stat_new(struct perf_stat_config *config, int nthreads)
+{
+   int i;
+
+   config->stats = calloc(nthreads, sizeof(struct runtime_stat));
+   if (!config->stats)
+   return -1;
+
+   config->stats_num = nthreads;
+
+   for (i = 0; i < nthreads; i++)
+   runtime_stat__init(>stats[i]);
+
+   return 0;
+}
+
+static void runtime_stat_delete(struct perf_stat_config *config)
+{
+   int i;
+
+   if (!config->stats)
+   return;
+
+   for (i = 0; i < config->stats_num; i++)
+   runtime_stat__exit(>stats[i]);
+
+   free(config->stats);
+}
+
 static const char * const stat_report_usage[] = {
"perf stat report []",
NULL,
@@ -2751,8 +2785,15 @@ int cmd_stat(int argc, const char **argv)
 * Initialize thread_map with comm names,
 * so we could print it out on output.
 */
-   if (stat_config.aggr_mode == AGGR_THREAD)
+   if (stat_config.aggr_mode == AGGR_THREAD) {
thread_map__read_comms(evsel_list->threads);
+   if (target.system_wide) {
+   if (runtime_stat_new(_config,
+   thread_map__nr(evsel_list->threads))) {
+   goto out;
+   }
+   }
+   }
 
if (interval && interval < 100) {
if (interval < 10) {
@@ -2842,5 +2883,8 @@ int cmd_stat(int argc, const char **argv)
sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
 
perf_evlist__delete(evsel_list);
+
+   runtime_stat_delete(_config);
+
return status;
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 27d7a18..06475c4 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,8 @@ struct perf_stat_config {
boolscale;
FILE*output;
unsigned intinterval;
+   struct runtime_stat *stats;
+   int stats_num;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.7.4



Re: [PATCH 1/1] mm/page_owner: ignore everything below the IRQ entry point

2017-12-04 Thread kbuild test robot
Hi Maninder,

Thank you for the patch! Yet something to improve:

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

url:
https://github.com/0day-ci/linux/commits/Maninder-Singh/mm-page_owner-ignore-everything-below-the-IRQ-entry-point/20171205-122901
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: tile-allmodconfig (attached as .config)
compiler: tilegx-linux-gcc (GCC) 5.5.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=tile 

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/interrupt.h:22:0,
from include/linux/kernel_stat.h:9,
from mm//swap.c:18:
>> arch/tile/include/asm/sections.h:18:29: error: redefinition of 
>> 'arch_is_kernel_data'
#define arch_is_kernel_data arch_is_kernel_data
^
>> arch/tile/include/asm/sections.h:38:19: note: in expansion of macro 
>> 'arch_is_kernel_data'
static inline int arch_is_kernel_data(unsigned long addr)
  ^
   In file included from include/linux/stacktrace.h:6:0,
from include/linux/lockdep.h:29,
from include/linux/spinlock_types.h:18,
from include/linux/spinlock.h:82,
from include/linux/mmzone.h:8,
from include/linux/gfp.h:6,
from include/linux/mm.h:10,
from mm//swap.c:16:
   include/asm-generic/sections.h:70:19: note: previous definition of 
'arch_is_kernel_data' was here
static inline int arch_is_kernel_data(unsigned long addr)
  ^

vim +/arch_is_kernel_data +18 arch/tile/include/asm/sections.h

867e359b Chris Metcalf 2010-05-28  17  
867e359b Chris Metcalf 2010-05-28 @18  #define arch_is_kernel_data 
arch_is_kernel_data
867e359b Chris Metcalf 2010-05-28  19  
867e359b Chris Metcalf 2010-05-28  20  #include 
867e359b Chris Metcalf 2010-05-28  21  
4a556f4f Chris Metcalf 2013-08-07  22  extern char vdso_start[], vdso_end[];
4a556f4f Chris Metcalf 2013-08-07  23  #ifdef CONFIG_COMPAT
4a556f4f Chris Metcalf 2013-08-07  24  extern char vdso32_start[], vdso32_end[];
4a556f4f Chris Metcalf 2013-08-07  25  #endif
0707ad30 Chris Metcalf 2010-06-25  26  
0707ad30 Chris Metcalf 2010-06-25  27  /* Not exactly sections, but PC 
comparison points in the code. */
0707ad30 Chris Metcalf 2010-06-25  28  extern char __rt_sigreturn[], 
__rt_sigreturn_end[];
2f9ac29e Chris Metcalf 2013-08-06  29  #ifdef __tilegx__
2f9ac29e Chris Metcalf 2013-08-06  30  extern char __start_unalign_asm_code[], 
__end_unalign_asm_code[];
2f9ac29e Chris Metcalf 2013-08-06  31  #else
0707ad30 Chris Metcalf 2010-06-25  32  extern char sys_cmpxchg[], 
__sys_cmpxchg_end[];
0707ad30 Chris Metcalf 2010-06-25  33  extern char __sys_cmpxchg_grab_lock[];
0707ad30 Chris Metcalf 2010-06-25  34  extern char __start_atomic_asm_code[], 
__end_atomic_asm_code[];
0707ad30 Chris Metcalf 2010-06-25  35  #endif
867e359b Chris Metcalf 2010-05-28  36  
40a3b8df Jiang Liu 2013-07-03  37  /* Handle the discontiguity between 
_sdata and _text. */
867e359b Chris Metcalf 2010-05-28 @38  static inline int 
arch_is_kernel_data(unsigned long addr)
867e359b Chris Metcalf 2010-05-28  39  {
867e359b Chris Metcalf 2010-05-28  40   return addr >= (unsigned long)_sdata &&
867e359b Chris Metcalf 2010-05-28  41   addr < (unsigned long)_end;
867e359b Chris Metcalf 2010-05-28  42  }
867e359b Chris Metcalf 2010-05-28  43  

:: The code at line 18 was first introduced by commit
:: 867e359b97c970a60626d5d76bbe2a8fadbf38fb arch/tile: core support for 
Tilera 32-bit chips.

:: TO: Chris Metcalf <cmetc...@tilera.com>
:: CC: Chris Metcalf <cmetc...@tilera.com>

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


.config.gz
Description: application/gzip


Re: [PATCH 1/1] mm/page_owner: ignore everything below the IRQ entry point

2017-12-04 Thread kbuild test robot
Hi Maninder,

Thank you for the patch! Yet something to improve:

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

url:
https://github.com/0day-ci/linux/commits/Maninder-Singh/mm-page_owner-ignore-everything-below-the-IRQ-entry-point/20171205-122901
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: tile-allmodconfig (attached as .config)
compiler: tilegx-linux-gcc (GCC) 5.5.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=tile 

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/interrupt.h:22:0,
from include/linux/kernel_stat.h:9,
from mm//swap.c:18:
>> arch/tile/include/asm/sections.h:18:29: error: redefinition of 
>> 'arch_is_kernel_data'
#define arch_is_kernel_data arch_is_kernel_data
^
>> arch/tile/include/asm/sections.h:38:19: note: in expansion of macro 
>> 'arch_is_kernel_data'
static inline int arch_is_kernel_data(unsigned long addr)
  ^
   In file included from include/linux/stacktrace.h:6:0,
from include/linux/lockdep.h:29,
from include/linux/spinlock_types.h:18,
from include/linux/spinlock.h:82,
from include/linux/mmzone.h:8,
from include/linux/gfp.h:6,
from include/linux/mm.h:10,
from mm//swap.c:16:
   include/asm-generic/sections.h:70:19: note: previous definition of 
'arch_is_kernel_data' was here
static inline int arch_is_kernel_data(unsigned long addr)
  ^

vim +/arch_is_kernel_data +18 arch/tile/include/asm/sections.h

867e359b Chris Metcalf 2010-05-28  17  
867e359b Chris Metcalf 2010-05-28 @18  #define arch_is_kernel_data 
arch_is_kernel_data
867e359b Chris Metcalf 2010-05-28  19  
867e359b Chris Metcalf 2010-05-28  20  #include 
867e359b Chris Metcalf 2010-05-28  21  
4a556f4f Chris Metcalf 2013-08-07  22  extern char vdso_start[], vdso_end[];
4a556f4f Chris Metcalf 2013-08-07  23  #ifdef CONFIG_COMPAT
4a556f4f Chris Metcalf 2013-08-07  24  extern char vdso32_start[], vdso32_end[];
4a556f4f Chris Metcalf 2013-08-07  25  #endif
0707ad30 Chris Metcalf 2010-06-25  26  
0707ad30 Chris Metcalf 2010-06-25  27  /* Not exactly sections, but PC 
comparison points in the code. */
0707ad30 Chris Metcalf 2010-06-25  28  extern char __rt_sigreturn[], 
__rt_sigreturn_end[];
2f9ac29e Chris Metcalf 2013-08-06  29  #ifdef __tilegx__
2f9ac29e Chris Metcalf 2013-08-06  30  extern char __start_unalign_asm_code[], 
__end_unalign_asm_code[];
2f9ac29e Chris Metcalf 2013-08-06  31  #else
0707ad30 Chris Metcalf 2010-06-25  32  extern char sys_cmpxchg[], 
__sys_cmpxchg_end[];
0707ad30 Chris Metcalf 2010-06-25  33  extern char __sys_cmpxchg_grab_lock[];
0707ad30 Chris Metcalf 2010-06-25  34  extern char __start_atomic_asm_code[], 
__end_atomic_asm_code[];
0707ad30 Chris Metcalf 2010-06-25  35  #endif
867e359b Chris Metcalf 2010-05-28  36  
40a3b8df Jiang Liu 2013-07-03  37  /* Handle the discontiguity between 
_sdata and _text. */
867e359b Chris Metcalf 2010-05-28 @38  static inline int 
arch_is_kernel_data(unsigned long addr)
867e359b Chris Metcalf 2010-05-28  39  {
867e359b Chris Metcalf 2010-05-28  40   return addr >= (unsigned long)_sdata &&
867e359b Chris Metcalf 2010-05-28  41   addr < (unsigned long)_end;
867e359b Chris Metcalf 2010-05-28  42  }
867e359b Chris Metcalf 2010-05-28  43  

:: The code at line 18 was first introduced by commit
:: 867e359b97c970a60626d5d76bbe2a8fadbf38fb arch/tile: core support for 
Tilera 32-bit chips.

:: TO: Chris Metcalf 
:: CC: Chris Metcalf 

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


.config.gz
Description: application/gzip


Re: [PATCH v10 3/6] clk: qcom: Add A53 PLL support

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:

> The CPUs on Qualcomm MSM8916-based platforms are clocked by two PLLs,
> a primary (A53) CPU PLL and a secondary fixed-rate GPLL0. These sources
> are connected to a mux and half-integer divider, which is feeding the
> CPU cores.
> 
> This patch adds support for the primary CPU PLL which generates the
> higher range of frequencies above 1GHz.
> 
> Signed-off-by: Georgi Djakov 
> Acked-by: Rob Herring 

Acked-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  .../devicetree/bindings/clock/qcom,a53pll.txt  |  22 +
>  drivers/clk/qcom/Kconfig   |  10 ++
>  drivers/clk/qcom/Makefile  |   1 +
>  drivers/clk/qcom/a53-pll.c | 109 
> +
>  4 files changed, 142 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,a53pll.txt
>  create mode 100644 drivers/clk/qcom/a53-pll.c
> 
> diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.txt 
> b/Documentation/devicetree/bindings/clock/qcom,a53pll.txt
> new file mode 100644
> index ..e3fa8118eaee
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.txt
> @@ -0,0 +1,22 @@
> +Qualcomm MSM8916 A53 PLL Binding
> +
> +The A53 PLL on MSM8916 platforms is the main CPU PLL used used for 
> frequencies
> +above 1GHz.
> +
> +Required properties :
> +- compatible : Shall contain only one of the following:
> +
> + "qcom,msm8916-a53pll"
> +
> +- reg : shall contain base register location and length
> +
> +- #clock-cells : must be set to <0>
> +
> +Example:
> +
> + a53pll: clock@b016000 {
> + compatible = "qcom,msm8916-a53pll";
> + reg = <0xb016000 0x40>;
> + #clock-cells = <0>;
> + };
> +
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index 9f6c278deead..81ac7b9378fe 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -12,6 +12,16 @@ config COMMON_CLK_QCOM
>   select REGMAP_MMIO
>   select RESET_CONTROLLER
>  
> +config QCOM_A53PLL
> + bool "MSM8916 A53 PLL"
> + depends on COMMON_CLK_QCOM
> + default ARCH_QCOM
> + help
> +   Support for the A53 PLL on MSM8916 devices. It provides
> +   the CPU with frequencies above 1GHz.
> +   Say Y if you want to support higher CPU frequencies on MSM8916
> +   devices.
> +
>  config QCOM_CLK_RPM
>   tristate "RPM based Clock Controller"
>   depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 26410d31446b..e767c60c24ec 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -32,5 +32,6 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
>  obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
>  obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
>  obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
> +obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>  obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
>  obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
> diff --git a/drivers/clk/qcom/a53-pll.c b/drivers/clk/qcom/a53-pll.c
> new file mode 100644
> index ..b2bb8e9437f1
> --- /dev/null
> +++ b/drivers/clk/qcom/a53-pll.c
> @@ -0,0 +1,109 @@
> +/*
> + * Copyright (c) 2017, Linaro Limited
> + * Copyright (c) 2014, The Linux Foundation. All rights reserved.
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "clk-pll.h"
> +#include "clk-regmap.h"
> +
> +static const struct pll_freq_tbl a53pll_freq[] = {
> + {  99840, 52, 0x0, 0x1, 0 },
> + { 109440, 57, 0x0, 0x1, 0 },
> + { 115200, 62, 0x0, 0x1, 0 },
> + { 120960, 63, 0x0, 0x1, 0 },
> + { 124800, 65, 0x0, 0x1, 0 },
> + { 136320, 71, 0x0, 0x1, 0 },
> + { 140160, 73, 0x0, 0x1, 0 },
> +};
> +
> +static const struct regmap_config a53pll_regmap_config = {
> + .reg_bits   = 32,
> + .reg_stride = 4,
> + .val_bits   = 32,
> + .max_register   = 0x40,
> + .fast_io= true,
> +};
> +
> +static int qcom_a53pll_remove(struct platform_device *pdev)
> +{
> + of_clk_del_provider(pdev->dev.of_node);
> + return 0;
> +}
> +
> +static int qcom_a53pll_probe(struct platform_device *pdev)
> +{
> + struct device *dev = >dev;
> + struct regmap *regmap;
> + struct resource *res;
> + struct clk_pll *pll;
> + void __iomem *base;
> + struct clk_init_data init = { };
> + int ret;
> +
> + pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
> + if (!pll)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + 

Re: [PATCH v10 3/6] clk: qcom: Add A53 PLL support

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:

> The CPUs on Qualcomm MSM8916-based platforms are clocked by two PLLs,
> a primary (A53) CPU PLL and a secondary fixed-rate GPLL0. These sources
> are connected to a mux and half-integer divider, which is feeding the
> CPU cores.
> 
> This patch adds support for the primary CPU PLL which generates the
> higher range of frequencies above 1GHz.
> 
> Signed-off-by: Georgi Djakov 
> Acked-by: Rob Herring 

Acked-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  .../devicetree/bindings/clock/qcom,a53pll.txt  |  22 +
>  drivers/clk/qcom/Kconfig   |  10 ++
>  drivers/clk/qcom/Makefile  |   1 +
>  drivers/clk/qcom/a53-pll.c | 109 
> +
>  4 files changed, 142 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,a53pll.txt
>  create mode 100644 drivers/clk/qcom/a53-pll.c
> 
> diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.txt 
> b/Documentation/devicetree/bindings/clock/qcom,a53pll.txt
> new file mode 100644
> index ..e3fa8118eaee
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.txt
> @@ -0,0 +1,22 @@
> +Qualcomm MSM8916 A53 PLL Binding
> +
> +The A53 PLL on MSM8916 platforms is the main CPU PLL used used for 
> frequencies
> +above 1GHz.
> +
> +Required properties :
> +- compatible : Shall contain only one of the following:
> +
> + "qcom,msm8916-a53pll"
> +
> +- reg : shall contain base register location and length
> +
> +- #clock-cells : must be set to <0>
> +
> +Example:
> +
> + a53pll: clock@b016000 {
> + compatible = "qcom,msm8916-a53pll";
> + reg = <0xb016000 0x40>;
> + #clock-cells = <0>;
> + };
> +
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index 9f6c278deead..81ac7b9378fe 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -12,6 +12,16 @@ config COMMON_CLK_QCOM
>   select REGMAP_MMIO
>   select RESET_CONTROLLER
>  
> +config QCOM_A53PLL
> + bool "MSM8916 A53 PLL"
> + depends on COMMON_CLK_QCOM
> + default ARCH_QCOM
> + help
> +   Support for the A53 PLL on MSM8916 devices. It provides
> +   the CPU with frequencies above 1GHz.
> +   Say Y if you want to support higher CPU frequencies on MSM8916
> +   devices.
> +
>  config QCOM_CLK_RPM
>   tristate "RPM based Clock Controller"
>   depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 26410d31446b..e767c60c24ec 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -32,5 +32,6 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
>  obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
>  obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
>  obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
> +obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>  obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
>  obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
> diff --git a/drivers/clk/qcom/a53-pll.c b/drivers/clk/qcom/a53-pll.c
> new file mode 100644
> index ..b2bb8e9437f1
> --- /dev/null
> +++ b/drivers/clk/qcom/a53-pll.c
> @@ -0,0 +1,109 @@
> +/*
> + * Copyright (c) 2017, Linaro Limited
> + * Copyright (c) 2014, The Linux Foundation. All rights reserved.
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "clk-pll.h"
> +#include "clk-regmap.h"
> +
> +static const struct pll_freq_tbl a53pll_freq[] = {
> + {  99840, 52, 0x0, 0x1, 0 },
> + { 109440, 57, 0x0, 0x1, 0 },
> + { 115200, 62, 0x0, 0x1, 0 },
> + { 120960, 63, 0x0, 0x1, 0 },
> + { 124800, 65, 0x0, 0x1, 0 },
> + { 136320, 71, 0x0, 0x1, 0 },
> + { 140160, 73, 0x0, 0x1, 0 },
> +};
> +
> +static const struct regmap_config a53pll_regmap_config = {
> + .reg_bits   = 32,
> + .reg_stride = 4,
> + .val_bits   = 32,
> + .max_register   = 0x40,
> + .fast_io= true,
> +};
> +
> +static int qcom_a53pll_remove(struct platform_device *pdev)
> +{
> + of_clk_del_provider(pdev->dev.of_node);
> + return 0;
> +}
> +
> +static int qcom_a53pll_probe(struct platform_device *pdev)
> +{
> + struct device *dev = >dev;
> + struct regmap *regmap;
> + struct resource *res;
> + struct clk_pll *pll;
> + void __iomem *base;
> + struct clk_init_data init = { };
> + int ret;
> +
> + pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
> + if (!pll)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + regmap = devm_regmap_init_mmio(dev, base, _regmap_config);
> + 

Re: [PATCH v10 2/6] mailbox: qcom: Create APCS child device for clock controller

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:

> There is a clock controller functionality provided by the APCS hardware
> block of msm8916 devices. The device-tree would represent an APCS node
> with both mailbox and clock provider properties.
> Create a platform child device for the clock controller functionality so
> the driver can probe and use APCS as parent.
> 
> Signed-off-by: Georgi Djakov 

Acked-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  drivers/mailbox/qcom-apcs-ipc-mailbox.c | 11 +++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c 
> b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
> index ab344bc6fa63..57bde0dfd12f 100644
> --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
> +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
> @@ -29,6 +29,7 @@ struct qcom_apcs_ipc {
>  
>   struct regmap *regmap;
>   unsigned long offset;
> + struct platform_device *clk;
>  };
>  
>  static const struct regmap_config apcs_regmap_config = {
> @@ -96,6 +97,14 @@ static int qcom_apcs_ipc_probe(struct platform_device 
> *pdev)
>   return ret;
>   }
>  
> + if (of_device_is_compatible(np, "qcom,msm8916-apcs-kpss-global")) {
> + apcs->clk = platform_device_register_data(>dev,
> +   
> "qcom-apcs-msm8916-clk",
> +   -1, NULL, 0);
> + if (IS_ERR(apcs->clk))
> + dev_err(>dev, "failed to register APCS clk\n");
> + }
> +
>   platform_set_drvdata(pdev, apcs);
>  
>   return 0;
> @@ -104,8 +113,10 @@ static int qcom_apcs_ipc_probe(struct platform_device 
> *pdev)
>  static int qcom_apcs_ipc_remove(struct platform_device *pdev)
>  {
>   struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
> + struct platform_device *clk = apcs->clk;
>  
>   mbox_controller_unregister(>mbox);
> + platform_device_unregister(clk);
>  
>   return 0;
>  }


Re: [PATCH v10 2/6] mailbox: qcom: Create APCS child device for clock controller

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:

> There is a clock controller functionality provided by the APCS hardware
> block of msm8916 devices. The device-tree would represent an APCS node
> with both mailbox and clock provider properties.
> Create a platform child device for the clock controller functionality so
> the driver can probe and use APCS as parent.
> 
> Signed-off-by: Georgi Djakov 

Acked-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  drivers/mailbox/qcom-apcs-ipc-mailbox.c | 11 +++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c 
> b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
> index ab344bc6fa63..57bde0dfd12f 100644
> --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
> +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
> @@ -29,6 +29,7 @@ struct qcom_apcs_ipc {
>  
>   struct regmap *regmap;
>   unsigned long offset;
> + struct platform_device *clk;
>  };
>  
>  static const struct regmap_config apcs_regmap_config = {
> @@ -96,6 +97,14 @@ static int qcom_apcs_ipc_probe(struct platform_device 
> *pdev)
>   return ret;
>   }
>  
> + if (of_device_is_compatible(np, "qcom,msm8916-apcs-kpss-global")) {
> + apcs->clk = platform_device_register_data(>dev,
> +   
> "qcom-apcs-msm8916-clk",
> +   -1, NULL, 0);
> + if (IS_ERR(apcs->clk))
> + dev_err(>dev, "failed to register APCS clk\n");
> + }
> +
>   platform_set_drvdata(pdev, apcs);
>  
>   return 0;
> @@ -104,8 +113,10 @@ static int qcom_apcs_ipc_probe(struct platform_device 
> *pdev)
>  static int qcom_apcs_ipc_remove(struct platform_device *pdev)
>  {
>   struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
> + struct platform_device *clk = apcs->clk;
>  
>   mbox_controller_unregister(>mbox);
> + platform_device_unregister(clk);
>  
>   return 0;
>  }


Re: [PATCH v10 6/6] clk: qcom: Add APCS clock controller support

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:
[..]
> diff --git a/drivers/clk/qcom/apcs-msm8916.c b/drivers/clk/qcom/apcs-msm8916.c
> new file mode 100644
> index ..f71039ff2347
> --- /dev/null
> +++ b/drivers/clk/qcom/apcs-msm8916.c
> @@ -0,0 +1,149 @@
> +/*
> + * Qualcomm APCS clock controller driver
> + *
> + * Copyright (c) 2017, Linaro Limited
> + * Author: Georgi Djakov 
> + *
> + * SPDX-License-Identifier: GPL-2.0

The SPDX-License-Identifier should be on the first line in the file,
commented by //

> + */
> +
[..]
> +static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
> +{
> + struct device *dev = pdev->dev.parent;

Call this "parent" instead.

> + struct device_node *np = dev->of_node;
> + struct clk_regmap_mux_div *a53cc;
> + struct regmap *regmap;
> + struct clk_init_data init = { };
> + int ret;
> +
> + regmap = dev_get_regmap(dev, NULL);
> + if (IS_ERR(regmap)) {
> + ret = PTR_ERR(regmap);
> + dev_err(dev, "failed to get regmap: %d\n", ret);

dev_* prints should be on >dev and not on parent device.

> + return ret;
> + }
> +
> + a53cc = devm_kzalloc(dev, sizeof(*a53cc), GFP_KERNEL);

Perform this allocation on behalf of this device (i.e. >dev and
not parent)

> + if (!a53cc)
> + return -ENOMEM;
> +
> + init.name = "a53mux";
> + init.parent_names = gpll0_a53cc;
> + init.num_parents = ARRAY_SIZE(gpll0_a53cc);
> + init.ops = _regmap_mux_div_ops;
> + init.flags = CLK_SET_RATE_PARENT;
> +
> + a53cc->clkr.hw.init = 
> + a53cc->clkr.regmap = regmap;
> + a53cc->reg_offset = 0x50;
> + a53cc->hid_width = 5;
> + a53cc->hid_shift = 0;
> + a53cc->src_width = 3;
> + a53cc->src_shift = 8;
> + a53cc->parent_map = gpll0_a53cc_map;
> +
> + a53cc->pclk = devm_clk_get(dev, NULL);
> + if (IS_ERR(a53cc->pclk)) {
> + ret = PTR_ERR(a53cc->pclk);
> + dev_err(dev, "failed to get clk: %d\n", ret);
> + return ret;
> + }
> +
> + a53cc->clk_nb.notifier_call = a53cc_notifier_cb;
> + ret = clk_notifier_register(a53cc->pclk, >clk_nb);
> + if (ret) {
> + dev_err(dev, "failed to register clock notifier: %d\n", ret);
> + return ret;
> + }
> +
> + ret = devm_clk_register_regmap(dev, >clkr);

This you can do on the >dev, it won't find a regmap on this node
and will try the parent.

> + if (ret) {
> + dev_err(dev, "failed to register regmap clock: %d\n", ret);
> + goto err;
> + }
> +
> + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get,

Be explicit here and do parent->of_node.

> +  >clkr.hw);
> + if (ret) {
> + dev_err(dev, "failed to add clock provider: %d\n", ret);
> + goto err;
> + }
> +
> + platform_set_drvdata(pdev, a53cc);
> +
> + return 0;
> +
> +err:
> + clk_notifier_unregister(a53cc->pclk, >clk_nb);
> + return ret;
> +}
> +
> +static int qcom_apcs_msm8916_clk_remove(struct platform_device *pdev)
> +{
> + struct clk_regmap_mux_div *a53cc = platform_get_drvdata(pdev);
> +
> + clk_notifier_unregister(a53cc->pclk, >clk_nb);
> + of_clk_del_provider(pdev->dev.of_node);

You registered the provider on pdev->dev->parent.of_node.

> +
> + return 0;
> +}
> +

Regards,
Bjorn


Re: [PATCH v10 6/6] clk: qcom: Add APCS clock controller support

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:
[..]
> diff --git a/drivers/clk/qcom/apcs-msm8916.c b/drivers/clk/qcom/apcs-msm8916.c
> new file mode 100644
> index ..f71039ff2347
> --- /dev/null
> +++ b/drivers/clk/qcom/apcs-msm8916.c
> @@ -0,0 +1,149 @@
> +/*
> + * Qualcomm APCS clock controller driver
> + *
> + * Copyright (c) 2017, Linaro Limited
> + * Author: Georgi Djakov 
> + *
> + * SPDX-License-Identifier: GPL-2.0

The SPDX-License-Identifier should be on the first line in the file,
commented by //

> + */
> +
[..]
> +static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
> +{
> + struct device *dev = pdev->dev.parent;

Call this "parent" instead.

> + struct device_node *np = dev->of_node;
> + struct clk_regmap_mux_div *a53cc;
> + struct regmap *regmap;
> + struct clk_init_data init = { };
> + int ret;
> +
> + regmap = dev_get_regmap(dev, NULL);
> + if (IS_ERR(regmap)) {
> + ret = PTR_ERR(regmap);
> + dev_err(dev, "failed to get regmap: %d\n", ret);

dev_* prints should be on >dev and not on parent device.

> + return ret;
> + }
> +
> + a53cc = devm_kzalloc(dev, sizeof(*a53cc), GFP_KERNEL);

Perform this allocation on behalf of this device (i.e. >dev and
not parent)

> + if (!a53cc)
> + return -ENOMEM;
> +
> + init.name = "a53mux";
> + init.parent_names = gpll0_a53cc;
> + init.num_parents = ARRAY_SIZE(gpll0_a53cc);
> + init.ops = _regmap_mux_div_ops;
> + init.flags = CLK_SET_RATE_PARENT;
> +
> + a53cc->clkr.hw.init = 
> + a53cc->clkr.regmap = regmap;
> + a53cc->reg_offset = 0x50;
> + a53cc->hid_width = 5;
> + a53cc->hid_shift = 0;
> + a53cc->src_width = 3;
> + a53cc->src_shift = 8;
> + a53cc->parent_map = gpll0_a53cc_map;
> +
> + a53cc->pclk = devm_clk_get(dev, NULL);
> + if (IS_ERR(a53cc->pclk)) {
> + ret = PTR_ERR(a53cc->pclk);
> + dev_err(dev, "failed to get clk: %d\n", ret);
> + return ret;
> + }
> +
> + a53cc->clk_nb.notifier_call = a53cc_notifier_cb;
> + ret = clk_notifier_register(a53cc->pclk, >clk_nb);
> + if (ret) {
> + dev_err(dev, "failed to register clock notifier: %d\n", ret);
> + return ret;
> + }
> +
> + ret = devm_clk_register_regmap(dev, >clkr);

This you can do on the >dev, it won't find a regmap on this node
and will try the parent.

> + if (ret) {
> + dev_err(dev, "failed to register regmap clock: %d\n", ret);
> + goto err;
> + }
> +
> + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get,

Be explicit here and do parent->of_node.

> +  >clkr.hw);
> + if (ret) {
> + dev_err(dev, "failed to add clock provider: %d\n", ret);
> + goto err;
> + }
> +
> + platform_set_drvdata(pdev, a53cc);
> +
> + return 0;
> +
> +err:
> + clk_notifier_unregister(a53cc->pclk, >clk_nb);
> + return ret;
> +}
> +
> +static int qcom_apcs_msm8916_clk_remove(struct platform_device *pdev)
> +{
> + struct clk_regmap_mux_div *a53cc = platform_get_drvdata(pdev);
> +
> + clk_notifier_unregister(a53cc->pclk, >clk_nb);
> + of_clk_del_provider(pdev->dev.of_node);

You registered the provider on pdev->dev->parent.of_node.

> +
> + return 0;
> +}
> +

Regards,
Bjorn


Re: [LKP] [lkp-robot] [fs/locks] 52306e882f: stress-ng.lockofd.ops_per_sec -11% regression

2017-12-04 Thread Aaron Lu
On Wed, Nov 08, 2017 at 03:22:33PM +0800, Aaron Lu wrote:
> On Thu, Sep 28, 2017 at 04:02:23PM +0800, kernel test robot wrote:
> > 
> > Greeting,
> > 
> > FYI, we noticed a -11% regression of stress-ng.lockofd.ops_per_sec due to 
> > commit:
> > 
> > 
> > commit: 52306e882f77d3fd73f91435c41373d634acc5d2 ("fs/locks: Use allocation 
> > rather than the stack in fcntl_getlk()")
> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
> 
> It's been a while, I wonder what do you think of this regression?
> 
> The test stresses byte-range locks AFAICS and since the commit uses
> dynamic allocation instead of stack for the 'struct file_lock', it sounds
> natural the performance regressed for this test.
> 
> Now the question is, do we care about the performance regression here?

Appreciated it if you can share your opinion on this, thanks.

Regards,
Aaron
 
> Feel free to let me know if you need any other data.
> 
> Thanks for your time.
> 
> > in testcase: stress-ng
> > on test machine: 88 threads Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz with 
> > 128G memory
> > with following parameters:
> > 
> > testtime: 1s
> > class: filesystem
> > cpufreq_governor: performance
> > 
> > 
> > 
> > 
> > Details are as below:
> > -->
> > 
> > 
> > To reproduce:
> > 
> > git clone https://github.com/intel/lkp-tests.git
> > cd lkp-tests
> > bin/lkp install job.yaml  # job file is attached in this email
> > bin/lkp run job.yaml
> > 
> > testcase/path_params/tbox_group/run: 
> > stress-ng/1s-filesystem-performance/lkp-bdw-ep6
> > 
> >v4.13-rc1  52306e882f77d3fd73f91435c4  
> >   --  
> >  %stddev  change %stddev
> >  \  |\  
> >  1.219e+08 -11%   1.09e+08stress-ng.lockofd.ops_per_sec
> >  1.229e+08 -10%  1.103e+08stress-ng.locka.ops_per_sec
> >  1.233e+08 -10%  1.105e+08stress-ng.locka.ops
> >  1.223e+08 -11%  1.093e+08stress-ng.lockofd.ops
> >1061237  10%1168476stress-ng.eventfd.ops
> >1061205  10%1168414stress-ng.eventfd.ops_per_sec
> >2913174   9%3163165
> > stress-ng.time.voluntary_context_switches
> >  89.90  -4%  86.58stress-ng.time.user_time
> >  26510  -6%  24822stress-ng.io.ops
> >  26489  -6%  24798stress-ng.io.ops_per_sec
> > 885499 ± 14%18%1042236perf-stat.cpu-migrations
> >  2.537e+08  10%  2.783e+08perf-stat.node-store-misses
> >1067830 ±  4% 8%1154877 ±  3%  perf-stat.page-faults
> >5384755 ±  4% 7%5747689perf-stat.context-switches
> >  32.28   7%  34.42 ±  3%  
> > perf-stat.node-store-miss-rate%
> >  12245 ±110% -7e+03   5367 ± 29%  
> > latency_stats.avg.call_usermodehelper_exec.__request_module.get_fs_type.do_mount.SyS_mount.entry_SYSCALL_64_fastpath
> > 311261 ±173% -3e+05  11702 ±100%  
> > latency_stats.avg.tty_release_struct.tty_release.__fput.fput.task_work_run.exit_to_usermode_loop.syscall_return_slowpath.entry_SYSCALL_64_fastpath
> >   1472 ± 60%  4e+03   5144 ± 97%  
> > latency_stats.max.sync_inodes_sb.sync_inodes_one_sb.iterate_supers.sys_sync.entry_SYSCALL_64_fastpath
> >225 ± 39%  3e+03   3698 ±132%  
> > latency_stats.max.rpc_wait_bit_killable.__rpc_wait_for_completion_task.nfs4_do_close.[nfsv4].__nfs4_close.[nfsv4].nfs4_close_sync.[nfsv4].nfs4_close_context.[nfsv4].__put_nfs_open_context.nfs_file_clear_open_context.nfs_file_release.__fput.fput.task_work_run
> >228 ± 34%  3e+03   3103 ±159%  
> > latency_stats.max.rpc_wait_bit_killable.__rpc_wait_for_completion_task.nfs4_run_open_task.[nfsv4].nfs4_do_open.[nfsv4].nfs4_atomic_open.[nfsv4].nfs4_file_open.[nfsv4].do_dentry_open.vfs_open.path_openat.do_filp_open.do_sys_open.SyS_open
> >270 ± 24%  3e+03   3110 ±162%  
> > latency_stats.max.io_schedule.wait_on_page_bit_common.__filemap_fdatawait_range.filemap_write_and_wait_range.nfs_file_fsync.vfs_fsync_range.vfs_fsync.nfs4_file_flush.[nfsv4].filp_close.do_dup2.SyS_dup2.entry_SYSCALL_64_fastpath
> >  12245 ±110% -7e+03   5367 ± 29%  
> > latency_stats.max.call_usermodehelper_exec.__request_module.get_fs_type.do_mount.SyS_mount.entry_SYSCALL_64_fastpath
> > 927506 ±173% -9e+05  11702 ±100%  
> > latency_stats.max.tty_release_struct.tty_release.__fput.fput.task_work_run.exit_to_usermode_loop.syscall_return_slowpath.entry_SYSCALL_64_fastpath
> >   7892 ± 54%  3e+04  33793 ±131%  
> > 

Re: [LKP] [lkp-robot] [fs/locks] 52306e882f: stress-ng.lockofd.ops_per_sec -11% regression

2017-12-04 Thread Aaron Lu
On Wed, Nov 08, 2017 at 03:22:33PM +0800, Aaron Lu wrote:
> On Thu, Sep 28, 2017 at 04:02:23PM +0800, kernel test robot wrote:
> > 
> > Greeting,
> > 
> > FYI, we noticed a -11% regression of stress-ng.lockofd.ops_per_sec due to 
> > commit:
> > 
> > 
> > commit: 52306e882f77d3fd73f91435c41373d634acc5d2 ("fs/locks: Use allocation 
> > rather than the stack in fcntl_getlk()")
> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
> 
> It's been a while, I wonder what do you think of this regression?
> 
> The test stresses byte-range locks AFAICS and since the commit uses
> dynamic allocation instead of stack for the 'struct file_lock', it sounds
> natural the performance regressed for this test.
> 
> Now the question is, do we care about the performance regression here?

Appreciated it if you can share your opinion on this, thanks.

Regards,
Aaron
 
> Feel free to let me know if you need any other data.
> 
> Thanks for your time.
> 
> > in testcase: stress-ng
> > on test machine: 88 threads Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz with 
> > 128G memory
> > with following parameters:
> > 
> > testtime: 1s
> > class: filesystem
> > cpufreq_governor: performance
> > 
> > 
> > 
> > 
> > Details are as below:
> > -->
> > 
> > 
> > To reproduce:
> > 
> > git clone https://github.com/intel/lkp-tests.git
> > cd lkp-tests
> > bin/lkp install job.yaml  # job file is attached in this email
> > bin/lkp run job.yaml
> > 
> > testcase/path_params/tbox_group/run: 
> > stress-ng/1s-filesystem-performance/lkp-bdw-ep6
> > 
> >v4.13-rc1  52306e882f77d3fd73f91435c4  
> >   --  
> >  %stddev  change %stddev
> >  \  |\  
> >  1.219e+08 -11%   1.09e+08stress-ng.lockofd.ops_per_sec
> >  1.229e+08 -10%  1.103e+08stress-ng.locka.ops_per_sec
> >  1.233e+08 -10%  1.105e+08stress-ng.locka.ops
> >  1.223e+08 -11%  1.093e+08stress-ng.lockofd.ops
> >1061237  10%1168476stress-ng.eventfd.ops
> >1061205  10%1168414stress-ng.eventfd.ops_per_sec
> >2913174   9%3163165
> > stress-ng.time.voluntary_context_switches
> >  89.90  -4%  86.58stress-ng.time.user_time
> >  26510  -6%  24822stress-ng.io.ops
> >  26489  -6%  24798stress-ng.io.ops_per_sec
> > 885499 ± 14%18%1042236perf-stat.cpu-migrations
> >  2.537e+08  10%  2.783e+08perf-stat.node-store-misses
> >1067830 ±  4% 8%1154877 ±  3%  perf-stat.page-faults
> >5384755 ±  4% 7%5747689perf-stat.context-switches
> >  32.28   7%  34.42 ±  3%  
> > perf-stat.node-store-miss-rate%
> >  12245 ±110% -7e+03   5367 ± 29%  
> > latency_stats.avg.call_usermodehelper_exec.__request_module.get_fs_type.do_mount.SyS_mount.entry_SYSCALL_64_fastpath
> > 311261 ±173% -3e+05  11702 ±100%  
> > latency_stats.avg.tty_release_struct.tty_release.__fput.fput.task_work_run.exit_to_usermode_loop.syscall_return_slowpath.entry_SYSCALL_64_fastpath
> >   1472 ± 60%  4e+03   5144 ± 97%  
> > latency_stats.max.sync_inodes_sb.sync_inodes_one_sb.iterate_supers.sys_sync.entry_SYSCALL_64_fastpath
> >225 ± 39%  3e+03   3698 ±132%  
> > latency_stats.max.rpc_wait_bit_killable.__rpc_wait_for_completion_task.nfs4_do_close.[nfsv4].__nfs4_close.[nfsv4].nfs4_close_sync.[nfsv4].nfs4_close_context.[nfsv4].__put_nfs_open_context.nfs_file_clear_open_context.nfs_file_release.__fput.fput.task_work_run
> >228 ± 34%  3e+03   3103 ±159%  
> > latency_stats.max.rpc_wait_bit_killable.__rpc_wait_for_completion_task.nfs4_run_open_task.[nfsv4].nfs4_do_open.[nfsv4].nfs4_atomic_open.[nfsv4].nfs4_file_open.[nfsv4].do_dentry_open.vfs_open.path_openat.do_filp_open.do_sys_open.SyS_open
> >270 ± 24%  3e+03   3110 ±162%  
> > latency_stats.max.io_schedule.wait_on_page_bit_common.__filemap_fdatawait_range.filemap_write_and_wait_range.nfs_file_fsync.vfs_fsync_range.vfs_fsync.nfs4_file_flush.[nfsv4].filp_close.do_dup2.SyS_dup2.entry_SYSCALL_64_fastpath
> >  12245 ±110% -7e+03   5367 ± 29%  
> > latency_stats.max.call_usermodehelper_exec.__request_module.get_fs_type.do_mount.SyS_mount.entry_SYSCALL_64_fastpath
> > 927506 ±173% -9e+05  11702 ±100%  
> > latency_stats.max.tty_release_struct.tty_release.__fput.fput.task_work_run.exit_to_usermode_loop.syscall_return_slowpath.entry_SYSCALL_64_fastpath
> >   7892 ± 54%  3e+04  33793 ±131%  
> > 

[PATCHv2 2/2] mtd: m25p80: restore the status of SPI flash when stop using it

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Implement .shutdown function to restore the status in reboot
process, and add the same operation to the .remove function.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed code format slightly.

 drivers/mtd/devices/m25p80.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..a4e18f6aaa33 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore(>spi_nor);
+
/* Clean up MTD stuff. */
return mtd_device_unregister(>spi_nor.mtd);
 }
 
+static void m25p_shutdown(struct spi_device *spi)
+{
+   struct m25p *flash = spi_get_drvdata(spi);
+
+   spi_nor_restore(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = {
.id_table   = m25p_ids,
.probe  = m25p_probe,
.remove = m25p_remove,
+   .shutdown   = m25p_shutdown,
 
/* REVISIT: many of these chips have deep power-down modes, which
 * should clearly be entered on suspend() to minimize power use.
-- 
2.14.1



[PATCHv2 2/2] mtd: m25p80: restore the status of SPI flash when stop using it

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Implement .shutdown function to restore the status in reboot
process, and add the same operation to the .remove function.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed code format slightly.

 drivers/mtd/devices/m25p80.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..a4e18f6aaa33 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore(>spi_nor);
+
/* Clean up MTD stuff. */
return mtd_device_unregister(>spi_nor.mtd);
 }
 
+static void m25p_shutdown(struct spi_device *spi)
+{
+   struct m25p *flash = spi_get_drvdata(spi);
+
+   spi_nor_restore(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = {
.id_table   = m25p_ids,
.probe  = m25p_probe,
.remove = m25p_remove,
+   .shutdown   = m25p_shutdown,
 
/* REVISIT: many of these chips have deep power-down modes, which
 * should clearly be entered on suspend() to minimize power use.
-- 
2.14.1



[PATCHv2 1/2] mtd: spi-nor: add an API to restore the status of SPI flash chip

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add this API to restore the status of SPI flash chip to the default
such as addressing mode, whenever detach the driver from device or
reboot the system.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed the API name and added the comments and kernel document for it.
 - Export this symbol for modules.

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt
index 548d6306ebca..da1fbff5a24c 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.txt
@@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a 
driver should
 initialize the necessary fields for spi_nor{}. Please see
 drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
 when you want to write a new driver for a SPI NOR controller.
+Another API is spi_nor_restore(), this is used to restore the status of SPI
+flash chip such as addressing mode. Call it whenever detach the driver from
+device or reboot the system.
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..4a925378d434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,16 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore(struct spi_nor *nor)
+{
+   /* restore the addressing mode */
+   if ((nor->addr_width == 4) &&
+   (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+   !(nor->info->flags & SPI_NOR_4B_OPCODES))
+   set_4byte(nor, nor->info, 0);
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps)
 {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d0c66a0975cf..0a182c3d0884 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -399,4 +399,10 @@ struct spi_nor_hwcaps {
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
 
+/*
+ * spi_nor_restore_addr_mode() - restore the status of SPI NOR
+ * @nor:   the spi_nor structure
+ */
+void spi_nor_restore(struct spi_nor *nor);
+
 #endif
-- 
2.14.1



[PATCHv2 1/2] mtd: spi-nor: add an API to restore the status of SPI flash chip

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add this API to restore the status of SPI flash chip to the default
such as addressing mode, whenever detach the driver from device or
reboot the system.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed the API name and added the comments and kernel document for it.
 - Export this symbol for modules.

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt
index 548d6306ebca..da1fbff5a24c 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.txt
@@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a 
driver should
 initialize the necessary fields for spi_nor{}. Please see
 drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
 when you want to write a new driver for a SPI NOR controller.
+Another API is spi_nor_restore(), this is used to restore the status of SPI
+flash chip such as addressing mode. Call it whenever detach the driver from
+device or reboot the system.
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..4a925378d434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,16 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore(struct spi_nor *nor)
+{
+   /* restore the addressing mode */
+   if ((nor->addr_width == 4) &&
+   (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+   !(nor->info->flags & SPI_NOR_4B_OPCODES))
+   set_4byte(nor, nor->info, 0);
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps)
 {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d0c66a0975cf..0a182c3d0884 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -399,4 +399,10 @@ struct spi_nor_hwcaps {
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
 
+/*
+ * spi_nor_restore_addr_mode() - restore the status of SPI NOR
+ * @nor:   the spi_nor structure
+ */
+void spi_nor_restore(struct spi_nor *nor);
+
 #endif
-- 
2.14.1



[PATCHv2 0/2] mtd: m25p80: restore the addressing mode when stop using the flash

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

To be compatible with legacy device, reset the addressing mode
to the default mode. Such as Freescale eSPI boot, it copies the
images from SPI flash without firing a reset signal previously,
so the reboot command will fail without reseting the addressing
mode of SPI flash.

Hou Zhiqiang (2):
  mtd: spi-nor: add an API to restore the status of SPI flash chip
  mtd: m25p80: restore the status of SPI flash when stop using it

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/devices/m25p80.c  |  9 +
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 4 files changed, 28 insertions(+)

-- 
2.14.1



[PATCHv2 0/2] mtd: m25p80: restore the addressing mode when stop using the flash

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

To be compatible with legacy device, reset the addressing mode
to the default mode. Such as Freescale eSPI boot, it copies the
images from SPI flash without firing a reset signal previously,
so the reboot command will fail without reseting the addressing
mode of SPI flash.

Hou Zhiqiang (2):
  mtd: spi-nor: add an API to restore the status of SPI flash chip
  mtd: m25p80: restore the status of SPI flash when stop using it

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/devices/m25p80.c  |  9 +
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 4 files changed, 28 insertions(+)

-- 
2.14.1



Re: [PATCH v10 5/6] dt-bindings: mailbox: qcom: Document the APCS clock binding

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:

> Update the binding documentation for APCS to mention that the APCS
> hardware block also expose a clock controller functionality.
> 
> The APCS clock controller is a mux and half-integer divider. It has the
> main CPU PLL as an input and provides the clock for the application CPU.
> 
> Signed-off-by: Georgi Djakov 

Nice!

Acked-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  .../bindings/mailbox/qcom,apcs-kpss-global.txt | 18 
> ++
>  1 file changed, 18 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt 
> b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
> index fb961c310f44..16964f0c1773 100644
> --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
> +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
> @@ -15,12 +15,21 @@ platforms.
>   Usage: required
>   Value type: 
>   Definition: must specify the base address and size of the global block
> +- clocks:
> + Usage: required if #clocks-cells property is present
> + Value type: 
> + Definition: phandle to the input PLL, which feeds the APCS mux/divider
>  
>  - #mbox-cells:
>   Usage: required
>   Value type: 
>   Definition: as described in mailbox.txt, must be 1
>  
> +- #clock-cells:
> + Usage: optional
> + Value type: 
> + Definition: as described in clock.txt, must be 0
> +
>  
>  = EXAMPLE
>  The following example describes the APCS HMSS found in MSM8996 and part of 
> the
> @@ -44,3 +53,12 @@ GLINK RPM referencing the "rpm_hlos" doorbell therein.
>   mbox-names = "rpm_hlos";
>   };
>  
> +Below is another example of the APCS binding on MSM8916 platforms:
> +
> + apcs: mailbox@b011000 {
> + compatible = "qcom,msm8916-apcs-kpss-global";
> + reg = <0xb011000 0x1000>;
> + #mbox-cells = <1>;
> + clocks = <>;
> + #clock-cells = <0>;
> + };


Re: [PATCH v10 5/6] dt-bindings: mailbox: qcom: Document the APCS clock binding

2017-12-04 Thread Bjorn Andersson
On Fri 01 Dec 09:02 PST 2017, Georgi Djakov wrote:

> Update the binding documentation for APCS to mention that the APCS
> hardware block also expose a clock controller functionality.
> 
> The APCS clock controller is a mux and half-integer divider. It has the
> main CPU PLL as an input and provides the clock for the application CPU.
> 
> Signed-off-by: Georgi Djakov 

Nice!

Acked-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  .../bindings/mailbox/qcom,apcs-kpss-global.txt | 18 
> ++
>  1 file changed, 18 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt 
> b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
> index fb961c310f44..16964f0c1773 100644
> --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
> +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
> @@ -15,12 +15,21 @@ platforms.
>   Usage: required
>   Value type: 
>   Definition: must specify the base address and size of the global block
> +- clocks:
> + Usage: required if #clocks-cells property is present
> + Value type: 
> + Definition: phandle to the input PLL, which feeds the APCS mux/divider
>  
>  - #mbox-cells:
>   Usage: required
>   Value type: 
>   Definition: as described in mailbox.txt, must be 1
>  
> +- #clock-cells:
> + Usage: optional
> + Value type: 
> + Definition: as described in clock.txt, must be 0
> +
>  
>  = EXAMPLE
>  The following example describes the APCS HMSS found in MSM8996 and part of 
> the
> @@ -44,3 +53,12 @@ GLINK RPM referencing the "rpm_hlos" doorbell therein.
>   mbox-names = "rpm_hlos";
>   };
>  
> +Below is another example of the APCS binding on MSM8916 platforms:
> +
> + apcs: mailbox@b011000 {
> + compatible = "qcom,msm8916-apcs-kpss-global";
> + reg = <0xb011000 0x1000>;
> + #mbox-cells = <1>;
> + clocks = <>;
> + #clock-cells = <0>;
> + };


Re: [PATCH v2 0/4] lockdep/crossrelease: Apply crossrelease to page locks

2017-12-04 Thread Byungchul Park

On 12/5/2017 2:30 PM, Matthew Wilcox wrote:

On Mon, Dec 04, 2017 at 02:16:19PM +0900, Byungchul Park wrote:

For now, wait_for_completion() / complete() works with lockdep, add
lock_page() / unlock_page() and its family to lockdep support.

Changes from v1
  - Move lockdep_map_cross outside of page_ext to make it flexible
  - Prevent allocating lockdep_map per page by default
  - Add a boot parameter allowing the allocation for debugging

Byungchul Park (4):
   lockdep: Apply crossrelease to PG_locked locks
   lockdep: Apply lock_acquire(release) on __Set(__Clear)PageLocked
   lockdep: Move data of CONFIG_LOCKDEP_PAGELOCK from page to page_ext
   lockdep: Add a boot parameter enabling to track page locks using
 lockdep and disable it by default


I don't like the way you've structured this patch series; first adding
the lockdep map to struct page, then moving it to page_ext.


Hello,

I will make them into one patch.


I also don't like it that you've made CONFIG_LOCKDEP_PAGELOCK not
individually selectable.  I might well want a kernel with crosslock
support, but only for completions.


OK then, I will make it individually selectable.

I want to know others' opinions as well.

Thank you for the opinions. I will apply yours next spin.

--
Thanks,
Byungchul


Re: [PATCH v2 0/4] lockdep/crossrelease: Apply crossrelease to page locks

2017-12-04 Thread Byungchul Park

On 12/5/2017 2:30 PM, Matthew Wilcox wrote:

On Mon, Dec 04, 2017 at 02:16:19PM +0900, Byungchul Park wrote:

For now, wait_for_completion() / complete() works with lockdep, add
lock_page() / unlock_page() and its family to lockdep support.

Changes from v1
  - Move lockdep_map_cross outside of page_ext to make it flexible
  - Prevent allocating lockdep_map per page by default
  - Add a boot parameter allowing the allocation for debugging

Byungchul Park (4):
   lockdep: Apply crossrelease to PG_locked locks
   lockdep: Apply lock_acquire(release) on __Set(__Clear)PageLocked
   lockdep: Move data of CONFIG_LOCKDEP_PAGELOCK from page to page_ext
   lockdep: Add a boot parameter enabling to track page locks using
 lockdep and disable it by default


I don't like the way you've structured this patch series; first adding
the lockdep map to struct page, then moving it to page_ext.


Hello,

I will make them into one patch.


I also don't like it that you've made CONFIG_LOCKDEP_PAGELOCK not
individually selectable.  I might well want a kernel with crosslock
support, but only for completions.


OK then, I will make it individually selectable.

I want to know others' opinions as well.

Thank you for the opinions. I will apply yours next spin.

--
Thanks,
Byungchul


Re: [PATCH v3 07/16] iommu/vt-d: assign PFSID in device TLB invalidation

2017-12-04 Thread Lu Baolu
Hi,

On 11/18/2017 02:55 AM, Jacob Pan wrote:
> When SRIOV VF device IOTLB is invalidated, we need to provide
> the PF source SID such that IOMMU hardware can gauge the depth
> of invalidation queue which is shared among VFs. This is needed
> when device invalidation throttle (DIT) capability is supported.
>
> Signed-off-by: Jacob Pan 
> ---
>  drivers/iommu/intel-iommu.c | 13 +
>  include/linux/intel-iommu.h |  3 +++
>  2 files changed, 16 insertions(+)
>
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 000b2b3..e1bd219 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -1459,6 +1459,19 @@ static void iommu_enable_dev_iotlb(struct 
> device_domain_info *info)
>   return;
>  
>   pdev = to_pci_dev(info->dev);
> + /* For IOMMU that supports device IOTLB throttling (DIT), we assign
> +  * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
> +  * queue depth at PF level. If DIT is not set, PFSID will be treated as
> +  * reserved, which should be set to 0.
> +  */
> + if (!ecap_dit(info->iommu->ecap))
> + info->pfsid = 0;
> + else if (pdev && pdev->is_virtfn) {
> + if (ecap_dit(info->iommu->ecap))

Isn't this condition always true when it comes here?

Best regards,
Lu Baolu

> + dev_warn(>dev, "SRIOV VF device IOTLB enabled 
> without flow control\n");
> + info->pfsid = PCI_DEVID(pdev->physfn->bus->number, 
> pdev->physfn->devfn);
> + } else
> + info->pfsid = PCI_DEVID(info->bus, info->devfn);
>  
>  #ifdef CONFIG_INTEL_IOMMU_SVM
>   /* The PCIe spec, in its wisdom, declares that the behaviour of
> diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
> index 7f05e36..6956a4e 100644
> --- a/include/linux/intel-iommu.h
> +++ b/include/linux/intel-iommu.h
> @@ -112,6 +112,7 @@
>   * Extended Capability Register
>   */
>  
> +#define ecap_dit(e)  ((e >> 41) & 0x1)
>  #define ecap_pasid(e)((e >> 40) & 0x1)
>  #define ecap_pss(e)  ((e >> 35) & 0x1f)
>  #define ecap_eafs(e) ((e >> 34) & 0x1)
> @@ -285,6 +286,7 @@ enum {
>  #define QI_DEV_IOTLB_SID(sid)((u64)((sid) & 0x) << 32)
>  #define QI_DEV_IOTLB_QDEP(qdep)  (((qdep) & 0x1f) << 16)
>  #define QI_DEV_IOTLB_ADDR(addr)  ((u64)(addr) & VTD_PAGE_MASK)
> +#define QI_DEV_IOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid 
> & 0xff0) << 48))
>  #define QI_DEV_IOTLB_SIZE1
>  #define QI_DEV_IOTLB_MAX_INVS32
>  
> @@ -475,6 +477,7 @@ struct device_domain_info {
>   struct list_head global; /* link to global list */
>   u8 bus; /* PCI bus number */
>   u8 devfn;   /* PCI devfn number */
> + u16 pfsid;  /* SRIOV physical function source ID */
>   u8 pasid_supported:3;
>   u8 pasid_enabled:1;
>   u8 pri_supported:1;



Re: [PATCH v3 07/16] iommu/vt-d: assign PFSID in device TLB invalidation

2017-12-04 Thread Lu Baolu
Hi,

On 11/18/2017 02:55 AM, Jacob Pan wrote:
> When SRIOV VF device IOTLB is invalidated, we need to provide
> the PF source SID such that IOMMU hardware can gauge the depth
> of invalidation queue which is shared among VFs. This is needed
> when device invalidation throttle (DIT) capability is supported.
>
> Signed-off-by: Jacob Pan 
> ---
>  drivers/iommu/intel-iommu.c | 13 +
>  include/linux/intel-iommu.h |  3 +++
>  2 files changed, 16 insertions(+)
>
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 000b2b3..e1bd219 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -1459,6 +1459,19 @@ static void iommu_enable_dev_iotlb(struct 
> device_domain_info *info)
>   return;
>  
>   pdev = to_pci_dev(info->dev);
> + /* For IOMMU that supports device IOTLB throttling (DIT), we assign
> +  * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
> +  * queue depth at PF level. If DIT is not set, PFSID will be treated as
> +  * reserved, which should be set to 0.
> +  */
> + if (!ecap_dit(info->iommu->ecap))
> + info->pfsid = 0;
> + else if (pdev && pdev->is_virtfn) {
> + if (ecap_dit(info->iommu->ecap))

Isn't this condition always true when it comes here?

Best regards,
Lu Baolu

> + dev_warn(>dev, "SRIOV VF device IOTLB enabled 
> without flow control\n");
> + info->pfsid = PCI_DEVID(pdev->physfn->bus->number, 
> pdev->physfn->devfn);
> + } else
> + info->pfsid = PCI_DEVID(info->bus, info->devfn);
>  
>  #ifdef CONFIG_INTEL_IOMMU_SVM
>   /* The PCIe spec, in its wisdom, declares that the behaviour of
> diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
> index 7f05e36..6956a4e 100644
> --- a/include/linux/intel-iommu.h
> +++ b/include/linux/intel-iommu.h
> @@ -112,6 +112,7 @@
>   * Extended Capability Register
>   */
>  
> +#define ecap_dit(e)  ((e >> 41) & 0x1)
>  #define ecap_pasid(e)((e >> 40) & 0x1)
>  #define ecap_pss(e)  ((e >> 35) & 0x1f)
>  #define ecap_eafs(e) ((e >> 34) & 0x1)
> @@ -285,6 +286,7 @@ enum {
>  #define QI_DEV_IOTLB_SID(sid)((u64)((sid) & 0x) << 32)
>  #define QI_DEV_IOTLB_QDEP(qdep)  (((qdep) & 0x1f) << 16)
>  #define QI_DEV_IOTLB_ADDR(addr)  ((u64)(addr) & VTD_PAGE_MASK)
> +#define QI_DEV_IOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid 
> & 0xff0) << 48))
>  #define QI_DEV_IOTLB_SIZE1
>  #define QI_DEV_IOTLB_MAX_INVS32
>  
> @@ -475,6 +477,7 @@ struct device_domain_info {
>   struct list_head global; /* link to global list */
>   u8 bus; /* PCI bus number */
>   u8 devfn;   /* PCI devfn number */
> + u16 pfsid;  /* SRIOV physical function source ID */
>   u8 pasid_supported:3;
>   u8 pasid_enabled:1;
>   u8 pri_supported:1;



Re: [PATCH v3 06/16] iommu/vt-d: add svm/sva invalidate function

2017-12-04 Thread Lu Baolu
Hi,

On 11/18/2017 02:55 AM, Jacob Pan wrote:
> This patch adds Intel VT-d specific function to implement
> iommu passdown invalidate API for shared virtual address.
>
> The use case is for supporting caching structure invalidation
> of assigned SVM capable devices. Emulated IOMMU exposes queue
> invalidation capability and passes down all descriptors from the guest
> to the physical IOMMU.
>
> The assumption is that guest to host device ID mapping should be
> resolved prior to calling IOMMU driver. Based on the device handle,
> host IOMMU driver can replace certain fields before submit to the
> invalidation queue.
>
> Signed-off-by: Liu, Yi L 
> Signed-off-by: Jacob Pan 
> Signed-off-by: Ashok Raj 
> ---
>  drivers/iommu/intel-iommu.c | 200 
> +++-
>  include/linux/intel-iommu.h |  17 +++-
>  2 files changed, 211 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 556bdd2..000b2b3 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -4981,6 +4981,183 @@ static void intel_iommu_detach_device(struct 
> iommu_domain *domain,
>   dmar_remove_one_dev_info(to_dmar_domain(domain), dev);
>  }
>  
> +/*
> + * 3D array for converting IOMMU generic type-granularity to VT-d granularity
> + * X indexed by enum iommu_inv_type
> + * Y indicates request without and with PASID
> + * Z indexed by enum enum iommu_inv_granularity
> + *
> + * For an example, if we want to find the VT-d granularity encoding for IOTLB
> + * type, DMA request with PASID, and page selective. The look up indices are:
> + * [1][1][8], where
> + * 1: IOMMU_INV_TYPE_TLB
> + * 1: with PASID
> + * 8: IOMMU_INV_GRANU_PAGE_PASID
> + *
> + */
> +const static int 
> inv_type_granu_map[IOMMU_INV_NR_TYPE][2][IOMMU_INV_NR_GRANU] = {
> + /* extended dev IOTLBs, for dev-IOTLB, only global is valid,
> +for dev-EXIOTLB, two valid granu */
> + {
> + {1},
> + {0, 0, 0, 0, 1, 1, 0, 0, 0}
> + },
> + /* IOTLB and EIOTLB */
> + {
> + {1, 1, 0, 1, 0, 0, 0, 0, 0},
> + {0, 0, 0, 0, 1, 0, 1, 1, 1}
> + },
> + /* PASID cache */
> + {
> + {0},
> + {0, 0, 0, 0, 1, 1, 0, 0, 0}
> + },
> + /* context cache */
> + {
> + {1, 1, 1}
> + }
> +};
> +
> +const static u64 
> inv_type_granu_table[IOMMU_INV_NR_TYPE][2][IOMMU_INV_NR_GRANU] = {
> + /* extended dev IOTLBs, only global is valid */
> + {
> + {QI_DEV_IOTLB_GRAN_ALL},
> + {0, 0, 0, 0, QI_DEV_IOTLB_GRAN_ALL, 
> QI_DEV_IOTLB_GRAN_PASID_SEL, 0, 0, 0}
> + },
> + /* IOTLB and EIOTLB */
> + {
> + {DMA_TLB_GLOBAL_FLUSH, DMA_TLB_DSI_FLUSH, 0, DMA_TLB_PSI_FLUSH},
> + {0, 0, 0, 0, QI_GRAN_ALL_ALL, 0, QI_GRAN_NONG_ALL, 
> QI_GRAN_NONG_PASID, QI_GRAN_PSI_PASID}
> + },
> + /* PASID cache */
> + {
> + {0},
> + {0, 0, 0, 0, QI_PC_ALL_PASIDS, QI_PC_PASID_SEL}
> + },
> + /* context cache */
> + {
> + {DMA_CCMD_GLOBAL_INVL, DMA_CCMD_DOMAIN_INVL, 
> DMA_CCMD_DEVICE_INVL}
> + }
> +};
> +
> +static inline int to_vtd_granularity(int type, int granu, int with_pasid, 
> u64 *vtd_granu)
> +{
> + if (type >= IOMMU_INV_NR_TYPE || granu >= IOMMU_INV_NR_GRANU || 
> with_pasid > 1)
> + return -EINVAL;
> +
> + if (inv_type_granu_map[type][with_pasid][granu] == 0)
> + return -EINVAL;
> +
> + *vtd_granu = inv_type_granu_table[type][with_pasid][granu];
> +
> + return 0;
> +}
> +
> +static int intel_iommu_sva_invalidate(struct iommu_domain *domain,
> + struct device *dev, struct tlb_invalidate_info *inv_info)
> +{
> + struct intel_iommu *iommu;
> + struct dmar_domain *dmar_domain = to_dmar_domain(domain);
> + struct device_domain_info *info;
> + struct pci_dev *pdev;
> + u16 did, sid, pfsid;
> + u8 bus, devfn;
> + int ret = 0;
> + u64 granu;
> + unsigned long flags;
> +
> + if (!inv_info || !dmar_domain)
> + return -EINVAL;
> +
> + iommu = device_to_iommu(dev, , );
> + if (!iommu)
> + return -ENODEV;
> +
> + if (!dev || !dev_is_pci(dev))
> + return -ENODEV;
> +
> + did = dmar_domain->iommu_did[iommu->seq_id];
> + sid = PCI_DEVID(bus, devfn);
> + ret = to_vtd_granularity(inv_info->hdr.type, inv_info->granularity,
> + !!(inv_info->flags & 
> IOMMU_INVALIDATE_PASID_TAGGED), );
> + if (ret) {
> + pr_err("Invalid range type %d, granu %d\n", inv_info->hdr.type,
> + inv_info->granularity);
> + return ret;
> + }
> +
> + spin_lock(>lock);
> + spin_lock_irqsave(_domain_lock, flags);
> +
> + switch (inv_info->hdr.type) {
> + case IOMMU_INV_TYPE_CONTEXT:

Re: [PATCH v3 06/16] iommu/vt-d: add svm/sva invalidate function

2017-12-04 Thread Lu Baolu
Hi,

On 11/18/2017 02:55 AM, Jacob Pan wrote:
> This patch adds Intel VT-d specific function to implement
> iommu passdown invalidate API for shared virtual address.
>
> The use case is for supporting caching structure invalidation
> of assigned SVM capable devices. Emulated IOMMU exposes queue
> invalidation capability and passes down all descriptors from the guest
> to the physical IOMMU.
>
> The assumption is that guest to host device ID mapping should be
> resolved prior to calling IOMMU driver. Based on the device handle,
> host IOMMU driver can replace certain fields before submit to the
> invalidation queue.
>
> Signed-off-by: Liu, Yi L 
> Signed-off-by: Jacob Pan 
> Signed-off-by: Ashok Raj 
> ---
>  drivers/iommu/intel-iommu.c | 200 
> +++-
>  include/linux/intel-iommu.h |  17 +++-
>  2 files changed, 211 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 556bdd2..000b2b3 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -4981,6 +4981,183 @@ static void intel_iommu_detach_device(struct 
> iommu_domain *domain,
>   dmar_remove_one_dev_info(to_dmar_domain(domain), dev);
>  }
>  
> +/*
> + * 3D array for converting IOMMU generic type-granularity to VT-d granularity
> + * X indexed by enum iommu_inv_type
> + * Y indicates request without and with PASID
> + * Z indexed by enum enum iommu_inv_granularity
> + *
> + * For an example, if we want to find the VT-d granularity encoding for IOTLB
> + * type, DMA request with PASID, and page selective. The look up indices are:
> + * [1][1][8], where
> + * 1: IOMMU_INV_TYPE_TLB
> + * 1: with PASID
> + * 8: IOMMU_INV_GRANU_PAGE_PASID
> + *
> + */
> +const static int 
> inv_type_granu_map[IOMMU_INV_NR_TYPE][2][IOMMU_INV_NR_GRANU] = {
> + /* extended dev IOTLBs, for dev-IOTLB, only global is valid,
> +for dev-EXIOTLB, two valid granu */
> + {
> + {1},
> + {0, 0, 0, 0, 1, 1, 0, 0, 0}
> + },
> + /* IOTLB and EIOTLB */
> + {
> + {1, 1, 0, 1, 0, 0, 0, 0, 0},
> + {0, 0, 0, 0, 1, 0, 1, 1, 1}
> + },
> + /* PASID cache */
> + {
> + {0},
> + {0, 0, 0, 0, 1, 1, 0, 0, 0}
> + },
> + /* context cache */
> + {
> + {1, 1, 1}
> + }
> +};
> +
> +const static u64 
> inv_type_granu_table[IOMMU_INV_NR_TYPE][2][IOMMU_INV_NR_GRANU] = {
> + /* extended dev IOTLBs, only global is valid */
> + {
> + {QI_DEV_IOTLB_GRAN_ALL},
> + {0, 0, 0, 0, QI_DEV_IOTLB_GRAN_ALL, 
> QI_DEV_IOTLB_GRAN_PASID_SEL, 0, 0, 0}
> + },
> + /* IOTLB and EIOTLB */
> + {
> + {DMA_TLB_GLOBAL_FLUSH, DMA_TLB_DSI_FLUSH, 0, DMA_TLB_PSI_FLUSH},
> + {0, 0, 0, 0, QI_GRAN_ALL_ALL, 0, QI_GRAN_NONG_ALL, 
> QI_GRAN_NONG_PASID, QI_GRAN_PSI_PASID}
> + },
> + /* PASID cache */
> + {
> + {0},
> + {0, 0, 0, 0, QI_PC_ALL_PASIDS, QI_PC_PASID_SEL}
> + },
> + /* context cache */
> + {
> + {DMA_CCMD_GLOBAL_INVL, DMA_CCMD_DOMAIN_INVL, 
> DMA_CCMD_DEVICE_INVL}
> + }
> +};
> +
> +static inline int to_vtd_granularity(int type, int granu, int with_pasid, 
> u64 *vtd_granu)
> +{
> + if (type >= IOMMU_INV_NR_TYPE || granu >= IOMMU_INV_NR_GRANU || 
> with_pasid > 1)
> + return -EINVAL;
> +
> + if (inv_type_granu_map[type][with_pasid][granu] == 0)
> + return -EINVAL;
> +
> + *vtd_granu = inv_type_granu_table[type][with_pasid][granu];
> +
> + return 0;
> +}
> +
> +static int intel_iommu_sva_invalidate(struct iommu_domain *domain,
> + struct device *dev, struct tlb_invalidate_info *inv_info)
> +{
> + struct intel_iommu *iommu;
> + struct dmar_domain *dmar_domain = to_dmar_domain(domain);
> + struct device_domain_info *info;
> + struct pci_dev *pdev;
> + u16 did, sid, pfsid;
> + u8 bus, devfn;
> + int ret = 0;
> + u64 granu;
> + unsigned long flags;
> +
> + if (!inv_info || !dmar_domain)
> + return -EINVAL;
> +
> + iommu = device_to_iommu(dev, , );
> + if (!iommu)
> + return -ENODEV;
> +
> + if (!dev || !dev_is_pci(dev))
> + return -ENODEV;
> +
> + did = dmar_domain->iommu_did[iommu->seq_id];
> + sid = PCI_DEVID(bus, devfn);
> + ret = to_vtd_granularity(inv_info->hdr.type, inv_info->granularity,
> + !!(inv_info->flags & 
> IOMMU_INVALIDATE_PASID_TAGGED), );
> + if (ret) {
> + pr_err("Invalid range type %d, granu %d\n", inv_info->hdr.type,
> + inv_info->granularity);
> + return ret;
> + }
> +
> + spin_lock(>lock);
> + spin_lock_irqsave(_domain_lock, flags);
> +
> + switch (inv_info->hdr.type) {
> + case IOMMU_INV_TYPE_CONTEXT:
> + iommu->flush.flush_context(iommu, did, sid,
> +

Re: [PATCH] cpufreq: powernv: Define methods to parse positive & negative pstates

2017-12-04 Thread Viresh Kumar
On 30-11-17, 10:13, Shilpasri G Bhat wrote:
> From: "Gautham R. Shenoy" 
> 
> Pstates are 8bit values but on POWER8 they are negative and on POWER9
> they are positive. This patch adds helper routines to differentiate
> the sign to read the correct pstate value.
> 
> Signed-off-by: Gautham R. Shenoy 
> Tested-by: Shilpasri G Bhat 
> ---
>  drivers/cpufreq/powernv-cpufreq.c | 43 
> ++-
>  1 file changed, 33 insertions(+), 10 deletions(-)

Acked-by: Viresh Kumar 

-- 
viresh


Re: [PATCH] cpufreq: powernv: Define methods to parse positive & negative pstates

2017-12-04 Thread Viresh Kumar
On 30-11-17, 10:13, Shilpasri G Bhat wrote:
> From: "Gautham R. Shenoy" 
> 
> Pstates are 8bit values but on POWER8 they are negative and on POWER9
> they are positive. This patch adds helper routines to differentiate
> the sign to read the correct pstate value.
> 
> Signed-off-by: Gautham R. Shenoy 
> Tested-by: Shilpasri G Bhat 
> ---
>  drivers/cpufreq/powernv-cpufreq.c | 43 
> ++-
>  1 file changed, 33 insertions(+), 10 deletions(-)

Acked-by: Viresh Kumar 

-- 
viresh


Re: [PATCH 1/1] mm/page_owner: ignore everything below the IRQ entry point

2017-12-04 Thread kbuild test robot
Hi Maninder,

Thank you for the patch! Yet something to improve:

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

url:
https://github.com/0day-ci/linux/commits/Maninder-Singh/mm-page_owner-ignore-everything-below-the-IRQ-entry-point/20171205-122901
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: blackfin-allmodconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=blackfin 

All errors (new ones prefixed by >>):

   In file included from include/linux/interrupt.h:22:0,
from include/linux/kernel_stat.h:9,
from arch/blackfin/kernel/asm-offsets.c:11:
>> arch/blackfin/include/asm/sections.h:35:19: error: redefinition of 
>> 'arch_is_kernel_text'
static inline int arch_is_kernel_text(unsigned long addr)
  ^~~
   In file included from include/linux/stacktrace.h:6:0,
from include/linux/lockdep.h:29,
from include/linux/rcupdate.h:42,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from arch/blackfin/kernel/asm-offsets.c:10:
   include/asm-generic/sections.h:63:19: note: previous definition of 
'arch_is_kernel_text' was here
static inline int arch_is_kernel_text(unsigned long addr)
  ^~~
   In file included from include/linux/interrupt.h:22:0,
from include/linux/kernel_stat.h:9,
from arch/blackfin/kernel/asm-offsets.c:11:
>> arch/blackfin/include/asm/sections.h:48:19: error: redefinition of 
>> 'arch_is_kernel_data'
static inline int arch_is_kernel_data(unsigned long addr)
  ^~~
   In file included from include/linux/stacktrace.h:6:0,
from include/linux/lockdep.h:29,
from include/linux/rcupdate.h:42,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from arch/blackfin/kernel/asm-offsets.c:10:
   include/asm-generic/sections.h:70:19: note: previous definition of 
'arch_is_kernel_data' was here
static inline int arch_is_kernel_data(unsigned long addr)
  ^~~
   make[2]: *** [arch/blackfin/kernel/asm-offsets.s] Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [prepare0] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [sub-make] Error 2

vim +/arch_is_kernel_text +35 arch/blackfin/include/asm/sections.h

e56770fb Mike Frysinger 2009-09-22  33  
e56770fb Mike Frysinger 2009-09-22  34  /* Blackfin systems have discontinuous 
memory map and no virtualized memory */
e56770fb Mike Frysinger 2009-09-22 @35  static inline int 
arch_is_kernel_text(unsigned long addr)
e56770fb Mike Frysinger 2009-09-22  36  {
e56770fb Mike Frysinger 2009-09-22  37  return
e56770fb Mike Frysinger 2009-09-22  38  (L1_CODE_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  39   addr >= (unsigned 
long)_stext_l1 &&
e56770fb Mike Frysinger 2009-09-22  40   addr <  (unsigned 
long)_etext_l1)
e56770fb Mike Frysinger 2009-09-22  41  ||
e56770fb Mike Frysinger 2009-09-22  42  (L2_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  43   addr >= (unsigned 
long)_stext_l2 &&
e56770fb Mike Frysinger 2009-09-22  44   addr <  (unsigned 
long)_etext_l2);
e56770fb Mike Frysinger 2009-09-22  45  }
e56770fb Mike Frysinger 2009-09-22  46  #define arch_is_kernel_text(addr) 
arch_is_kernel_text(addr)
e56770fb Mike Frysinger 2009-09-22  47  
e56770fb Mike Frysinger 2009-09-22 @48  static inline int 
arch_is_kernel_data(unsigned long addr)
e56770fb Mike Frysinger 2009-09-22  49  {
e56770fb Mike Frysinger 2009-09-22  50  return
e56770fb Mike Frysinger 2009-09-22  51  (L1_DATA_A_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  52   addr >= (unsigned 
long)_sdata_l1 &&
e56770fb Mike Frysinger 2009-09-22  53   addr <  (unsigned 
long)_ebss_l1)
e56770fb Mike Frysinger 2009-09-22  54  ||
e56770fb Mike Frysinger 2009-09-22  55  (L1_DATA_B_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  56   addr >= (unsigned 
long)_sdata_b_l1 &&
e56770fb 

Re: [PATCH 1/1] mm/page_owner: ignore everything below the IRQ entry point

2017-12-04 Thread kbuild test robot
Hi Maninder,

Thank you for the patch! Yet something to improve:

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

url:
https://github.com/0day-ci/linux/commits/Maninder-Singh/mm-page_owner-ignore-everything-below-the-IRQ-entry-point/20171205-122901
base:   git://git.cmpxchg.org/linux-mmotm.git master
config: blackfin-allmodconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=blackfin 

All errors (new ones prefixed by >>):

   In file included from include/linux/interrupt.h:22:0,
from include/linux/kernel_stat.h:9,
from arch/blackfin/kernel/asm-offsets.c:11:
>> arch/blackfin/include/asm/sections.h:35:19: error: redefinition of 
>> 'arch_is_kernel_text'
static inline int arch_is_kernel_text(unsigned long addr)
  ^~~
   In file included from include/linux/stacktrace.h:6:0,
from include/linux/lockdep.h:29,
from include/linux/rcupdate.h:42,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from arch/blackfin/kernel/asm-offsets.c:10:
   include/asm-generic/sections.h:63:19: note: previous definition of 
'arch_is_kernel_text' was here
static inline int arch_is_kernel_text(unsigned long addr)
  ^~~
   In file included from include/linux/interrupt.h:22:0,
from include/linux/kernel_stat.h:9,
from arch/blackfin/kernel/asm-offsets.c:11:
>> arch/blackfin/include/asm/sections.h:48:19: error: redefinition of 
>> 'arch_is_kernel_data'
static inline int arch_is_kernel_data(unsigned long addr)
  ^~~
   In file included from include/linux/stacktrace.h:6:0,
from include/linux/lockdep.h:29,
from include/linux/rcupdate.h:42,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from arch/blackfin/kernel/asm-offsets.c:10:
   include/asm-generic/sections.h:70:19: note: previous definition of 
'arch_is_kernel_data' was here
static inline int arch_is_kernel_data(unsigned long addr)
  ^~~
   make[2]: *** [arch/blackfin/kernel/asm-offsets.s] Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [prepare0] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [sub-make] Error 2

vim +/arch_is_kernel_text +35 arch/blackfin/include/asm/sections.h

e56770fb Mike Frysinger 2009-09-22  33  
e56770fb Mike Frysinger 2009-09-22  34  /* Blackfin systems have discontinuous 
memory map and no virtualized memory */
e56770fb Mike Frysinger 2009-09-22 @35  static inline int 
arch_is_kernel_text(unsigned long addr)
e56770fb Mike Frysinger 2009-09-22  36  {
e56770fb Mike Frysinger 2009-09-22  37  return
e56770fb Mike Frysinger 2009-09-22  38  (L1_CODE_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  39   addr >= (unsigned 
long)_stext_l1 &&
e56770fb Mike Frysinger 2009-09-22  40   addr <  (unsigned 
long)_etext_l1)
e56770fb Mike Frysinger 2009-09-22  41  ||
e56770fb Mike Frysinger 2009-09-22  42  (L2_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  43   addr >= (unsigned 
long)_stext_l2 &&
e56770fb Mike Frysinger 2009-09-22  44   addr <  (unsigned 
long)_etext_l2);
e56770fb Mike Frysinger 2009-09-22  45  }
e56770fb Mike Frysinger 2009-09-22  46  #define arch_is_kernel_text(addr) 
arch_is_kernel_text(addr)
e56770fb Mike Frysinger 2009-09-22  47  
e56770fb Mike Frysinger 2009-09-22 @48  static inline int 
arch_is_kernel_data(unsigned long addr)
e56770fb Mike Frysinger 2009-09-22  49  {
e56770fb Mike Frysinger 2009-09-22  50  return
e56770fb Mike Frysinger 2009-09-22  51  (L1_DATA_A_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  52   addr >= (unsigned 
long)_sdata_l1 &&
e56770fb Mike Frysinger 2009-09-22  53   addr <  (unsigned 
long)_ebss_l1)
e56770fb Mike Frysinger 2009-09-22  54  ||
e56770fb Mike Frysinger 2009-09-22  55  (L1_DATA_B_LENGTH &&
e56770fb Mike Frysinger 2009-09-22  56   addr >= (unsigned 
long)_sdata_b_l1 &&
e56770fb 

Re: [PATCH V1 4/4] qcom: spmi-wled: Add auto-calibration logic support

2017-12-04 Thread Bjorn Andersson
On Thu 16 Nov 04:18 PST 2017, Kiran Gunda wrote:

> The auto-calibration algorithm checks if the current WLED sink
> configuration is valid. It tries enabling every sink and checks
> if the OVP fault is observed. Based on this information it
> detects and enables the valid sink configuration. Auto calibration
> will be triggered when the OVP fault interrupts are seen frequently
> thereby it tries to fix the sink configuration.
> 

So it's not auto "calibration" it's auto "detection" of strings?

When is this feature needed?

> Signed-off-by: Kiran Gunda 
> ---
>  .../bindings/leds/backlight/qcom-spmi-wled.txt |   5 +
>  drivers/video/backlight/qcom-spmi-wled.c   | 304 
> -
>  2 files changed, 306 insertions(+), 3 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt 
> b/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt
> index d39ee93..f06c0cd 100644
> --- a/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt
> +++ b/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt
> @@ -94,6 +94,11 @@ The PMIC is connected to the host processor via SPMI bus.
>   Definition: Interrupt names associated with the interrupts.
>   Currently supported interrupts are "sc-irq" and "ovp-irq".
>  
> +- qcom,auto-calibration

qcom,auto-string-detect?

> + Usage:  optional
> + Value type: 
> + Definition: Enables auto-calibration of the WLED sink configuration.
> +
>  Example:
>  
>  qcom-wled@d800 {
> diff --git a/drivers/video/backlight/qcom-spmi-wled.c 
> b/drivers/video/backlight/qcom-spmi-wled.c
> index 8b2a77a..aee5c56 100644
> --- a/drivers/video/backlight/qcom-spmi-wled.c
> +++ b/drivers/video/backlight/qcom-spmi-wled.c
> @@ -38,11 +38,14 @@
>  #define  QCOM_WLED_CTRL_SC_FAULT_BIT BIT(2)
>  
>  #define QCOM_WLED_CTRL_INT_RT_STS0x10
> +#define  QCOM_WLED_CTRL_OVP_FLT_RT_STS_BIT   BIT(1)

The use of BIT() makes this a mask and not a bit number, so if you just
drop that you can afford to spell out the "FAULT" like the data sheet
does. Perhaps even making it QCOM_WLED_CTRL_OVP_FAULT_STATUS ?

>  
>  #define QCOM_WLED_CTRL_MOD_ENABLE0x46
>  #define  QCOM_WLED_CTRL_MOD_EN_MASK  BIT(7)
>  #define  QCOM_WLED_CTRL_MODULE_EN_SHIFT  7
>  
> +#define QCOM_WLED_CTRL_FDBK_OP   0x48

This is called WLED_CTRL_FEEDBACK_CONTROL, why the need to make it
unreadable?

> +
>  #define QCOM_WLED_CTRL_SWITCH_FREQ   0x4c
>  #define  QCOM_WLED_CTRL_SWITCH_FREQ_MASK GENMASK(3, 0)
>  
> @@ -99,6 +102,7 @@ struct qcom_wled_config {
>   int ovp_irq;
>   bool en_cabc;
>   bool ext_pfet_sc_pro_en;
> + bool auto_calib_enabled;
>  };
>  
>  struct qcom_wled {
> @@ -108,18 +112,25 @@ struct qcom_wled {
>   struct mutex lock;
>   struct qcom_wled_config cfg;
>   ktime_t last_sc_event_time;
> + ktime_t start_ovp_fault_time;
>   u16 sink_addr;
>   u16 ctrl_addr;
> + u16 auto_calibration_ovp_count;
>   u32 brightness;
>   u32 sc_count;
>   bool prev_state;
>   bool ovp_irq_disabled;
> + bool auto_calib_done;
> + bool force_mod_disable;
>  };
>  
>  static int qcom_wled_module_enable(struct qcom_wled *wled, int val)
>  {
>   int rc;
>  
> + if (wled->force_mod_disable)
> + return 0;
> +
>   rc = regmap_update_bits(wled->regmap, wled->ctrl_addr +
>   QCOM_WLED_CTRL_MOD_ENABLE, QCOM_WLED_CTRL_MOD_EN_MASK,
>   val << QCOM_WLED_CTRL_MODULE_EN_SHIFT);
> @@ -187,12 +198,10 @@ static int qcom_wled_set_brightness(struct qcom_wled 
> *wled, u16 brightness)
>   v[1] = (brightness >> 8) & 0xf;
>  
>   for (i = 0; (string_cfg >> i) != 0; i++) {
> - if (string_cfg & BIT(i)) {

Why was this check here in the first place, if it's now fine to
configure the brightness of all strings?

Also, a single-string config of 0b0001 will only set brightness on the
first string, while 0b1000 will set brightness on all strings.

>   rc = regmap_bulk_write(wled->regmap, wled->sink_addr +
>   QCOM_WLED_SINK_BRIGHT_LSB_REG(i), v, 2);
>   if (rc < 0)
>   return rc;
> - }
>   }
>  
>   return 0;
> @@ -294,6 +303,262 @@ static irqreturn_t qcom_wled_sc_irq_handler(int irq, 
> void *_wled)
>   return IRQ_HANDLED;
>  }
>  
> +#define AUTO_CALIB_BRIGHTNESS200
> +static int qcom_wled_auto_calibrate(struct qcom_wled *wled)
> +{
> + int rc = 0, i;
> + u32 sink_config = 0, int_sts;
> + u8 reg = 0, sink_test = 0, sink_valid = 0;
> + u8 string_cfg = wled->cfg.string_cfg;
> +
> + /* read configured sink configuration */
> + rc = regmap_read(wled->regmap, wled->sink_addr +
> + QCOM_WLED_SINK_CURR_SINK_EN, 

Re: [PATCH V1 4/4] qcom: spmi-wled: Add auto-calibration logic support

2017-12-04 Thread Bjorn Andersson
On Thu 16 Nov 04:18 PST 2017, Kiran Gunda wrote:

> The auto-calibration algorithm checks if the current WLED sink
> configuration is valid. It tries enabling every sink and checks
> if the OVP fault is observed. Based on this information it
> detects and enables the valid sink configuration. Auto calibration
> will be triggered when the OVP fault interrupts are seen frequently
> thereby it tries to fix the sink configuration.
> 

So it's not auto "calibration" it's auto "detection" of strings?

When is this feature needed?

> Signed-off-by: Kiran Gunda 
> ---
>  .../bindings/leds/backlight/qcom-spmi-wled.txt |   5 +
>  drivers/video/backlight/qcom-spmi-wled.c   | 304 
> -
>  2 files changed, 306 insertions(+), 3 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt 
> b/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt
> index d39ee93..f06c0cd 100644
> --- a/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt
> +++ b/Documentation/devicetree/bindings/leds/backlight/qcom-spmi-wled.txt
> @@ -94,6 +94,11 @@ The PMIC is connected to the host processor via SPMI bus.
>   Definition: Interrupt names associated with the interrupts.
>   Currently supported interrupts are "sc-irq" and "ovp-irq".
>  
> +- qcom,auto-calibration

qcom,auto-string-detect?

> + Usage:  optional
> + Value type: 
> + Definition: Enables auto-calibration of the WLED sink configuration.
> +
>  Example:
>  
>  qcom-wled@d800 {
> diff --git a/drivers/video/backlight/qcom-spmi-wled.c 
> b/drivers/video/backlight/qcom-spmi-wled.c
> index 8b2a77a..aee5c56 100644
> --- a/drivers/video/backlight/qcom-spmi-wled.c
> +++ b/drivers/video/backlight/qcom-spmi-wled.c
> @@ -38,11 +38,14 @@
>  #define  QCOM_WLED_CTRL_SC_FAULT_BIT BIT(2)
>  
>  #define QCOM_WLED_CTRL_INT_RT_STS0x10
> +#define  QCOM_WLED_CTRL_OVP_FLT_RT_STS_BIT   BIT(1)

The use of BIT() makes this a mask and not a bit number, so if you just
drop that you can afford to spell out the "FAULT" like the data sheet
does. Perhaps even making it QCOM_WLED_CTRL_OVP_FAULT_STATUS ?

>  
>  #define QCOM_WLED_CTRL_MOD_ENABLE0x46
>  #define  QCOM_WLED_CTRL_MOD_EN_MASK  BIT(7)
>  #define  QCOM_WLED_CTRL_MODULE_EN_SHIFT  7
>  
> +#define QCOM_WLED_CTRL_FDBK_OP   0x48

This is called WLED_CTRL_FEEDBACK_CONTROL, why the need to make it
unreadable?

> +
>  #define QCOM_WLED_CTRL_SWITCH_FREQ   0x4c
>  #define  QCOM_WLED_CTRL_SWITCH_FREQ_MASK GENMASK(3, 0)
>  
> @@ -99,6 +102,7 @@ struct qcom_wled_config {
>   int ovp_irq;
>   bool en_cabc;
>   bool ext_pfet_sc_pro_en;
> + bool auto_calib_enabled;
>  };
>  
>  struct qcom_wled {
> @@ -108,18 +112,25 @@ struct qcom_wled {
>   struct mutex lock;
>   struct qcom_wled_config cfg;
>   ktime_t last_sc_event_time;
> + ktime_t start_ovp_fault_time;
>   u16 sink_addr;
>   u16 ctrl_addr;
> + u16 auto_calibration_ovp_count;
>   u32 brightness;
>   u32 sc_count;
>   bool prev_state;
>   bool ovp_irq_disabled;
> + bool auto_calib_done;
> + bool force_mod_disable;
>  };
>  
>  static int qcom_wled_module_enable(struct qcom_wled *wled, int val)
>  {
>   int rc;
>  
> + if (wled->force_mod_disable)
> + return 0;
> +
>   rc = regmap_update_bits(wled->regmap, wled->ctrl_addr +
>   QCOM_WLED_CTRL_MOD_ENABLE, QCOM_WLED_CTRL_MOD_EN_MASK,
>   val << QCOM_WLED_CTRL_MODULE_EN_SHIFT);
> @@ -187,12 +198,10 @@ static int qcom_wled_set_brightness(struct qcom_wled 
> *wled, u16 brightness)
>   v[1] = (brightness >> 8) & 0xf;
>  
>   for (i = 0; (string_cfg >> i) != 0; i++) {
> - if (string_cfg & BIT(i)) {

Why was this check here in the first place, if it's now fine to
configure the brightness of all strings?

Also, a single-string config of 0b0001 will only set brightness on the
first string, while 0b1000 will set brightness on all strings.

>   rc = regmap_bulk_write(wled->regmap, wled->sink_addr +
>   QCOM_WLED_SINK_BRIGHT_LSB_REG(i), v, 2);
>   if (rc < 0)
>   return rc;
> - }
>   }
>  
>   return 0;
> @@ -294,6 +303,262 @@ static irqreturn_t qcom_wled_sc_irq_handler(int irq, 
> void *_wled)
>   return IRQ_HANDLED;
>  }
>  
> +#define AUTO_CALIB_BRIGHTNESS200
> +static int qcom_wled_auto_calibrate(struct qcom_wled *wled)
> +{
> + int rc = 0, i;
> + u32 sink_config = 0, int_sts;
> + u8 reg = 0, sink_test = 0, sink_valid = 0;
> + u8 string_cfg = wled->cfg.string_cfg;
> +
> + /* read configured sink configuration */
> + rc = regmap_read(wled->regmap, wled->sink_addr +
> + QCOM_WLED_SINK_CURR_SINK_EN, _config);
> + if (rc 

[PATCH V2 3/4] cpu_cooling: Keep only one of_cpufreq*cooling_register() helper

2017-12-04 Thread Viresh Kumar
of_cpufreq_cooling_register() isn't used by anyone and so can be
removed, but then we would be left with two routines:
cpufreq_cooling_register() and of_cpufreq_power_cooling_register() that
would look odd.

Remove current implementation of of_cpufreq_cooling_register() and
rename of_cpufreq_power_cooling_register() as
of_cpufreq_cooling_register(). This simplifies lots of stuff.

Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 Documentation/thermal/cpu-cooling-api.txt | 14 ++--
 drivers/cpufreq/arm_big_little.c  |  2 +-
 drivers/cpufreq/cpufreq-dt.c  |  2 +-
 drivers/cpufreq/mediatek-cpufreq.c|  2 +-
 drivers/cpufreq/qoriq-cpufreq.c   |  2 +-
 drivers/thermal/cpu_cooling.c | 28 ++--
 include/linux/cpu_cooling.h   | 53 ---
 7 files changed, 23 insertions(+), 80 deletions(-)

diff --git a/Documentation/thermal/cpu-cooling-api.txt 
b/Documentation/thermal/cpu-cooling-api.txt
index ea61e8bf7e2b..7a1c89db0419 100644
--- a/Documentation/thermal/cpu-cooling-api.txt
+++ b/Documentation/thermal/cpu-cooling-api.txt
@@ -26,24 +26,16 @@ the user. The registration APIs returns the cooling device 
pointer.
clip_cpus: cpumask of cpus where the frequency constraints will happen.
 
 1.1.2 struct thermal_cooling_device *of_cpufreq_cooling_register(
-   struct device_node *np, const struct cpumask *clip_cpus)
+   struct cpufreq_policy *policy)
 
 This interface function registers the cpufreq cooling device with
 the name "thermal-cpufreq-%x" linking it with a device tree node, in
 order to bind it via the thermal DT code. This api can support multiple
 instances of cpufreq cooling devices.
 
-np: pointer to the cooling device device tree node
-clip_cpus: cpumask of cpus where the frequency constraints will happen.
-
-1.1.3 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
-   struct cpufreq_policy *policy)
-
-Similar to cpufreq_cooling_register, this function register a
-cpufreq cooling device with power extensions using the device tree
-information supplied by the np parameter.
+policy: CPUFreq policy.
 
-1.1.4 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
+1.1.3 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 This interface function unregisters the "thermal-cpufreq-%x" cooling 
device.
 
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 3d5ed4ef3927..c56b57dcfda5 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -532,7 +532,7 @@ static void bL_cpufreq_ready(struct cpufreq_policy *policy)
if (cur_cluster >= MAX_CLUSTERS)
return;
 
-   cdev[cur_cluster] = of_cpufreq_power_cooling_register(policy);
+   cdev[cur_cluster] = of_cpufreq_cooling_register(policy);
 }
 
 static struct cpufreq_driver bL_cpufreq_driver = {
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 1e7bec7694ab..de3d104c25d7 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -320,7 +320,7 @@ static void cpufreq_ready(struct cpufreq_policy *policy)
 {
struct private_data *priv = policy->driver_data;
 
-   priv->cdev = of_cpufreq_power_cooling_register(policy);
+   priv->cdev = of_cpufreq_cooling_register(policy);
 }
 
 static struct cpufreq_driver dt_cpufreq_driver = {
diff --git a/drivers/cpufreq/mediatek-cpufreq.c 
b/drivers/cpufreq/mediatek-cpufreq.c
index 6ff783e1b18a..f95975b76d98 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -311,7 +311,7 @@ static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
 {
struct mtk_cpu_dvfs_info *info = policy->driver_data;
 
-   info->cdev = of_cpufreq_power_cooling_register(policy);
+   info->cdev = of_cpufreq_cooling_register(policy);
 }
 
 static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 3a665c18e14e..0562761a3dec 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -276,7 +276,7 @@ static void qoriq_cpufreq_ready(struct cpufreq_policy 
*policy)
 {
struct cpu_data *cpud = policy->driver_data;
 
-   cpud->cdev = of_cpufreq_power_cooling_register(policy);
+   cpud->cdev = of_cpufreq_cooling_register(policy);
 }
 
 static struct cpufreq_driver qoriq_cpufreq_driver = {
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 10199f7e1196..3371caf3095c 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -819,7 +819,6 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
 
 /**
  * of_cpufreq_cooling_register - function to create cpufreq cooling 

[PATCH V2 1/4] cpu_cooling: Make of_cpufreq_power_cooling_register() parse DT

2017-12-04 Thread Viresh Kumar
All the callers of of_cpufreq_power_cooling_register() have almost
identical code and it makes more sense to move that code into the helper
as its all about reading DT properties.

This got rid of lot of redundant code.

Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 Documentation/thermal/cpu-cooling-api.txt |  7 ++---
 drivers/cpufreq/arm_big_little.c  | 23 +--
 drivers/cpufreq/cpufreq-dt.c  | 27 +
 drivers/cpufreq/mediatek-cpufreq.c| 22 +-
 drivers/cpufreq/qoriq-cpufreq.c   | 14 +
 drivers/thermal/cpu_cooling.c | 49 +++
 include/linux/cpu_cooling.h   | 15 ++
 7 files changed, 41 insertions(+), 116 deletions(-)

diff --git a/Documentation/thermal/cpu-cooling-api.txt 
b/Documentation/thermal/cpu-cooling-api.txt
index 71653584cd03..4f6f5e9bb4d6 100644
--- a/Documentation/thermal/cpu-cooling-api.txt
+++ b/Documentation/thermal/cpu-cooling-api.txt
@@ -51,8 +51,7 @@ Dynamic power).  "plat_static_func" is a function to 
calculate the
 static power consumed by these cpus (See 2.2 Static power).
 
 1.1.4 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
-struct device_node *np, const struct cpumask *clip_cpus, u32 capacitance,
-get_static_t plat_static_func)
+   struct cpufreq_policy *policy)
 
 Similar to cpufreq_power_cooling_register, this function register a
 cpufreq cooling device with power extensions using the device tree
@@ -76,8 +75,8 @@ cpu.  If you are using CONFIG_CPUFREQ_DT then the
 device.
 
 The `plat_static_func` parameter of `cpufreq_power_cooling_register()`
-and `of_cpufreq_power_cooling_register()` is optional.  If you don't
-provide it, only dynamic power will be considered.
+is optional.  If you don't provide it, only dynamic power will be
+considered.
 
 2.1 Dynamic power
 
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 65ec5f01aa8d..3d5ed4ef3927 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -526,34 +526,13 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
 
 static void bL_cpufreq_ready(struct cpufreq_policy *policy)
 {
-   struct device *cpu_dev = get_cpu_device(policy->cpu);
int cur_cluster = cpu_to_cluster(policy->cpu);
-   struct device_node *np;
 
/* Do not register a cpu_cooling device if we are in IKS mode */
if (cur_cluster >= MAX_CLUSTERS)
return;
 
-   np = of_node_get(cpu_dev->of_node);
-   if (WARN_ON(!np))
-   return;
-
-   if (of_find_property(np, "#cooling-cells", NULL)) {
-   u32 power_coefficient = 0;
-
-   of_property_read_u32(np, "dynamic-power-coefficient",
-_coefficient);
-
-   cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
-   policy, power_coefficient, NULL);
-   if (IS_ERR(cdev[cur_cluster])) {
-   dev_err(cpu_dev,
-   "running cpufreq without cooling device: %ld\n",
-   PTR_ERR(cdev[cur_cluster]));
-   cdev[cur_cluster] = NULL;
-   }
-   }
-   of_node_put(np);
+   cdev[cur_cluster] = of_cpufreq_power_cooling_register(policy);
 }
 
 static struct cpufreq_driver bL_cpufreq_driver = {
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 545946ad0752..1e7bec7694ab 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -319,33 +319,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
 static void cpufreq_ready(struct cpufreq_policy *policy)
 {
struct private_data *priv = policy->driver_data;
-   struct device_node *np = of_node_get(priv->cpu_dev->of_node);
 
-   if (WARN_ON(!np))
-   return;
-
-   /*
-* For now, just loading the cooling device;
-* thermal DT code takes care of matching them.
-*/
-   if (of_find_property(np, "#cooling-cells", NULL)) {
-   u32 power_coefficient = 0;
-
-   of_property_read_u32(np, "dynamic-power-coefficient",
-_coefficient);
-
-   priv->cdev = of_cpufreq_power_cooling_register(np,
-   policy, power_coefficient, NULL);
-   if (IS_ERR(priv->cdev)) {
-   dev_err(priv->cpu_dev,
-   "running cpufreq without cooling device: %ld\n",
-   PTR_ERR(priv->cdev));
-
-   priv->cdev = NULL;
-   }
-   }
-
-   of_node_put(np);
+   priv->cdev = of_cpufreq_power_cooling_register(policy);
 }
 
 static struct cpufreq_driver dt_cpufreq_driver = {
diff 

[PATCH V2 4/4] cpu_cooling: Drop static-power related stuff

2017-12-04 Thread Viresh Kumar
No one has used it for the last two and half years (since it was
introduced by commit c36cf0717631 ("thermal: cpu_cooling: implement the
power cooling device API")), get rid of it.

Cc: Javi Merino 
Cc: Punit Agrawal 
Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c  | 106 +
 include/linux/cpu_cooling.h|   3 --
 include/trace/events/thermal.h |  10 ++--
 3 files changed, 16 insertions(+), 103 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 3371caf3095c..dfd23245f778 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -88,7 +88,6 @@ struct time_in_idle {
  * @policy: cpufreq policy.
  * @node: list_head to link all cpufreq_cooling_device together.
  * @idle_time: idle time stats
- * @plat_get_static_power: callback to calculate the static power
  *
  * This structure is required for keeping information of each registered
  * cpufreq_cooling_device.
@@ -104,7 +103,6 @@ struct cpufreq_cooling_device {
struct cpufreq_policy *policy;
struct list_head node;
struct time_in_idle *idle_time;
-   get_static_t plat_get_static_power;
 };
 
 static DEFINE_IDA(cpufreq_ida);
@@ -319,60 +317,6 @@ static u32 get_load(struct cpufreq_cooling_device 
*cpufreq_cdev, int cpu,
 }
 
 /**
- * get_static_power() - calculate the static power consumed by the cpus
- * @cpufreq_cdev:  struct _cooling_device for this cpu cdev
- * @tz:thermal zone device in which we're operating
- * @freq:  frequency in KHz
- * @power: pointer in which to store the calculated static power
- *
- * Calculate the static power consumed by the cpus described by
- * @cpu_actor running at frequency @freq.  This function relies on a
- * platform specific function that should have been provided when the
- * actor was registered.  If it wasn't, the static power is assumed to
- * be negligible.  The calculated static power is stored in @power.
- *
- * Return: 0 on success, -E* on failure.
- */
-static int get_static_power(struct cpufreq_cooling_device *cpufreq_cdev,
-   struct thermal_zone_device *tz, unsigned long freq,
-   u32 *power)
-{
-   struct dev_pm_opp *opp;
-   unsigned long voltage;
-   struct cpufreq_policy *policy = cpufreq_cdev->policy;
-   struct cpumask *cpumask = policy->related_cpus;
-   unsigned long freq_hz = freq * 1000;
-   struct device *dev;
-
-   if (!cpufreq_cdev->plat_get_static_power) {
-   *power = 0;
-   return 0;
-   }
-
-   dev = get_cpu_device(policy->cpu);
-   WARN_ON(!dev);
-
-   opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true);
-   if (IS_ERR(opp)) {
-   dev_warn_ratelimited(dev, "Failed to find OPP for frequency 
%lu: %ld\n",
-freq_hz, PTR_ERR(opp));
-   return -EINVAL;
-   }
-
-   voltage = dev_pm_opp_get_voltage(opp);
-   dev_pm_opp_put(opp);
-
-   if (voltage == 0) {
-   dev_err_ratelimited(dev, "Failed to get voltage for frequency 
%lu\n",
-   freq_hz);
-   return -EINVAL;
-   }
-
-   return cpufreq_cdev->plat_get_static_power(cpumask, tz->passive_delay,
- voltage, power);
-}
-
-/**
  * get_dynamic_power() - calculate the dynamic power
  * @cpufreq_cdev:  _cooling_device for this cdev
  * @freq:  current frequency
@@ -491,8 +435,8 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
   u32 *power)
 {
unsigned long freq;
-   int i = 0, cpu, ret;
-   u32 static_power, dynamic_power, total_load = 0;
+   int i = 0, cpu;
+   u32 total_load = 0;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpufreq_policy *policy = cpufreq_cdev->policy;
u32 *load_cpu = NULL;
@@ -522,22 +466,15 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
 
cpufreq_cdev->last_load = total_load;
 
-   dynamic_power = get_dynamic_power(cpufreq_cdev, freq);
-   ret = get_static_power(cpufreq_cdev, tz, freq, _power);
-   if (ret) {
-   kfree(load_cpu);
-   return ret;
-   }
+   *power = get_dynamic_power(cpufreq_cdev, freq);
 
if (load_cpu) {
trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
- load_cpu, i, dynamic_power,
- static_power);
+ load_cpu, i, *power);
 
kfree(load_cpu);
}
 
-   *power = static_power + dynamic_power;
 

[PATCH V2 3/4] cpu_cooling: Keep only one of_cpufreq*cooling_register() helper

2017-12-04 Thread Viresh Kumar
of_cpufreq_cooling_register() isn't used by anyone and so can be
removed, but then we would be left with two routines:
cpufreq_cooling_register() and of_cpufreq_power_cooling_register() that
would look odd.

Remove current implementation of of_cpufreq_cooling_register() and
rename of_cpufreq_power_cooling_register() as
of_cpufreq_cooling_register(). This simplifies lots of stuff.

Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 Documentation/thermal/cpu-cooling-api.txt | 14 ++--
 drivers/cpufreq/arm_big_little.c  |  2 +-
 drivers/cpufreq/cpufreq-dt.c  |  2 +-
 drivers/cpufreq/mediatek-cpufreq.c|  2 +-
 drivers/cpufreq/qoriq-cpufreq.c   |  2 +-
 drivers/thermal/cpu_cooling.c | 28 ++--
 include/linux/cpu_cooling.h   | 53 ---
 7 files changed, 23 insertions(+), 80 deletions(-)

diff --git a/Documentation/thermal/cpu-cooling-api.txt 
b/Documentation/thermal/cpu-cooling-api.txt
index ea61e8bf7e2b..7a1c89db0419 100644
--- a/Documentation/thermal/cpu-cooling-api.txt
+++ b/Documentation/thermal/cpu-cooling-api.txt
@@ -26,24 +26,16 @@ the user. The registration APIs returns the cooling device 
pointer.
clip_cpus: cpumask of cpus where the frequency constraints will happen.
 
 1.1.2 struct thermal_cooling_device *of_cpufreq_cooling_register(
-   struct device_node *np, const struct cpumask *clip_cpus)
+   struct cpufreq_policy *policy)
 
 This interface function registers the cpufreq cooling device with
 the name "thermal-cpufreq-%x" linking it with a device tree node, in
 order to bind it via the thermal DT code. This api can support multiple
 instances of cpufreq cooling devices.
 
-np: pointer to the cooling device device tree node
-clip_cpus: cpumask of cpus where the frequency constraints will happen.
-
-1.1.3 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
-   struct cpufreq_policy *policy)
-
-Similar to cpufreq_cooling_register, this function register a
-cpufreq cooling device with power extensions using the device tree
-information supplied by the np parameter.
+policy: CPUFreq policy.
 
-1.1.4 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
+1.1.3 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 This interface function unregisters the "thermal-cpufreq-%x" cooling 
device.
 
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 3d5ed4ef3927..c56b57dcfda5 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -532,7 +532,7 @@ static void bL_cpufreq_ready(struct cpufreq_policy *policy)
if (cur_cluster >= MAX_CLUSTERS)
return;
 
-   cdev[cur_cluster] = of_cpufreq_power_cooling_register(policy);
+   cdev[cur_cluster] = of_cpufreq_cooling_register(policy);
 }
 
 static struct cpufreq_driver bL_cpufreq_driver = {
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 1e7bec7694ab..de3d104c25d7 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -320,7 +320,7 @@ static void cpufreq_ready(struct cpufreq_policy *policy)
 {
struct private_data *priv = policy->driver_data;
 
-   priv->cdev = of_cpufreq_power_cooling_register(policy);
+   priv->cdev = of_cpufreq_cooling_register(policy);
 }
 
 static struct cpufreq_driver dt_cpufreq_driver = {
diff --git a/drivers/cpufreq/mediatek-cpufreq.c 
b/drivers/cpufreq/mediatek-cpufreq.c
index 6ff783e1b18a..f95975b76d98 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -311,7 +311,7 @@ static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
 {
struct mtk_cpu_dvfs_info *info = policy->driver_data;
 
-   info->cdev = of_cpufreq_power_cooling_register(policy);
+   info->cdev = of_cpufreq_cooling_register(policy);
 }
 
 static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 3a665c18e14e..0562761a3dec 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -276,7 +276,7 @@ static void qoriq_cpufreq_ready(struct cpufreq_policy 
*policy)
 {
struct cpu_data *cpud = policy->driver_data;
 
-   cpud->cdev = of_cpufreq_power_cooling_register(policy);
+   cpud->cdev = of_cpufreq_cooling_register(policy);
 }
 
 static struct cpufreq_driver qoriq_cpufreq_driver = {
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 10199f7e1196..3371caf3095c 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -819,7 +819,6 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
 
 /**
  * of_cpufreq_cooling_register - function to create cpufreq cooling device.
- * @np: a valid struct device_node to 

[PATCH V2 1/4] cpu_cooling: Make of_cpufreq_power_cooling_register() parse DT

2017-12-04 Thread Viresh Kumar
All the callers of of_cpufreq_power_cooling_register() have almost
identical code and it makes more sense to move that code into the helper
as its all about reading DT properties.

This got rid of lot of redundant code.

Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 Documentation/thermal/cpu-cooling-api.txt |  7 ++---
 drivers/cpufreq/arm_big_little.c  | 23 +--
 drivers/cpufreq/cpufreq-dt.c  | 27 +
 drivers/cpufreq/mediatek-cpufreq.c| 22 +-
 drivers/cpufreq/qoriq-cpufreq.c   | 14 +
 drivers/thermal/cpu_cooling.c | 49 +++
 include/linux/cpu_cooling.h   | 15 ++
 7 files changed, 41 insertions(+), 116 deletions(-)

diff --git a/Documentation/thermal/cpu-cooling-api.txt 
b/Documentation/thermal/cpu-cooling-api.txt
index 71653584cd03..4f6f5e9bb4d6 100644
--- a/Documentation/thermal/cpu-cooling-api.txt
+++ b/Documentation/thermal/cpu-cooling-api.txt
@@ -51,8 +51,7 @@ Dynamic power).  "plat_static_func" is a function to 
calculate the
 static power consumed by these cpus (See 2.2 Static power).
 
 1.1.4 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
-struct device_node *np, const struct cpumask *clip_cpus, u32 capacitance,
-get_static_t plat_static_func)
+   struct cpufreq_policy *policy)
 
 Similar to cpufreq_power_cooling_register, this function register a
 cpufreq cooling device with power extensions using the device tree
@@ -76,8 +75,8 @@ cpu.  If you are using CONFIG_CPUFREQ_DT then the
 device.
 
 The `plat_static_func` parameter of `cpufreq_power_cooling_register()`
-and `of_cpufreq_power_cooling_register()` is optional.  If you don't
-provide it, only dynamic power will be considered.
+is optional.  If you don't provide it, only dynamic power will be
+considered.
 
 2.1 Dynamic power
 
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 65ec5f01aa8d..3d5ed4ef3927 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -526,34 +526,13 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
 
 static void bL_cpufreq_ready(struct cpufreq_policy *policy)
 {
-   struct device *cpu_dev = get_cpu_device(policy->cpu);
int cur_cluster = cpu_to_cluster(policy->cpu);
-   struct device_node *np;
 
/* Do not register a cpu_cooling device if we are in IKS mode */
if (cur_cluster >= MAX_CLUSTERS)
return;
 
-   np = of_node_get(cpu_dev->of_node);
-   if (WARN_ON(!np))
-   return;
-
-   if (of_find_property(np, "#cooling-cells", NULL)) {
-   u32 power_coefficient = 0;
-
-   of_property_read_u32(np, "dynamic-power-coefficient",
-_coefficient);
-
-   cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
-   policy, power_coefficient, NULL);
-   if (IS_ERR(cdev[cur_cluster])) {
-   dev_err(cpu_dev,
-   "running cpufreq without cooling device: %ld\n",
-   PTR_ERR(cdev[cur_cluster]));
-   cdev[cur_cluster] = NULL;
-   }
-   }
-   of_node_put(np);
+   cdev[cur_cluster] = of_cpufreq_power_cooling_register(policy);
 }
 
 static struct cpufreq_driver bL_cpufreq_driver = {
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 545946ad0752..1e7bec7694ab 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -319,33 +319,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
 static void cpufreq_ready(struct cpufreq_policy *policy)
 {
struct private_data *priv = policy->driver_data;
-   struct device_node *np = of_node_get(priv->cpu_dev->of_node);
 
-   if (WARN_ON(!np))
-   return;
-
-   /*
-* For now, just loading the cooling device;
-* thermal DT code takes care of matching them.
-*/
-   if (of_find_property(np, "#cooling-cells", NULL)) {
-   u32 power_coefficient = 0;
-
-   of_property_read_u32(np, "dynamic-power-coefficient",
-_coefficient);
-
-   priv->cdev = of_cpufreq_power_cooling_register(np,
-   policy, power_coefficient, NULL);
-   if (IS_ERR(priv->cdev)) {
-   dev_err(priv->cpu_dev,
-   "running cpufreq without cooling device: %ld\n",
-   PTR_ERR(priv->cdev));
-
-   priv->cdev = NULL;
-   }
-   }
-
-   of_node_put(np);
+   priv->cdev = of_cpufreq_power_cooling_register(policy);
 }
 
 static struct cpufreq_driver dt_cpufreq_driver = {
diff --git a/drivers/cpufreq/mediatek-cpufreq.c 

[PATCH V2 4/4] cpu_cooling: Drop static-power related stuff

2017-12-04 Thread Viresh Kumar
No one has used it for the last two and half years (since it was
introduced by commit c36cf0717631 ("thermal: cpu_cooling: implement the
power cooling device API")), get rid of it.

Cc: Javi Merino 
Cc: Punit Agrawal 
Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 drivers/thermal/cpu_cooling.c  | 106 +
 include/linux/cpu_cooling.h|   3 --
 include/trace/events/thermal.h |  10 ++--
 3 files changed, 16 insertions(+), 103 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 3371caf3095c..dfd23245f778 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -88,7 +88,6 @@ struct time_in_idle {
  * @policy: cpufreq policy.
  * @node: list_head to link all cpufreq_cooling_device together.
  * @idle_time: idle time stats
- * @plat_get_static_power: callback to calculate the static power
  *
  * This structure is required for keeping information of each registered
  * cpufreq_cooling_device.
@@ -104,7 +103,6 @@ struct cpufreq_cooling_device {
struct cpufreq_policy *policy;
struct list_head node;
struct time_in_idle *idle_time;
-   get_static_t plat_get_static_power;
 };
 
 static DEFINE_IDA(cpufreq_ida);
@@ -319,60 +317,6 @@ static u32 get_load(struct cpufreq_cooling_device 
*cpufreq_cdev, int cpu,
 }
 
 /**
- * get_static_power() - calculate the static power consumed by the cpus
- * @cpufreq_cdev:  struct _cooling_device for this cpu cdev
- * @tz:thermal zone device in which we're operating
- * @freq:  frequency in KHz
- * @power: pointer in which to store the calculated static power
- *
- * Calculate the static power consumed by the cpus described by
- * @cpu_actor running at frequency @freq.  This function relies on a
- * platform specific function that should have been provided when the
- * actor was registered.  If it wasn't, the static power is assumed to
- * be negligible.  The calculated static power is stored in @power.
- *
- * Return: 0 on success, -E* on failure.
- */
-static int get_static_power(struct cpufreq_cooling_device *cpufreq_cdev,
-   struct thermal_zone_device *tz, unsigned long freq,
-   u32 *power)
-{
-   struct dev_pm_opp *opp;
-   unsigned long voltage;
-   struct cpufreq_policy *policy = cpufreq_cdev->policy;
-   struct cpumask *cpumask = policy->related_cpus;
-   unsigned long freq_hz = freq * 1000;
-   struct device *dev;
-
-   if (!cpufreq_cdev->plat_get_static_power) {
-   *power = 0;
-   return 0;
-   }
-
-   dev = get_cpu_device(policy->cpu);
-   WARN_ON(!dev);
-
-   opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true);
-   if (IS_ERR(opp)) {
-   dev_warn_ratelimited(dev, "Failed to find OPP for frequency 
%lu: %ld\n",
-freq_hz, PTR_ERR(opp));
-   return -EINVAL;
-   }
-
-   voltage = dev_pm_opp_get_voltage(opp);
-   dev_pm_opp_put(opp);
-
-   if (voltage == 0) {
-   dev_err_ratelimited(dev, "Failed to get voltage for frequency 
%lu\n",
-   freq_hz);
-   return -EINVAL;
-   }
-
-   return cpufreq_cdev->plat_get_static_power(cpumask, tz->passive_delay,
- voltage, power);
-}
-
-/**
  * get_dynamic_power() - calculate the dynamic power
  * @cpufreq_cdev:  _cooling_device for this cdev
  * @freq:  current frequency
@@ -491,8 +435,8 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
   u32 *power)
 {
unsigned long freq;
-   int i = 0, cpu, ret;
-   u32 static_power, dynamic_power, total_load = 0;
+   int i = 0, cpu;
+   u32 total_load = 0;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpufreq_policy *policy = cpufreq_cdev->policy;
u32 *load_cpu = NULL;
@@ -522,22 +466,15 @@ static int cpufreq_get_requested_power(struct 
thermal_cooling_device *cdev,
 
cpufreq_cdev->last_load = total_load;
 
-   dynamic_power = get_dynamic_power(cpufreq_cdev, freq);
-   ret = get_static_power(cpufreq_cdev, tz, freq, _power);
-   if (ret) {
-   kfree(load_cpu);
-   return ret;
-   }
+   *power = get_dynamic_power(cpufreq_cdev, freq);
 
if (load_cpu) {
trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
- load_cpu, i, dynamic_power,
- static_power);
+ load_cpu, i, *power);
 
kfree(load_cpu);
}
 
-   *power = static_power + dynamic_power;
return 0;
 }
 
@@ -561,8 +498,6 @@ static int cpufreq_state2power(struct 

[PATCH V2 0/4] cpu_cooling: cooling dev registration cleanups

2017-12-04 Thread Viresh Kumar
Hi,

This cleans up the helpers exposed by cpu_cooling driver and its users
and removes a lot of code (around 280 lines effectively). Lots of unused
code is removed.

Tested on Hikey6220 and based over pm/linux-next.

V1->V2:
- Fixed a compilation warning when CONFIG_CPU_THERMAL isn't selected.

--
viresh

Viresh Kumar (4):
  cpu_cooling: Make of_cpufreq_power_cooling_register() parse DT
  cpu_cooling: Remove unused cpufreq_power_cooling_register()
  cpu_cooling: Keep only one of_cpufreq*cooling_register() helper
  cpu_cooling: Drop static-power related stuff

 Documentation/thermal/cpu-cooling-api.txt |  33 +
 drivers/cpufreq/arm_big_little.c  |  23 +---
 drivers/cpufreq/cpufreq-dt.c  |  27 +---
 drivers/cpufreq/mediatek-cpufreq.c|  22 +---
 drivers/cpufreq/qoriq-cpufreq.c   |  14 +--
 drivers/thermal/cpu_cooling.c | 201 ++
 include/linux/cpu_cooling.h   |  75 +++
 include/trace/events/thermal.h|  10 +-
 8 files changed, 64 insertions(+), 341 deletions(-)

-- 
2.11.0



[PATCH V2 2/4] cpu_cooling: Remove unused cpufreq_power_cooling_register()

2017-12-04 Thread Viresh Kumar
It isn't used by anyone, drop it.

Acked-by: Eduardo Valentin 
Signed-off-by: Viresh Kumar 
---
 Documentation/thermal/cpu-cooling-api.txt | 24 +++-
 drivers/thermal/cpu_cooling.c | 30 --
 include/linux/cpu_cooling.h   | 10 --
 3 files changed, 3 insertions(+), 61 deletions(-)

diff --git a/Documentation/thermal/cpu-cooling-api.txt 
b/Documentation/thermal/cpu-cooling-api.txt
index 4f6f5e9bb4d6..ea61e8bf7e2b 100644
--- a/Documentation/thermal/cpu-cooling-api.txt
+++ b/Documentation/thermal/cpu-cooling-api.txt
@@ -36,28 +36,14 @@ the user. The registration APIs returns the cooling device 
pointer.
 np: pointer to the cooling device device tree node
 clip_cpus: cpumask of cpus where the frequency constraints will happen.
 
-1.1.3 struct thermal_cooling_device *cpufreq_power_cooling_register(
-const struct cpumask *clip_cpus, u32 capacitance,
-get_static_t plat_static_func)
-
-Similar to cpufreq_cooling_register, this function registers a cpufreq
-cooling device.  Using this function, the cooling device will
-implement the power extensions by using a simple cpu power model.  The
-cpus must have registered their OPPs using the OPP library.
-
-The additional parameters are needed for the power model (See 2. Power
-models).  "capacitance" is the dynamic power coefficient (See 2.1
-Dynamic power).  "plat_static_func" is a function to calculate the
-static power consumed by these cpus (See 2.2 Static power).
-
-1.1.4 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
+1.1.3 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
struct cpufreq_policy *policy)
 
-Similar to cpufreq_power_cooling_register, this function register a
+Similar to cpufreq_cooling_register, this function register a
 cpufreq cooling device with power extensions using the device tree
 information supplied by the np parameter.
 
-1.1.5 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
+1.1.4 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 This interface function unregisters the "thermal-cpufreq-%x" cooling 
device.
 
@@ -74,10 +60,6 @@ cpu.  If you are using CONFIG_CPUFREQ_DT then the
 `cpufreq_frequency_table` should already be assigned to the cpu
 device.
 
-The `plat_static_func` parameter of `cpufreq_power_cooling_register()`
-is optional.  If you don't provide it, only dynamic power will be
-considered.
-
 2.1 Dynamic power
 
 The dynamic power consumption of a processor depends on many factors.
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index a31eb03c788e..10199f7e1196 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -842,36 +842,6 @@ of_cpufreq_cooling_register(struct device_node *np,
 EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
 
 /**
- * cpufreq_power_cooling_register() - create cpufreq cooling device with power 
extensions
- * @policy:cpufreq policy
- * @capacitance:   dynamic power coefficient for these cpus
- * @plat_static_func:  function to calculate the static power consumed by these
- * cpus (optional)
- *
- * This interface function registers the cpufreq cooling device with
- * the name "thermal-cpufreq-%x".  This api can support multiple
- * instances of cpufreq cooling devices.  Using this function, the
- * cooling device will implement the power extensions by using a
- * simple cpu power model.  The cpus must have registered their OPPs
- * using the OPP library.
- *
- * An optional @plat_static_func may be provided to calculate the
- * static power consumed by these cpus.  If the platform's static
- * power consumption is unknown or negligible, make it NULL.
- *
- * Return: a valid struct thermal_cooling_device pointer on success,
- * on failure, it returns a corresponding ERR_PTR().
- */
-struct thermal_cooling_device *
-cpufreq_power_cooling_register(struct cpufreq_policy *policy, u32 capacitance,
-  get_static_t plat_static_func)
-{
-   return __cpufreq_cooling_register(NULL, policy, capacitance,
-   plat_static_func);
-}
-EXPORT_SYMBOL(cpufreq_power_cooling_register);
-
-/**
  * of_cpufreq_power_cooling_register() - create cpufreq cooling device with 
power extensions
  * @policy: CPUFreq policy.
  *
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index f09d4feb34f4..c35778960a9c 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -41,10 +41,6 @@ typedef int (*get_static_t)(cpumask_t *cpumask, int interval,
 struct thermal_cooling_device *
 cpufreq_cooling_register(struct cpufreq_policy *policy);
 
-struct thermal_cooling_device *
-cpufreq_power_cooling_register(struct cpufreq_policy *policy,
-  u32 capacitance, get_static_t 

<    1   2   3   4   5   6   7   8   9   10   >