[PATCH net-next 12/12] rocker, dsa, ethsw: Don't filter VLAN events on bridge itself

2018-11-22 Thread Petr Machata
Due to an explicit check in rocker_world_port_obj_vlan_add(),
dsa_slave_switchdev_event() resp. port_switchdev_event(), VLAN objects
that are added to a device that is not a front-panel port device are
ignored. Therefore this check is immaterial.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/net/ethernet/rocker/rocker_main.c | 3 ---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c   | 3 ---
 net/dsa/port.c| 3 ---
 3 files changed, 9 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index f05d5c1341b6..6213827e3956 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1632,9 +1632,6 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
-   if (netif_is_bridge_master(vlan->obj.orig_dev))
-   return -EOPNOTSUPP;
-
if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;
 
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 06a233c7cdd3..4fa37d6e598b 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -719,9 +719,6 @@ static int port_vlans_add(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err = 0;
 
-   if (netif_is_bridge_master(vlan->obj.orig_dev))
-   return -EOPNOTSUPP;
-
if (switchdev_trans_ph_prepare(trans))
return 0;
 
diff --git a/net/dsa/port.c b/net/dsa/port.c
index ed0595459df1..2d7e01b23572 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,9 +252,6 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan,
};
 
-   if (netif_is_bridge_master(vlan->obj.orig_dev))
-   return -EOPNOTSUPP;
-
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, );
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 05/10] staging: erofs: add a full barrier in erofs_workgroup_unfreeze

2018-11-22 Thread Gao Xiang
Hi Andrea,

On 2018/11/23 2:50, Andrea Parri wrote:
> On Thu, Nov 22, 2018 at 06:56:32PM +0800, Gao Xiang wrote:
>> Hi Greg,
>>
>> On 2018/11/22 18:22, Greg Kroah-Hartman wrote:
>>> Please document this memory barrier.  It does not make much sense to
>>> me...
>>
>> Because we need to make the other observers noticing the latest values 
>> modified
>> in this locking period before unfreezing the whole workgroup, one way is to 
>> use
>> a memory barrier and the other way is to use ACQUIRE and RELEASE. we selected
>> the first one.
>>
>> Hmmm...ok, I will add a simple message to explain this, but I think that is
>> plain enough for a lock...
> 
> Sympathizing with Greg's request, let me add some specific suggestions:
> 
>   1. It wouldn't hurt to indicate a pair of memory accesses which are
>  intended to be "ordered" by the memory barrier in question (yes,
>  this pair might not be unique, but you should be able to provide
>  an example).
> 
>   2. Memory barriers always come matched by other memory barriers, or
>  dependencies (it really does not make sense to talk about a full
>  barrier "in isolation"): please also indicate (an instance of) a
>  matching barrier or the matching barriers.
> 
>   3. How do the hardware threads communicate?  In the acquire/release
>  pattern you mentioned above, the load-acquire *reads from* a/the
>  previous store-release, a memory access that follows the acquire
>  somehow communicate with a memory access preceding the release...
> 
>   4. It is a good practice to include the above information within an
>  (inline) comment accompanying the added memory barrier (in fact,
>  IIRC, checkpatch.pl gives you a "memory barrier without comment"
>  warning when you omit to do so); not just in the commit message.
> 
> Hope this helps.  Please let me know if something I wrote is unclear,

Thanks for taking time on the detailed explanation. I think it is helpful for 
me. :)
And you are right, barriers should be in pairs, and I think I need to explain 
more:

255 static inline bool erofs_workgroup_get(struct erofs_workgroup *grp, int 
*ocnt)
256 {
257 int o;
258
259 repeat:
260 o = erofs_wait_on_workgroup_freezed(grp);
261
262 if (unlikely(o <= 0))
263 return -1;
264
265 if (unlikely(atomic_cmpxchg(>refcount, o, o + 1) != o)) <- *
266 goto repeat;
imply a memory barrier here
267
268 *ocnt = o;
269 return 0;
270 }

I think atomic_cmpxchg implies a memory barrier semantics when the value 
comparison (*) succeeds...

I don't know whether my understanding is correct, If I am wrong..please correct 
me, or
I need to add more detailed code comments to explain in the code?

Thanks,
Gao Xiang


> 
>   Andrea
> 
> 
>>
>> Thanks,
>> Gao Xiang
>>
>>>
>>> thanks,
>>>
>>> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next 00/12] switchdev: Convert switchdev_port_obj_{add,del}() to notifiers

2018-11-22 Thread Petr Machata
Petr Machata  writes:

> An offloading driver may need to have access to switchdev events on
> ports that aren't directly under its control. An example is a VXLAN port
> attached to a bridge offloaded by a driver. The driver needs to know
> about VLANs configured on the VXLAN device. However the VXLAN device
> isn't stashed between the bridge and a front-panel-port device (such as
> is the case e.g. for LAG devices), so the usual switchdev ops don't
> reach the driver.

mlxsw will use these notifications to offload VXLAN devices attached to
a VLAN-aware bridge. The patches are available here should anyone wish
to take a look:

https://github.com/idosch/linux/commits/vxlan

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 11/12] switchdev: Replace port obj add/del SDO with a notification

2018-11-22 Thread Petr Machata
Drop switchdev_ops.switchdev_port_obj_add and _del. Drop the uses of
this field from all clients, which were migrated to use switchdev
notification in the previous patches.

Add a new function switchdev_port_obj_notify() that sends the switchdev
notifications SWITCHDEV_PORT_OBJ_ADD and _DEL.

Update switchdev_port_obj_del_now() to dispatch to this new function.
Drop __switchdev_port_obj_add() and update switchdev_port_obj_add()
likewise.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  2 -
 drivers/net/ethernet/mscc/ocelot.c |  2 -
 drivers/net/ethernet/rocker/rocker_main.c  |  2 -
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  2 -
 include/net/switchdev.h|  9 ---
 net/dsa/slave.c|  2 -
 net/switchdev/switchdev.c  | 67 --
 7 files changed, 25 insertions(+), 61 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 3756aaecd39c..73e5db176d7e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1968,8 +1968,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct 
mlxsw_sp *mlxsw_sp,
 static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
.switchdev_port_attr_get= mlxsw_sp_port_attr_get,
.switchdev_port_attr_set= mlxsw_sp_port_attr_set,
-   .switchdev_port_obj_add = mlxsw_sp_port_obj_add,
-   .switchdev_port_obj_del = mlxsw_sp_port_obj_del,
 };
 
 static int
diff --git a/drivers/net/ethernet/mscc/ocelot.c 
b/drivers/net/ethernet/mscc/ocelot.c
index 01403b530522..7f8da8873a96 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1337,8 +1337,6 @@ static int ocelot_port_obj_del(struct net_device *dev,
 static const struct switchdev_ops ocelot_port_switchdev_ops = {
.switchdev_port_attr_get= ocelot_port_attr_get,
.switchdev_port_attr_set= ocelot_port_attr_set,
-   .switchdev_port_obj_add = ocelot_port_obj_add,
-   .switchdev_port_obj_del = ocelot_port_obj_del,
 };
 
 static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port,
diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index 806ffe1d906e..f05d5c1341b6 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2145,8 +2145,6 @@ static int rocker_port_obj_del(struct net_device *dev,
 static const struct switchdev_ops rocker_port_switchdev_ops = {
.switchdev_port_attr_get= rocker_port_attr_get,
.switchdev_port_attr_set= rocker_port_attr_set,
-   .switchdev_port_obj_add = rocker_port_obj_add,
-   .switchdev_port_obj_del = rocker_port_obj_del,
 };
 
 struct rocker_fib_event_work {
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 83e1d92dc7f3..06a233c7cdd3 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -930,8 +930,6 @@ static int swdev_port_obj_del(struct net_device *netdev,
 static const struct switchdev_ops ethsw_port_switchdev_ops = {
.switchdev_port_attr_get= swdev_port_attr_get,
.switchdev_port_attr_set= swdev_port_attr_set,
-   .switchdev_port_obj_add = swdev_port_obj_add,
-   .switchdev_port_obj_del = swdev_port_obj_del,
 };
 
 /* For the moment, only flood setting needs to be updated */
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 6dc7de576167..866b6d148b77 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -121,10 +121,6 @@ typedef int switchdev_obj_dump_cb_t(struct switchdev_obj 
*obj);
  * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr).
  *
  * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr).
- *
- * @switchdev_port_obj_add: Add an object to port (see switchdev_obj_*).
- *
- * @switchdev_port_obj_del: Delete an object from port (see switchdev_obj_*).
  */
 struct switchdev_ops {
int (*switchdev_port_attr_get)(struct net_device *dev,
@@ -132,11 +128,6 @@ struct switchdev_ops {
int (*switchdev_port_attr_set)(struct net_device *dev,
   const struct switchdev_attr *attr,
   struct switchdev_trans *trans);
-   int (*switchdev_port_obj_add)(struct net_device *dev,
- const struct switchdev_obj *obj,
- struct switchdev_trans *trans);
-   int (*switchdev_port_obj_del)(struct net_device *dev,
- 

[PATCH net-next 09/12] mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

To handle SWITCHDEV_PORT_OBJ_ADD and _DEL, subscribe to the blocking
notifier chain. Dispatch to mlxsw_sp_port_obj_add() resp. _del() to
maintain the behavior that the switchdev operation based code currently
has. Defer to switchdev_handle_port_obj_add() / _del() to handle the
recursive descend, because mlxsw supports a number of upper types.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 45 +-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index b32a5ee57fb9..3756aaecd39c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -3118,6 +3118,32 @@ static struct notifier_block mlxsw_sp_switchdev_notifier 
= {
.notifier_call = mlxsw_sp_switchdev_event,
 };
 
+static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
+unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+   int err;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = switchdev_handle_port_obj_add(dev, ptr,
+   mlxsw_sp_port_dev_check,
+   mlxsw_sp_port_obj_add);
+   return notifier_from_errno(err);
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = switchdev_handle_port_obj_del(dev, ptr,
+   mlxsw_sp_port_dev_check,
+   mlxsw_sp_port_obj_del);
+   return notifier_from_errno(err);
+   }
+
+   return NOTIFY_DONE;
+}
+
+static struct notifier_block mlxsw_sp_switchdev_blocking_notifier = {
+   .notifier_call = mlxsw_sp_switchdev_blocking_event,
+};
+
 u8
 mlxsw_sp_bridge_port_stp_state(struct mlxsw_sp_bridge_port *bridge_port)
 {
@@ -3127,6 +3153,7 @@ mlxsw_sp_bridge_port_stp_state(struct 
mlxsw_sp_bridge_port *bridge_port)
 static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 {
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
+   struct notifier_block *nb;
int err;
 
err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME);
@@ -3141,17 +3168,33 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
return err;
}
 
+   nb = _sp_switchdev_blocking_notifier;
+   err = register_switchdev_blocking_notifier(nb);
+   if (err) {
+   dev_err(mlxsw_sp->bus_info->dev, "Failed to register switchdev 
blocking notifier\n");
+   goto err_register_switchdev_blocking_notifier;
+   }
+
INIT_DELAYED_WORK(>fdb_notify.dw, mlxsw_sp_fdb_notify_work);
bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
return 0;
+
+err_register_switchdev_blocking_notifier:
+   unregister_switchdev_notifier(_sp_switchdev_notifier);
+   return err;
 }
 
 static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
 {
+   struct notifier_block *nb;
+
cancel_delayed_work_sync(_sp->bridge->fdb_notify.dw);
-   unregister_switchdev_notifier(_sp_switchdev_notifier);
 
+   nb = _sp_switchdev_blocking_notifier;
+   unregister_switchdev_blocking_notifier(nb);
+
+   unregister_switchdev_notifier(_sp_switchdev_notifier);
 }
 
 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 07/12] staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

ethsw currently doesn't support any uppers other than bridge.
SWITCHDEV_OBJ_ID_HOST_MDB and _PORT_MDB objects are always notified on
the bridge port device. Thus the only case that a stacked device could
be validly referenced by port object notifications are bridge
notifications for VLAN objects added to the bridge itself. But the
driver explicitly rejects such notifications in port_vlans_add(). It is
therefore safe to assume that the only interesting case is that the
notification is on a front-panel port netdevice.

To handle SWITCHDEV_PORT_OBJ_ADD and _DEL, subscribe to the blocking
notifier chain. Dispatch to swdev_port_obj_add() resp. _del() to
maintain the behavior that the switchdev operation based code currently
has.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 56 +
 1 file changed, 56 insertions(+)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index e379b0fa936f..83e1d92dc7f3 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -1088,10 +1088,51 @@ static int port_switchdev_event(struct notifier_block 
*unused,
return NOTIFY_BAD;
 }
 
+static int
+ethsw_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
+   struct switchdev_notifier_port_obj_info *port_obj_info)
+{
+   int err = -EOPNOTSUPP;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = swdev_port_obj_add(netdev, port_obj_info->obj,
+port_obj_info->trans);
+   break;
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = swdev_port_obj_del(netdev, port_obj_info->obj);
+   break;
+   }
+
+   port_obj_info->handled = true;
+   return notifier_from_errno(err);
+}
+
+static int port_switchdev_blocking_event(struct notifier_block *unused,
+unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+   if (!ethsw_port_dev_check(dev))
+   return NOTIFY_DONE;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
+   case SWITCHDEV_PORT_OBJ_DEL:
+   return ethsw_switchdev_port_obj_event(event, dev, ptr);
+   }
+
+   return NOTIFY_DONE;
+}
+
 static struct notifier_block port_switchdev_nb = {
.notifier_call = port_switchdev_event,
 };
 
+static struct notifier_block port_switchdev_blocking_nb = {
+   .notifier_call = port_switchdev_blocking_event,
+};
+
 static int ethsw_register_notifier(struct device *dev)
 {
int err;
@@ -1108,8 +1149,16 @@ static int ethsw_register_notifier(struct device *dev)
goto err_switchdev_nb;
}
 
+   err = register_switchdev_blocking_notifier(_switchdev_blocking_nb);
+   if (err) {
+   dev_err(dev, "Failed to register switchdev blocking 
notifier\n");
+   goto err_switchdev_blocking_nb;
+   }
+
return 0;
 
+err_switchdev_blocking_nb:
+   unregister_switchdev_notifier(_switchdev_nb);
 err_switchdev_nb:
unregister_netdevice_notifier(_nb);
return err;
@@ -1296,8 +1345,15 @@ static int ethsw_port_init(struct ethsw_port_priv 
*port_priv, u16 port)
 
 static void ethsw_unregister_notifier(struct device *dev)
 {
+   struct notifier_block *nb;
int err;
 
+   nb = _switchdev_blocking_nb;
+   err = unregister_switchdev_blocking_notifier(nb);
+   if (err)
+   dev_err(dev,
+   "Failed to unregister switchdev blocking notifier 
(%d)\n", err);
+
err = unregister_switchdev_notifier(_switchdev_nb);
if (err)
dev_err(dev,
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 10/12] ocelot: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

Dispatch the new events to ocelot_port_obj_add() resp. _del() to
maintain the same behavior that the switchdev operation based code
currently has. Pass through switchdev_handle_port_obj_add() / _del() to
handle the recursive descend, because Ocelot supports LAG uppers.

Register to the new switchdev blocking notifier chain to get the new
events when they start getting distributed.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/net/ethernet/mscc/ocelot.c   | 28 
 drivers/net/ethernet/mscc/ocelot.h   |  1 +
 drivers/net/ethernet/mscc/ocelot_board.c |  3 +++
 3 files changed, 32 insertions(+)

diff --git a/drivers/net/ethernet/mscc/ocelot.c 
b/drivers/net/ethernet/mscc/ocelot.c
index 3238b9ee42f3..01403b530522 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1595,6 +1595,34 @@ struct notifier_block ocelot_netdevice_nb __read_mostly 
= {
 };
 EXPORT_SYMBOL(ocelot_netdevice_nb);
 
+static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
+  unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+   int err;
+
+   switch (event) {
+   /* Blocking events. */
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = switchdev_handle_port_obj_add(dev, ptr,
+   ocelot_netdevice_dev_check,
+   ocelot_port_obj_add);
+   return notifier_from_errno(err);
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = switchdev_handle_port_obj_del(dev, ptr,
+   ocelot_netdevice_dev_check,
+   ocelot_port_obj_del);
+   return notifier_from_errno(err);
+   }
+
+   return NOTIFY_DONE;
+}
+
+struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = {
+   .notifier_call = ocelot_switchdev_blocking_event,
+};
+EXPORT_SYMBOL(ocelot_switchdev_blocking_nb);
+
 int ocelot_probe_port(struct ocelot *ocelot, u8 port,
  void __iomem *regs,
  struct phy_device *phy)
diff --git a/drivers/net/ethernet/mscc/ocelot.h 
b/drivers/net/ethernet/mscc/ocelot.h
index 62c7c8eb00d9..086775f7b52f 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -499,5 +499,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
  struct phy_device *phy);
 
 extern struct notifier_block ocelot_netdevice_nb;
+extern struct notifier_block ocelot_switchdev_blocking_nb;
 
 #endif
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c 
b/drivers/net/ethernet/mscc/ocelot_board.c
index 4c23d18bbf44..ca3ea2fbfcd0 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ocelot.h"
 
@@ -328,6 +329,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
}
 
register_netdevice_notifier(_netdevice_nb);
+   register_switchdev_blocking_notifier(_switchdev_blocking_nb);
 
dev_info(>dev, "Ocelot switch probed\n");
 
@@ -342,6 +344,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
struct ocelot *ocelot = platform_get_drvdata(pdev);
 
ocelot_deinit(ocelot);
+   unregister_switchdev_blocking_notifier(_switchdev_blocking_nb);
unregister_netdevice_notifier(_netdevice_nb);
 
return 0;
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 06/12] staging: fsl-dpaa2: ethsw: Introduce ethsw_port_dev_check()

2018-11-22 Thread Petr Machata
ethsw currently uses an open-coded comparison of netdev_ops to determine
whether whether a device represents a front panel port. Wrap this into a
named function to simplify reuse.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 7a7ca67822c5..e379b0fa936f 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -972,6 +972,11 @@ static int port_bridge_leave(struct net_device *netdev)
return err;
 }
 
+static bool ethsw_port_dev_check(const struct net_device *netdev)
+{
+   return netdev->netdev_ops == _port_ops;
+}
+
 static int port_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
 {
@@ -980,7 +985,7 @@ static int port_netdevice_event(struct notifier_block 
*unused,
struct net_device *upper_dev;
int err = 0;
 
-   if (netdev->netdev_ops != _port_ops)
+   if (!ethsw_port_dev_check(netdev))
return NOTIFY_DONE;
 
/* Handle just upper dev link/unlink for the moment */
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 08/12] switchdev: Add helpers to aid traversal through lower devices

2018-11-22 Thread Petr Machata
After the transition from switchdev operations to notifier chain (which
will take place in following patches), the onus is on the driver to find
its own devices below possible layer of LAG or other uppers.

The logic to do so is fairly repetitive: each driver is looking for its
own devices among the lowers of the notified device. For those that it
finds, it calls a handler. To indicate that the event was handled,
struct switchdev_notifier_port_obj_info.handled is set. The differences
lie only in what constitutes an "own" device and what handler to call.

Therefore abstract this logic into two helpers,
switchdev_handle_port_obj_add() and switchdev_handle_port_obj_del(). If
a driver only supports physical ports under a bridge device, it will
simply avoid this layer of indirection.

One area where this helper diverges from the current switchdev behavior
is the case of mixed lowers, some of which are switchdev ports and some
of which are not. Previously, such scenario would fail with -EOPNOTSUPP.
The helper could do that for lowers for which the passed-in predicate
doesn't hold. That would however break the case that switchdev ports
from several different drivers are stashed under one master, a scenario
that switchdev currently happily supports. Therefore tolerate any and
all unknown netdevices, whether they are backed by a switchdev driver
or not.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h   |  33 +++
 net/switchdev/switchdev.c | 100 ++
 2 files changed, 133 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index a2f3ebf39301..6dc7de576167 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -210,6 +210,18 @@ void switchdev_port_fwd_mark_set(struct net_device *dev,
 bool switchdev_port_same_parent_id(struct net_device *a,
   struct net_device *b);
 
+int switchdev_handle_port_obj_add(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*add_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans));
+int switchdev_handle_port_obj_del(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*del_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj));
+
 #define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops))
 #else
 
@@ -284,6 +296,27 @@ static inline bool switchdev_port_same_parent_id(struct 
net_device *a,
return false;
 }
 
+static inline int
+switchdev_handle_port_obj_add(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*add_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans))
+{
+   return 0;
+}
+
+static inline int
+switchdev_handle_port_obj_del(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*del_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj))
+{
+   return 0;
+}
+
 #define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0)
 
 #endif
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index e109bb97ce3f..099434ec7996 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -621,3 +621,103 @@ bool switchdev_port_same_parent_id(struct net_device *a,
return netdev_phys_item_id_same(_attr.u.ppid, _attr.u.ppid);
 }
 EXPORT_SYMBOL_GPL(switchdev_port_same_parent_id);
+
+static int __switchdev_handle_port_obj_add(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*add_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans))
+{
+   struct net_device *lower_dev;
+   struct list_head *iter;
+   int err = -EOPNOTSUPP;
+
+   if (check_cb(dev)) {
+   /* This flag is only checked if the return value is success. */
+   port_obj_info->handled = true;
+   return add_cb(dev, port_obj_info->obj, port_obj_info->trans);
+   }
+
+   /* Switch 

[PATCH net-next 05/12] net: dsa: slave: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

DSA currently doesn't support any other uppers than bridge.
SWITCHDEV_OBJ_ID_HOST_MDB and _PORT_MDB objects are always notified on
the bridge port device. Thus the only case that a stacked device could
be validly referenced by port object notifications are bridge
notifications for VLAN objects added to the bridge itself. But the
driver explicitly rejects such notifications in dsa_port_vlan_add(). It
is therefore safe to assume that the only interesting case is that the
notification is on a front-panel port netdevice. Therefore keep the
filtering by dsa_slave_dev_check() in place.

To handle SWITCHDEV_PORT_OBJ_ADD and _DEL, subscribe to the blocking
notifier chain. Dispatch to rocker_port_obj_add() resp. _del() to
maintain the behavior that the switchdev operation based code currently
has.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 net/dsa/slave.c | 56 
 1 file changed, 56 insertions(+)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7d0c19e7edcf..d00a0b6d4ce0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1557,6 +1557,44 @@ static int dsa_slave_switchdev_event(struct 
notifier_block *unused,
return NOTIFY_BAD;
 }
 
+static int
+dsa_slave_switchdev_port_obj_event(unsigned long event,
+   struct net_device *netdev,
+   struct switchdev_notifier_port_obj_info *port_obj_info)
+{
+   int err = -EOPNOTSUPP;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = dsa_slave_port_obj_add(netdev, port_obj_info->obj,
+port_obj_info->trans);
+   break;
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = dsa_slave_port_obj_del(netdev, port_obj_info->obj);
+   break;
+   }
+
+   port_obj_info->handled = true;
+   return notifier_from_errno(err);
+}
+
+static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+   if (!dsa_slave_dev_check(dev))
+   return NOTIFY_DONE;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
+   case SWITCHDEV_PORT_OBJ_DEL:
+   return dsa_slave_switchdev_port_obj_event(event, dev, ptr);
+   }
+
+   return NOTIFY_DONE;
+}
+
 static struct notifier_block dsa_slave_nb __read_mostly = {
.notifier_call  = dsa_slave_netdevice_event,
 };
@@ -1565,8 +1603,13 @@ static struct notifier_block 
dsa_slave_switchdev_notifier = {
.notifier_call = dsa_slave_switchdev_event,
 };
 
+static struct notifier_block dsa_slave_switchdev_blocking_notifier = {
+   .notifier_call = dsa_slave_switchdev_blocking_event,
+};
+
 int dsa_slave_register_notifier(void)
 {
+   struct notifier_block *nb;
int err;
 
err = register_netdevice_notifier(_slave_nb);
@@ -1577,8 +1620,15 @@ int dsa_slave_register_notifier(void)
if (err)
goto err_switchdev_nb;
 
+   nb = _slave_switchdev_blocking_notifier;
+   err = register_switchdev_blocking_notifier(nb);
+   if (err)
+   goto err_switchdev_blocking_nb;
+
return 0;
 
+err_switchdev_blocking_nb:
+   unregister_switchdev_notifier(_slave_switchdev_notifier);
 err_switchdev_nb:
unregister_netdevice_notifier(_slave_nb);
return err;
@@ -1586,8 +1636,14 @@ int dsa_slave_register_notifier(void)
 
 void dsa_slave_unregister_notifier(void)
 {
+   struct notifier_block *nb;
int err;
 
+   nb = _slave_switchdev_blocking_notifier;
+   err = unregister_switchdev_blocking_notifier(nb);
+   if (err)
+   pr_err("DSA: failed to unregister switchdev blocking notifier 
(%d)\n", err);
+
err = unregister_switchdev_notifier(_slave_switchdev_notifier);
if (err)
pr_err("DSA: failed to unregister switchdev notifier (%d)\n", 
err);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 03/12] switchdev: Add SWITCHDEV_PORT_OBJ_ADD, SWITCHDEV_PORT_OBJ_DEL

2018-11-22 Thread Petr Machata
An offloading driver may need to have access to switchdev events on
ports that aren't directly under its control. An example is a VXLAN port
attached to a bridge offloaded by a driver. The driver needs to know
about VLANs configured on the VXLAN device. However the VXLAN device
isn't stashed between the bridge and a front-panel-port device (such as
is the case e.g. for LAG devices), so the usual switchdev ops don't
reach the driver.

VXLAN is likely not the only device type like this: in theory any L2
tunnel device that needs offloading will prompt requirement of this
sort. This falsifies the assumption that only the lower devices of a
front panel port need to be notified to achieve flawless offloading.

A way to fix this is to give up the notion of port object addition /
deletion as a switchdev operation, which assumes somewhat tight coupling
between the message producer and consumer. And instead send the message
over a notifier chain.

To that end, introduce two new switchdev notifier types,
SWITCHDEV_PORT_OBJ_ADD and SWITCHDEV_PORT_OBJ_DEL. These notifier types
communicate the same event as the corresponding switchdev op, except in
a form of a notification. struct switchdev_notifier_port_obj_info was
added to carry the fields that the switchdev op carries. An additional
field, handled, will be used to communicate back to switchdev that the
event has reached an interested party, which will be important for the
two-phase commit.

The two switchdev operations themselves are kept in place. Following
patches first convert individual clients to the notifier protocol, and
only then are the operations removed.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index e021b67b9b32..a2f3ebf39301 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -146,6 +146,9 @@ enum switchdev_notifier_type {
SWITCHDEV_FDB_DEL_TO_DEVICE,
SWITCHDEV_FDB_OFFLOADED,
 
+   SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */
+   SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */
+
SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE,
SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE,
SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
@@ -165,6 +168,13 @@ struct switchdev_notifier_fdb_info {
   offloaded:1;
 };
 
+struct switchdev_notifier_port_obj_info {
+   struct switchdev_notifier_info info; /* must be first */
+   const struct switchdev_obj *obj;
+   struct switchdev_trans *trans;
+   bool handled;
+};
+
 static inline struct net_device *
 switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info)
 {
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 02/12] switchdev: Add a blocking notifier chain

2018-11-22 Thread Petr Machata
In general one can't assume that a switchdev notifier is called in a
non-atomic context, and correspondingly, the switchdev notifier chain is
an atomic one.

However, port object addition and deletion messages are delivered from a
process context. Even the MDB addition messages, whose delivery is
scheduled from atomic context, are queued and the delivery itself takes
place in blocking context. For VLAN messages in particular, keeping the
blocking nature is important for error reporting.

Therefore introduce a blocking notifier chain and related service
functions to distribute the notifications for which a blocking context
can be assumed.

Signed-off-by: Petr Machata 
Reviewed-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h   | 27 +++
 net/switchdev/switchdev.c | 26 ++
 2 files changed, 53 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index dd969224a9b9..e021b67b9b32 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -182,10 +182,17 @@ int switchdev_port_obj_add(struct net_device *dev,
   const struct switchdev_obj *obj);
 int switchdev_port_obj_del(struct net_device *dev,
   const struct switchdev_obj *obj);
+
 int register_switchdev_notifier(struct notifier_block *nb);
 int unregister_switchdev_notifier(struct notifier_block *nb);
 int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
 struct switchdev_notifier_info *info);
+
+int register_switchdev_blocking_notifier(struct notifier_block *nb);
+int unregister_switchdev_blocking_notifier(struct notifier_block *nb);
+int call_switchdev_blocking_notifiers(unsigned long val, struct net_device 
*dev,
+ struct switchdev_notifier_info *info);
+
 void switchdev_port_fwd_mark_set(struct net_device *dev,
 struct net_device *group_dev,
 bool joining);
@@ -241,6 +248,26 @@ static inline int call_switchdev_notifiers(unsigned long 
val,
return NOTIFY_DONE;
 }
 
+static inline int
+register_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   return 0;
+}
+
+static inline int
+unregister_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   return 0;
+}
+
+static inline int
+call_switchdev_blocking_notifiers(unsigned long val,
+ struct net_device *dev,
+ struct switchdev_notifier_info *info)
+{
+   return NOTIFY_DONE;
+}
+
 static inline bool switchdev_port_same_parent_id(struct net_device *a,
 struct net_device *b)
 {
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 74b9d916a58b..e109bb97ce3f 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -535,6 +535,7 @@ int switchdev_port_obj_del(struct net_device *dev,
 EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
 
 static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
+static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain);
 
 /**
  * register_switchdev_notifier - Register notifier
@@ -576,6 +577,31 @@ int call_switchdev_notifiers(unsigned long val, struct 
net_device *dev,
 }
 EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
 
+int register_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   struct blocking_notifier_head *chain = _blocking_notif_chain;
+
+   return blocking_notifier_chain_register(chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_switchdev_blocking_notifier);
+
+int unregister_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   struct blocking_notifier_head *chain = _blocking_notif_chain;
+
+   return blocking_notifier_chain_unregister(chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier);
+
+int call_switchdev_blocking_notifiers(unsigned long val, struct net_device 
*dev,
+ struct switchdev_notifier_info *info)
+{
+   info->dev = dev;
+   return blocking_notifier_call_chain(_blocking_notif_chain,
+   val, info);
+}
+EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers);
+
 bool switchdev_port_same_parent_id(struct net_device *a,
   struct net_device *b)
 {
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 01/12] switchdev: SWITCHDEV_OBJ_PORT_{VLAN, MDB}(): Sanitize

2018-11-22 Thread Petr Machata
The two macros SWITCHDEV_OBJ_PORT_VLAN() and SWITCHDEV_OBJ_PORT_MDB()
expand to a container_of() call, yielding an appropriate container of
their sole argument. However, due to a name collision, the first
argument, i.e. the contained object pointer, is not the only one to get
expanded. The third argument, which is a structure member name, and
should be kept literal, gets expanded as well. The only safe way to use
these two macros is therefore to name the local variable passed to them
"obj".

To fix this, rename the sole argument of the two macros from
"obj" (which collides with the member name) to "OBJ". Additionally,
instead of passing "OBJ" to container_of() verbatim, parenthesize it, so
that a comma in the passed-in expression doesn't pollute the
container_of() invocation.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 7b371e7c4bc6..dd969224a9b9 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -95,8 +95,8 @@ struct switchdev_obj_port_vlan {
u16 vid_end;
 };
 
-#define SWITCHDEV_OBJ_PORT_VLAN(obj) \
-   container_of(obj, struct switchdev_obj_port_vlan, obj)
+#define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \
+   container_of((OBJ), struct switchdev_obj_port_vlan, obj)
 
 /* SWITCHDEV_OBJ_ID_PORT_MDB */
 struct switchdev_obj_port_mdb {
@@ -105,8 +105,8 @@ struct switchdev_obj_port_mdb {
u16 vid;
 };
 
-#define SWITCHDEV_OBJ_PORT_MDB(obj) \
-   container_of(obj, struct switchdev_obj_port_mdb, obj)
+#define SWITCHDEV_OBJ_PORT_MDB(OBJ) \
+   container_of((OBJ), struct switchdev_obj_port_mdb, obj)
 
 void switchdev_trans_item_enqueue(struct switchdev_trans *trans,
  void *data, void (*destructor)(void const *),
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 00/12] switchdev: Convert switchdev_port_obj_{add,del}() to notifiers

2018-11-22 Thread Petr Machata
An offloading driver may need to have access to switchdev events on
ports that aren't directly under its control. An example is a VXLAN port
attached to a bridge offloaded by a driver. The driver needs to know
about VLANs configured on the VXLAN device. However the VXLAN device
isn't stashed between the bridge and a front-panel-port device (such as
is the case e.g. for LAG devices), so the usual switchdev ops don't
reach the driver.

VXLAN is likely not the only device type like this: in theory any L2
tunnel device that needs offloading will prompt requirement of this
sort.

A way to fix this is to give up the notion of port object addition /
deletion as a switchdev operation, which assumes somewhat tight coupling
between the message producer and consumer. And instead send the message
over a notifier chain.

The series starts with a clean-up patch #1, where
SWITCHDEV_OBJ_PORT_{VLAN, MDB}() are fixed up to lift the constraint
that the passed-in argument be a simple variable named "obj".

switchdev_port_obj_add and _del are invoked in a context that permits
blocking. Not only that, at least for the VLAN notification, being able
to signal failure is actually important. Therefore introduce a new
blocking notifier chain that the new events will be sent on. That's done
in patch #2. Retain the current (atomic) notifier chain for the
preexisting notifications.

In patch #3, introduce two new switchdev notifier types,
SWITCHDEV_PORT_OBJ_ADD and SWITCHDEV_PORT_OBJ_DEL. These notifier types
communicate the same event as the corresponding switchdev op, except in
a form of a notification. struct switchdev_notifier_port_obj_info was
added to carry the fields that correspond to the switchdev op arguments.
An additional field, handled, will be used to communicate back to
switchdev that the event has reached an interested party, which will be
important for the two-phase commit.

In patches #4, #5, and #7, rocker, DSA resp. ethsw are updated to
subscribe to the switchdev blocking notifier chain, and handle the new
notifier types. #6 introduces a helper to determine whether a
netdevice corresponds to a front panel port.

What these three drivers have in common is that their ports don't
support any uppers besides bridge. That makes it possible to ignore any
notifiers that don't reference a front-panel port device, because they
are certainly out of scope.

Unlike the previous three, mlxsw and ocelot drivers admit stacked
devices as uppers. While the current switchdev code recursively descends
through layers of lower devices, eventually calling the op on a
front-panel port device, the notifier would reference a stacking device
that's one of front-panel ports uppers. The filtering is thus more
complex.

For ocelot, such iteration is currently pretty much required, because
there's no bookkeeping of LAG devices. mlxsw does keep the list of LAGs,
however it iterates the lower devices anyway when deciding whether an
event on a tunnel device pertains to the driver or not.

Therefore this patch set instead introduces, in patch #8, a helper to
iterate through lowers, much like the current switchdev code does,
looking for devices that match a given predicate.

Then in patches #9 and #10, first mlxsw and then ocelot are updated to
dispatch the newly-added notifier types to the preexisting
port_obj_add/_del handlers. The dispatch is done via the new helper, to
recursively descend through lower devices.

Finally in patch #11, the actual switch is made, retiring the current
SDO-based code in favor of a notifier.

Now that the event is distributed through a notifier, the explicit
netdevice check in rocker, DSA and ethsw doesn't let through any events
except those done on a front-panel port itself. It is therefore
unnecessary to check in VLAN-handling code whether a VLAN was added to
the bridge itself: such events will simply be ignored much sooner.
Therefore remove it in patch #12.

Petr Machata (12):
  switchdev: SWITCHDEV_OBJ_PORT_{VLAN, MDB}(): Sanitize
  switchdev: Add a blocking notifier chain
  switchdev: Add SWITCHDEV_PORT_OBJ_ADD, SWITCHDEV_PORT_OBJ_DEL
  rocker: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  net: dsa: slave: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  staging: fsl-dpaa2: ethsw: Introduce ethsw_port_dev_check()
  staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  switchdev: Add helpers to aid traversal through lower devices
  mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  ocelot: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  switchdev: Replace port obj add/del SDO with a notification
  rocker, dsa, ethsw: Don't filter VLAN events on bridge itself

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  47 -
 drivers/net/ethernet/mscc/ocelot.c |  30 +++-
 drivers/net/ethernet/mscc/ocelot.h |   1 +
 drivers/net/ethernet/mscc/ocelot_board.c   |   3 +
 drivers/net/ethernet/rocker/rocker_main.c  |  60 ++-
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  68 

[PATCH net-next 04/12] rocker: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

rocker currently doesn't support any uppers other than bridge. Thus the
only case that a stacked device could be validly referenced by port
object notifications are bridge notifications for VLAN objects added to
the bridge itself. But the driver explicitly rejects such notifications
in rocker_world_port_obj_vlan_add(). It is therefore safe to assume that
the only interesting case is that the notification is on a front-panel
port netdevice.

Subscribe to the blocking notifier chain. In the handler, filter out
notifications on any foreign netdevices. Dispatch the new notifiers to
rocker_port_obj_add() resp. _del() to maintain the behavior that the
switchdev operation based code currently has.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/net/ethernet/rocker/rocker_main.c | 55 +++
 1 file changed, 55 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index beb06628f22d..806ffe1d906e 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2812,12 +2812,54 @@ static int rocker_switchdev_event(struct notifier_block 
*unused,
return NOTIFY_DONE;
 }
 
+static int
+rocker_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
+   struct switchdev_notifier_port_obj_info *port_obj_info)
+{
+   int err = -EOPNOTSUPP;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = rocker_port_obj_add(netdev, port_obj_info->obj,
+ port_obj_info->trans);
+   break;
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = rocker_port_obj_del(netdev, port_obj_info->obj);
+   break;
+   }
+
+   port_obj_info->handled = true;
+   return notifier_from_errno(err);
+}
+
+static int rocker_switchdev_blocking_event(struct notifier_block *unused,
+  unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+   if (!rocker_port_dev_check(dev))
+   return NOTIFY_DONE;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   case SWITCHDEV_PORT_OBJ_DEL:
+   return rocker_switchdev_port_obj_event(event, dev, ptr);
+   }
+
+   return NOTIFY_DONE;
+}
+
 static struct notifier_block rocker_switchdev_notifier = {
.notifier_call = rocker_switchdev_event,
 };
 
+static struct notifier_block rocker_switchdev_blocking_notifier = {
+   .notifier_call = rocker_switchdev_blocking_event,
+};
+
 static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+   struct notifier_block *nb;
struct rocker *rocker;
int err;
 
@@ -2933,6 +2975,13 @@ static int rocker_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
goto err_register_switchdev_notifier;
}
 
+   nb = _switchdev_blocking_notifier;
+   err = register_switchdev_blocking_notifier(nb);
+   if (err) {
+   dev_err(>dev, "Failed to register switchdev blocking 
notifier\n");
+   goto err_register_switchdev_blocking_notifier;
+   }
+
rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
 
dev_info(>dev, "Rocker switch with id %*phN\n",
@@ -2940,6 +2989,8 @@ static int rocker_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
 
return 0;
 
+err_register_switchdev_blocking_notifier:
+   unregister_switchdev_notifier(_switchdev_notifier);
 err_register_switchdev_notifier:
unregister_fib_notifier(>fib_nb);
 err_register_fib_notifier:
@@ -2971,6 +3022,10 @@ static int rocker_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
 static void rocker_remove(struct pci_dev *pdev)
 {
struct rocker *rocker = pci_get_drvdata(pdev);
+   struct notifier_block *nb;
+
+   nb = _switchdev_blocking_notifier;
+   unregister_switchdev_blocking_notifier(nb);
 
unregister_switchdev_notifier(_switchdev_notifier);
unregister_fib_notifier(>fib_nb);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 05/10] staging: erofs: add a full barrier in erofs_workgroup_unfreeze

2018-11-22 Thread Andrea Parri
On Thu, Nov 22, 2018 at 06:56:32PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 18:22, Greg Kroah-Hartman wrote:
> > Please document this memory barrier.  It does not make much sense to
> > me...
> 
> Because we need to make the other observers noticing the latest values 
> modified
> in this locking period before unfreezing the whole workgroup, one way is to 
> use
> a memory barrier and the other way is to use ACQUIRE and RELEASE. we selected
> the first one.
> 
> Hmmm...ok, I will add a simple message to explain this, but I think that is
> plain enough for a lock...

Sympathizing with Greg's request, let me add some specific suggestions:

  1. It wouldn't hurt to indicate a pair of memory accesses which are
 intended to be "ordered" by the memory barrier in question (yes,
 this pair might not be unique, but you should be able to provide
 an example).

  2. Memory barriers always come matched by other memory barriers, or
 dependencies (it really does not make sense to talk about a full
 barrier "in isolation"): please also indicate (an instance of) a
 matching barrier or the matching barriers.

  3. How do the hardware threads communicate?  In the acquire/release
 pattern you mentioned above, the load-acquire *reads from* a/the
 previous store-release, a memory access that follows the acquire
 somehow communicate with a memory access preceding the release...

  4. It is a good practice to include the above information within an
 (inline) comment accompanying the added memory barrier (in fact,
 IIRC, checkpatch.pl gives you a "memory barrier without comment"
 warning when you omit to do so); not just in the commit message.

Hope this helps.  Please let me know if something I wrote is unclear,

  Andrea


> 
> Thanks,
> Gao Xiang
> 
> > 
> > thanks,
> > 
> > greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 10/10] staging: erofs: rename strange variable names in z_erofs_vle_frontend

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

Previously, 2 members called `initial' and `cachedzone_la' are used
for applying caching policy (whether the workgroup is at either end),
which are hard to understand, rename them to `backmost' and `headoffset'.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/unzip_vle.c | 25 +++--
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/erofs/unzip_vle.c 
b/drivers/staging/erofs/unzip_vle.c
index fab907e0fe06..f5d088fdf7f2 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -587,10 +587,9 @@ struct z_erofs_vle_frontend {
 
z_erofs_vle_owned_workgrp_t owned_head;
 
-   bool initial;
-#if (EROFS_FS_ZIP_CACHE_LVL >= 2)
-   erofs_off_t cachedzone_la;
-#endif
+   /* used for applying cache strategy on the fly */
+   bool backmost;
+   erofs_off_t headoffset;
 };
 
 #define VLE_FRONTEND_INIT(__i) { \
@@ -601,7 +600,7 @@ struct z_erofs_vle_frontend {
}, \
.builder = VLE_WORK_BUILDER_INIT(), \
.owned_head = Z_EROFS_VLE_WORKGRP_TAIL, \
-   .initial = true, }
+   .backmost = true, }
 
 static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
struct page *page,
@@ -644,7 +643,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend 
*fe,
debugln("%s: [out-of-range] pos %llu", __func__, offset + cur);
 
if (z_erofs_vle_work_iter_end(builder))
-   fe->initial = false;
+   fe->backmost = false;
 
map->m_la = offset + cur;
map->m_llen = 0;
@@ -670,8 +669,8 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend 
*fe,
erofs_blknr(map->m_pa),
grp->compressed_pages, erofs_blknr(map->m_plen),
/* compressed page caching selection strategy */
-   fe->initial | (EROFS_FS_ZIP_CACHE_LVL >= 2 ?
-   map->m_la < fe->cachedzone_la : 0));
+   fe->backmost | (EROFS_FS_ZIP_CACHE_LVL >= 2 ?
+   map->m_la < fe->headoffset : 0));
 
if (noio_outoforder && builder_is_followed(builder))
builder->role = Z_EROFS_VLE_WORK_PRIMARY;
@@ -1317,9 +1316,8 @@ static int z_erofs_vle_normalaccess_readpage(struct file 
*file,
 
trace_erofs_readpage(page, false);
 
-#if (EROFS_FS_ZIP_CACHE_LVL >= 2)
-   f.cachedzone_la = (erofs_off_t)page->index << PAGE_SHIFT;
-#endif
+   f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT;
+
err = z_erofs_do_read_page(, page, );
(void)z_erofs_vle_work_iter_end();
 
@@ -1355,9 +1353,8 @@ static int z_erofs_vle_normalaccess_readpages(struct file 
*filp,
trace_erofs_readpages(mapping->host, lru_to_page(pages),
  nr_pages, false);
 
-#if (EROFS_FS_ZIP_CACHE_LVL >= 2)
-   f.cachedzone_la = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT;
-#endif
+   f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT;
+
for (; nr_pages; --nr_pages) {
struct page *page = lru_to_page(pages);
 
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 09/10] staging: erofs: decompress asynchronously if PG_readahead page at first

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

For the case of nr_to_read == lookahead_size, it is better to
decompress asynchronously as well since no page will be needed immediately.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/unzip_vle.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/erofs/unzip_vle.c 
b/drivers/staging/erofs/unzip_vle.c
index 6aa3c989dd4e..fab907e0fe06 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1345,8 +1345,8 @@ static int z_erofs_vle_normalaccess_readpages(struct file 
*filp,
 {
struct inode *const inode = mapping->host;
struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
-   const bool sync = __should_decompress_synchronously(sbi, nr_pages);
 
+   bool sync = __should_decompress_synchronously(sbi, nr_pages);
struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode);
gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL);
struct page *head = NULL;
@@ -1364,6 +1364,13 @@ static int z_erofs_vle_normalaccess_readpages(struct 
file *filp,
prefetchw(>flags);
list_del(>lru);
 
+   /*
+* A pure asynchronous readahead is indicated if
+* a PG_readahead marked page is hitted at first.
+* Let's also do asynchronous decompression for this case.
+*/
+   sync &= !(PageReadahead(page) && !head);
+
if (add_to_page_cache_lru(page, mapping, page->index, gfp)) {
list_add(>lru, );
continue;
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

`z_erofs_vle_workgroup' is heavily generated in the decompression,
for example, it resets 32 bytes redundantly for 64-bit platforms
even through Z_EROFS_VLE_INLINE_PAGEVECS + Z_EROFS_CLUSTER_MAX_PAGES,
default 4, pages are stored in `z_erofs_vle_workgroup'.

As an another example, `struct mutex' takes 72 bytes for our kirin
64-bit platforms, it's unnecessary to be reseted at first and
be initialized each time.

Let's avoid filling all `z_erofs_vle_workgroup' with 0 at first
since most fields are reinitialized to meaningful values later,
and pagevec is no need to initialized at all.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/unzip_vle.c | 34 +-
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/erofs/unzip_vle.c 
b/drivers/staging/erofs/unzip_vle.c
index ede3383ac601..4e5843e8ee35 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -43,12 +43,38 @@ static inline int init_unzip_workqueue(void)
return z_erofs_workqueue ? 0 : -ENOMEM;
 }
 
+static void init_once(void *ptr)
+{
+   struct z_erofs_vle_workgroup *grp = ptr;
+   struct z_erofs_vle_work *const work =
+   z_erofs_vle_grab_primary_work(grp);
+   unsigned int i;
+
+   mutex_init(>lock);
+   work->nr_pages = 0;
+   work->vcnt = 0;
+   for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i)
+   grp->compressed_pages[i] = NULL;
+}
+
+static void init_always(struct z_erofs_vle_workgroup *grp)
+{
+   struct z_erofs_vle_work *const work =
+   z_erofs_vle_grab_primary_work(grp);
+
+   atomic_set(>obj.refcount, 1);
+   grp->flags = 0;
+
+   DBG_BUGON(work->nr_pages);
+   DBG_BUGON(work->vcnt);
+}
+
 int __init z_erofs_init_zip_subsystem(void)
 {
z_erofs_workgroup_cachep =
kmem_cache_create("erofs_compress",
  Z_EROFS_WORKGROUP_SIZE, 0,
- SLAB_RECLAIM_ACCOUNT, NULL);
+ SLAB_RECLAIM_ACCOUNT, init_once);
 
if (z_erofs_workgroup_cachep) {
if (!init_unzip_workqueue())
@@ -370,10 +396,11 @@ z_erofs_vle_work_register(const struct 
z_erofs_vle_work_finder *f,
BUG_ON(grp);
 
/* no available workgroup, let's allocate one */
-   grp = kmem_cache_zalloc(z_erofs_workgroup_cachep, GFP_NOFS);
+   grp = kmem_cache_alloc(z_erofs_workgroup_cachep, GFP_NOFS);
if (unlikely(!grp))
return ERR_PTR(-ENOMEM);
 
+   init_always(grp);
grp->obj.index = f->idx;
grp->llen = map->m_llen;
 
@@ -381,7 +408,6 @@ z_erofs_vle_work_register(const struct 
z_erofs_vle_work_finder *f,
(map->m_flags & EROFS_MAP_ZIPPED) ?
Z_EROFS_VLE_WORKGRP_FMT_LZ4 :
Z_EROFS_VLE_WORKGRP_FMT_PLAIN);
-   atomic_set(>obj.refcount, 1);
 
/* new workgrps have been claimed as type 1 */
WRITE_ONCE(grp->next, *f->owned_head);
@@ -394,8 +420,6 @@ z_erofs_vle_work_register(const struct 
z_erofs_vle_work_finder *f,
work = z_erofs_vle_grab_primary_work(grp);
work->pageofs = f->pageofs;
 
-   mutex_init(>lock);
-
if (gnew) {
int err = erofs_register_workgroup(f->sb, >obj, 0);
 
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 08/10] staging: erofs: locked before registering for all new workgroups

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

Let's make sure that the one registering a workgroup will also
take the primary work lock at first for two reasons:
  1) There's no need to introduce such a race window (and consequently
 overhead) between registering and locking, other tasks could break
 in by chance, and the race seems unnecessary (no benefit at all);

  2) It's better to take the primary work when a workgroup
 is registered to apply the cache managed policy, for example,
 if some other tasks break in, it could turn into the in-place
 decompression rather than use as the cached decompression.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/unzip_vle.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/erofs/unzip_vle.c 
b/drivers/staging/erofs/unzip_vle.c
index 4e5843e8ee35..6aa3c989dd4e 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -420,18 +420,23 @@ z_erofs_vle_work_register(const struct 
z_erofs_vle_work_finder *f,
work = z_erofs_vle_grab_primary_work(grp);
work->pageofs = f->pageofs;
 
+   /*
+* lock all primary followed works before visible to others
+* and mutex_trylock *never* fails for a new workgroup.
+*/
+   mutex_trylock(>lock);
+
if (gnew) {
int err = erofs_register_workgroup(f->sb, >obj, 0);
 
if (err) {
+   mutex_unlock(>lock);
kmem_cache_free(z_erofs_workgroup_cachep, grp);
return ERR_PTR(-EAGAIN);
}
}
 
*f->owned_head = *f->grp_ret = grp;
-
-   mutex_lock(>lock);
return work;
 }
 
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 06/10] staging: erofs: add a full barrier in erofs_workgroup_unfreeze

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

Just like other generic locks, insert a full barrier
in case of memory reorder.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/internal.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h
index 399a7003e783..892944355867 100644
--- a/drivers/staging/erofs/internal.h
+++ b/drivers/staging/erofs/internal.h
@@ -209,6 +209,11 @@ static inline bool erofs_workgroup_try_to_freeze(struct 
erofs_workgroup *grp,
 static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
int orig_val)
 {
+   /*
+* other observers should notice all modifications
+* in the freezing period.
+*/
+   smp_mb();
atomic_set(>refcount, orig_val);
preempt_enable();
 }
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 03/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

When the managed cache is enabled, the last reference count
of a workgroup must be used for its workstation.

Otherwise, it could lead to incorrect (un)freezes in
the reclaim path, and it would be harmful.

A typical race as follows:

Thread 1 (In the reclaim path)  Thread 2
workgroup_freeze(grp, 1)refcnt = 1
...
workgroup_unfreeze(grp, 1)  refcnt = 1
workgroup_get(grp)  refcnt = 2 (x)
workgroup_put(grp)  refcnt = 1 (x)
...unexpected behaviors

* grp is detached but still used, which violates cache-managed
  freeze constraint.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/internal.h |   1 +
 drivers/staging/erofs/utils.c| 134 +++
 2 files changed, 96 insertions(+), 39 deletions(-)

diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h
index 048fb034b5aa..3ac4599bbe01 100644
--- a/drivers/staging/erofs/internal.h
+++ b/drivers/staging/erofs/internal.h
@@ -250,6 +250,7 @@ static inline bool erofs_workgroup_get(struct 
erofs_workgroup *grp, int *ocnt)
 }
 
 #define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount)
+#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount)
 
 extern int erofs_workgroup_put(struct erofs_workgroup *grp);
 
diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c
index ea8a962e5c95..d2e3ace91046 100644
--- a/drivers/staging/erofs/utils.c
+++ b/drivers/staging/erofs/utils.c
@@ -83,12 +83,21 @@ int erofs_register_workgroup(struct super_block *sb,
 
grp = xa_tag_pointer(grp, tag);
 
-   err = radix_tree_insert(>workstn_tree,
-   grp->index, grp);
+   /*
+* Bump up reference count before making this workgroup
+* visible to other users in order to avoid potential UAF
+* without serialized by erofs_workstn_lock.
+*/
+   __erofs_workgroup_get(grp);
 
-   if (!err) {
-   __erofs_workgroup_get(grp);
-   }
+   err = radix_tree_insert(>workstn_tree,
+   grp->index, grp);
+   if (unlikely(err))
+   /*
+* it's safe to decrease since the workgroup isn't visible
+* and refcount >= 2 (cannot be freezed).
+*/
+   __erofs_workgroup_put(grp);
 
erofs_workstn_unlock(sbi);
radix_tree_preload_end();
@@ -97,19 +106,94 @@ int erofs_register_workgroup(struct super_block *sb,
 
 extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp);
 
+static void  __erofs_workgroup_free(struct erofs_workgroup *grp)
+{
+   atomic_long_dec(_global_shrink_cnt);
+   erofs_workgroup_free_rcu(grp);
+}
+
 int erofs_workgroup_put(struct erofs_workgroup *grp)
 {
int count = atomic_dec_return(>refcount);
 
if (count == 1)
atomic_long_inc(_global_shrink_cnt);
-   else if (!count) {
-   atomic_long_dec(_global_shrink_cnt);
-   erofs_workgroup_free_rcu(grp);
-   }
+   else if (!count)
+   __erofs_workgroup_free(grp);
return count;
 }
 
+#ifdef EROFS_FS_HAS_MANAGED_CACHE
+/* for cache-managed case, customized reclaim paths exist */
+static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp)
+{
+   erofs_workgroup_unfreeze(grp, 0);
+   __erofs_workgroup_free(grp);
+}
+
+bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
+   struct erofs_workgroup *grp,
+   bool cleanup)
+{
+   /*
+* for managed cache enabled, the refcount of workgroups
+* themselves could be < 0 (freezed). So there is no guarantee
+* that all refcount > 0 if managed cache is enabled.
+*/
+   if (!erofs_workgroup_try_to_freeze(grp, 1))
+   return false;
+
+   /*
+* note that all cached pages should be unlinked
+* before delete it from the radix tree.
+* Otherwise some cached pages of an orphan old workgroup
+* could be still linked after the new one is available.
+*/
+   if (erofs_try_to_free_all_cached_pages(sbi, grp)) {
+   erofs_workgroup_unfreeze(grp, 1);
+   return false;
+   }
+
+   /*
+* it is impossible to fail after the workgroup is freezed,
+* however in order to avoid some race conditions, add a
+* DBG_BUGON to observe this in advance.
+*/
+   DBG_BUGON(xa_untag_pointer(radix_tree_delete(>workstn_tree,
+grp->index)) != grp);
+
+   /*
+* if managed cache is enable, the last refcount
+* should indicate the related workstation.
+*/
+   erofs_workgroup_unfreeze_final(grp);
+   return true;
+}
+

[PATCH v2 04/10] staging: erofs: atomic_cond_read_relaxed on ref-locked workgroup

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

It's better to use atomic_cond_read_relaxed, which is implemented
in hardware instructions to monitor a variable changes currently
for ARM64, instead of open-coded busy waiting.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/internal.h | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h
index 3ac4599bbe01..f933ab602c37 100644
--- a/drivers/staging/erofs/internal.h
+++ b/drivers/staging/erofs/internal.h
@@ -221,23 +221,29 @@ static inline void erofs_workgroup_unfreeze(
preempt_enable();
 }
 
+#if defined(CONFIG_SMP)
+static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
+{
+   return atomic_cond_read_relaxed(>refcount,
+   VAL != EROFS_LOCKED_MAGIC);
+}
+#else
+static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
+{
+   int v = atomic_read(>refcount);
+
+   /* workgroup is never freezed on uniprocessor systems */
+   DBG_BUGON(v == EROFS_LOCKED_MAGIC);
+   return v;
+}
+#endif
+
 static inline bool erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt)
 {
-   const int locked = (int)EROFS_LOCKED_MAGIC;
int o;
 
 repeat:
-   o = atomic_read(>refcount);
-
-   /* spin if it is temporarily locked at the reclaim path */
-   if (unlikely(o == locked)) {
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-   do
-   cpu_relax();
-   while (atomic_read(>refcount) == locked);
-#endif
-   goto repeat;
-   }
+   o = erofs_wait_on_workgroup_freezed(grp);
 
if (unlikely(o <= 0))
return -1;
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 05/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

There are two minor issues in the current freeze interface:

   1) Freeze interfaces have not related with CONFIG_DEBUG_SPINLOCK,
  therefore fix the incorrect conditions;

   2) For SMP platforms, it should also disable preemption before
  doing atomic_cmpxchg in case that some high priority tasks
  preempt between atomic_cmpxchg and disable_preempt, then spin
  on the locked refcount later.

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/internal.h | 41 
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h
index f933ab602c37..399a7003e783 100644
--- a/drivers/staging/erofs/internal.h
+++ b/drivers/staging/erofs/internal.h
@@ -194,40 +194,49 @@ struct erofs_workgroup {
 
 #define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL)
 
-static inline bool erofs_workgroup_try_to_freeze(
-   struct erofs_workgroup *grp, int v)
+#if defined(CONFIG_SMP)
+static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
+int val)
 {
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-   if (v != atomic_cmpxchg(>refcount,
-   v, EROFS_LOCKED_MAGIC))
-   return false;
preempt_disable();
-#else
-   preempt_disable();
-   if (atomic_read(>refcount) != v) {
+   if (val != atomic_cmpxchg(>refcount, val, EROFS_LOCKED_MAGIC)) {
preempt_enable();
return false;
}
-#endif
return true;
 }
 
-static inline void erofs_workgroup_unfreeze(
-   struct erofs_workgroup *grp, int v)
+static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
+   int orig_val)
 {
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-   atomic_set(>refcount, v);
-#endif
+   atomic_set(>refcount, orig_val);
preempt_enable();
 }
 
-#if defined(CONFIG_SMP)
 static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
 {
return atomic_cond_read_relaxed(>refcount,
VAL != EROFS_LOCKED_MAGIC);
 }
 #else
+static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
+int val)
+{
+   preempt_disable();
+   /* no need to spin on UP platforms, let's just disable preemption. */
+   if (val != atomic_read(>refcount)) {
+   preempt_enable();
+   return false;
+   }
+   return true;
+}
+
+static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
+   int orig_val)
+{
+   preempt_enable();
+}
+
 static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
 {
int v = atomic_read(>refcount);
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 01/10] staging: erofs: fix `trace_erofs_readpage' position

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

`trace_erofs_readpage' was designed for .readpage() interface hook
in order to trace the detailed synchronized read rather than
the internal implementation `z_erofs_do_read_page' which both
.readpage() and .readpages() use.

It seems the tracepoint was placed to a wrong place by mistake and
it should be moved to the right place.

Fixes: 284db12cfda3 ("staging: erofs: add trace points for reading zipped data")
Reviewed-by: Chen Gong 
Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/unzip_vle.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/erofs/unzip_vle.c 
b/drivers/staging/erofs/unzip_vle.c
index 6a283f618f46..ede3383ac601 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -598,8 +598,6 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend 
*fe,
unsigned int cur, end, spiltted, index;
int err = 0;
 
-   trace_erofs_readpage(page, false);
-
/* register locked file pages as online pages in pack */
z_erofs_onlinepage_init(page);
 
@@ -1288,6 +1286,8 @@ static int z_erofs_vle_normalaccess_readpage(struct file 
*file,
int err;
LIST_HEAD(pagepool);
 
+   trace_erofs_readpage(page, false);
+
 #if (EROFS_FS_ZIP_CACHE_LVL >= 2)
f.cachedzone_la = (erofs_off_t)page->index << PAGE_SHIFT;
 #endif
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 02/10] staging: erofs: fix the definition of DBG_BUGON

2018-11-22 Thread Gao Xiang
From: Gao Xiang 

It's better not to positively BUG_ON the kernel, however developers
need a way to locate issues as soon as possible.

DBG_BUGON is introduced and it could only crash when EROFS_FS_DEBUG
(EROFS developping feature) is on. It is helpful for developers
to find and solve bugs quickly by eng builds.

Previously, DBG_BUGON is defined as ((void)0) if EROFS_FS_DEBUG is off,
but some unused variable warnings as follows could occur:

drivers/staging/erofs/unzip_vle.c: In function `init_alway:':
drivers/staging/erofs/unzip_vle.c:61:33: warning: unused variable `work' 
[-Wunused-variable]
  struct z_erofs_vle_work *const work =
 ^~~~

Fix it to #define DBG_BUGON(x) ((void)(x)).

Reviewed-by: Chao Yu 
Signed-off-by: Gao Xiang 
---
 drivers/staging/erofs/internal.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h
index 57575c7f5635..048fb034b5aa 100644
--- a/drivers/staging/erofs/internal.h
+++ b/drivers/staging/erofs/internal.h
@@ -39,7 +39,7 @@
 #define debugln(x, ...) ((void)0)
 
 #define dbg_might_sleep()   ((void)0)
-#define DBG_BUGON(...)  ((void)0)
+#define DBG_BUGON(x)((void)(x))
 #endif
 
 enum {
-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 00/10] staging: erofs: decompression stability enhancement

2018-11-22 Thread Gao Xiang
Hi,

This patchset mainly focuses on erofs decompression stability, most of
them are found in the internal beta test. Some patches which are still
in testing or reviewing aren't included in this patchset and will be
sent after carefully testing.

Thanks,
Gao Xiang

Changelog from v1
===
  o fix a redundant BUG_ON suggested by Greg since it never happens at all;
  o add more description suggested by Greg in commit message of 
  [01/10] staging: erofs: fix `trace_erofs_readpage' position
  o add some description suggested by Greg of a memory barrier occurred in
  [06/10] staging: erofs: add a full barrier in erofs_workgroup_unfreeze 

Shortlog
===
Gao Xiang (10):
  staging: erofs: fix `trace_erofs_readpage' position
  staging: erofs: fix the definition of DBG_BUGON
  staging: erofs: fix race when the managed cache is enabled
  staging: erofs: atomic_cond_read_relaxed on ref-locked workgroup
  staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'
  staging: erofs: add a full barrier in erofs_workgroup_unfreeze
  staging: erofs: separate into init_once / always
  staging: erofs: locked before registering for all new workgroups
  staging: erofs: decompress asynchronously if PG_readahead page at
first
  staging: erofs: rename strange variable names in z_erofs_vle_frontend

 drivers/staging/erofs/internal.h  |  73 +
 drivers/staging/erofs/unzip_vle.c |  79 +++---
 drivers/staging/erofs/utils.c | 135 +++---
 3 files changed, 199 insertions(+), 88 deletions(-)

-- 
2.11.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 3/3] staging: greybus: arche-platform: Switch to the gpio descriptor interface

2018-11-22 Thread Nishad Kamdar
Use the gpiod interface instead of the deprecated
old non-descriptor interface.

Signed-off-by: Nishad Kamdar 
---
Changes in v2:
 - Move comment to the same line as to what it applies to.
---
 drivers/staging/greybus/arche-platform.c | 119 ---
 1 file changed, 41 insertions(+), 78 deletions(-)

diff --git a/drivers/staging/greybus/arche-platform.c 
b/drivers/staging/greybus/arche-platform.c
index 4c36e88766e7..a5cea79d8e32 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -8,10 +8,9 @@
 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -45,14 +44,14 @@ enum svc_wakedetect_state {
 
 struct arche_platform_drvdata {
/* Control GPIO signals to and from AP <=> SVC */
-   int svc_reset_gpio;
+   struct gpio_desc *svc_reset;
+   struct gpio_desc *svc_sysboot;
bool is_reset_act_hi;
-   int svc_sysboot_gpio;
-   int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
+   struct gpio_desc *wake_detect; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME 
signals */
 
enum arche_platform_state state;
 
-   int svc_refclk_req;
+   struct gpio_desc *svc_refclk_req;
struct clk *svc_ref_clk;
 
struct pinctrl *pinctrl;
@@ -85,9 +84,9 @@ static void arche_platform_set_wake_detect_state(
arche_pdata->wake_detect_state = state;
 }
 
-static inline void svc_reset_onoff(unsigned int gpio, bool onoff)
+static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff)
 {
-   gpio_set_value(gpio, onoff);
+   gpiod_set_value(gpio, onoff);
 }
 
 static int apb_cold_boot(struct device *dev, void *data)
@@ -116,7 +115,6 @@ static int apb_poweroff(struct device *dev, void *data)
 static void arche_platform_wd_irq_en(struct arche_platform_drvdata 
*arche_pdata)
 {
/* Enable interrupt here, to read event back from SVC */
-   gpio_direction_input(arche_pdata->wake_detect_gpio);
enable_irq(arche_pdata->wake_detect_irq);
 }
 
@@ -160,7 +158,7 @@ static irqreturn_t arche_platform_wd_irq(int irq, void 
*devid)
 
spin_lock_irqsave(_pdata->wake_lock, flags);
 
-   if (gpio_get_value(arche_pdata->wake_detect_gpio)) {
+   if (gpiod_get_value(arche_pdata->wake_detect)) {
/* wake/detect rising */
 
/*
@@ -224,10 +222,10 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata 
*arche_pdata)
 
dev_info(arche_pdata->dev, "Booting from cold boot state\n");
 
-   svc_reset_onoff(arche_pdata->svc_reset_gpio,
+   svc_reset_onoff(arche_pdata->svc_reset,
arche_pdata->is_reset_act_hi);
 
-   gpio_set_value(arche_pdata->svc_sysboot_gpio, 0);
+   gpiod_set_value(arche_pdata->svc_sysboot, 0);
usleep_range(100, 200);
 
ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
@@ -238,7 +236,7 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata 
*arche_pdata)
}
 
/* bring SVC out of reset */
-   svc_reset_onoff(arche_pdata->svc_reset_gpio,
+   svc_reset_onoff(arche_pdata->svc_reset,
!arche_pdata->is_reset_act_hi);
 
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE);
@@ -259,10 +257,10 @@ arche_platform_fw_flashing_seq(struct 
arche_platform_drvdata *arche_pdata)
 
dev_info(arche_pdata->dev, "Switching to FW flashing state\n");
 
-   svc_reset_onoff(arche_pdata->svc_reset_gpio,
+   svc_reset_onoff(arche_pdata->svc_reset,
arche_pdata->is_reset_act_hi);
 
-   gpio_set_value(arche_pdata->svc_sysboot_gpio, 1);
+   gpiod_set_value(arche_pdata->svc_sysboot, 1);
 
usleep_range(100, 200);
 
@@ -273,7 +271,7 @@ arche_platform_fw_flashing_seq(struct 
arche_platform_drvdata *arche_pdata)
return ret;
}
 
-   svc_reset_onoff(arche_pdata->svc_reset_gpio,
+   svc_reset_onoff(arche_pdata->svc_reset,
!arche_pdata->is_reset_act_hi);
 
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING);
@@ -305,7 +303,7 @@ arche_platform_poweroff_seq(struct arche_platform_drvdata 
*arche_pdata)
clk_disable_unprepare(arche_pdata->svc_ref_clk);
 
/* As part of exit, put APB back in reset state */
-   svc_reset_onoff(arche_pdata->svc_reset_gpio,
+   svc_reset_onoff(arche_pdata->svc_reset,
arche_pdata->is_reset_act_hi);
 
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
@@ -435,6 +433,7 @@ static int arche_platform_probe(struct platform_device 
*pdev)
struct device *dev = >dev;
struct device_node *np = dev->of_node;
int ret;
+   unsigned int flags;
 
arche_pdata = devm_kzalloc(>dev, sizeof(*arche_pdata),
   GFP_KERNEL);
@@ -444,61 +443,33 @@ static int arche_platform_probe(struct 

[PATCH v3 2/3] staging: greybus: arche-apb-ctrl.c: Switch to the gpio descriptor interface

2018-11-22 Thread Nishad Kamdar
Use the gpiod interface instead of the deprecated old non-descriptor
interface.

Signed-off-by: Nishad Kamdar 
---
Changes in v2:
 - Resolved compilation errors.
---
 drivers/staging/greybus/arche-apb-ctrl.c | 159 +--
 1 file changed, 65 insertions(+), 94 deletions(-)

diff --git a/drivers/staging/greybus/arche-apb-ctrl.c 
b/drivers/staging/greybus/arche-apb-ctrl.c
index be5ffed90bcf..e887f6aee20b 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -8,9 +8,8 @@
 
 #include 
 #include 
-#include 
+#include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -24,12 +23,12 @@ static void apb_bootret_deassert(struct device *dev);
 
 struct arche_apb_ctrl_drvdata {
/* Control GPIO signals to and from AP <=> AP Bridges */
-   int resetn_gpio;
-   int boot_ret_gpio;
-   int pwroff_gpio;
-   int wake_in_gpio;
-   int wake_out_gpio;
-   int pwrdn_gpio;
+   struct gpio_desc *resetn;
+   struct gpio_desc *boot_ret;
+   struct gpio_desc *pwroff;
+   struct gpio_desc *wake_in;
+   struct gpio_desc *wake_out;
+   struct gpio_desc *pwrdn;
 
enum arche_platform_state state;
bool init_disabled;
@@ -37,28 +36,28 @@ struct arche_apb_ctrl_drvdata {
struct regulator *vcore;
struct regulator *vio;
 
-   int clk_en_gpio;
+   struct gpio_desc *clk_en;
struct clk *clk;
 
struct pinctrl *pinctrl;
struct pinctrl_state *pin_default;
 
/* V2: SPI Bus control  */
-   int spi_en_gpio;
+   struct gpio_desc *spi_en;
bool spi_en_polarity_high;
 };
 
 /*
  * Note that these low level api's are active high
  */
-static inline void deassert_reset(unsigned int gpio)
+static inline void deassert_reset(struct gpio_desc *gpio)
 {
-   gpio_set_value(gpio, 1);
+   gpiod_set_value(gpio, 1);
 }
 
-static inline void assert_reset(unsigned int gpio)
+static inline void assert_reset(struct gpio_desc *gpio)
 {
-   gpio_set_value(gpio, 0);
+   gpiod_set_value(gpio, 0);
 }
 
 /*
@@ -75,11 +74,11 @@ static int coldboot_seq(struct platform_device *pdev)
return 0;
 
/* Hold APB in reset state */
-   assert_reset(apb->resetn_gpio);
+   assert_reset(apb->resetn);
 
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
-   gpio_is_valid(apb->spi_en_gpio))
-   devm_gpio_free(dev, apb->spi_en_gpio);
+   apb->spi_en)
+   devm_gpiod_put(dev, apb->spi_en);
 
/* Enable power to APB */
if (!IS_ERR(apb->vcore)) {
@@ -101,13 +100,13 @@ static int coldboot_seq(struct platform_device *pdev)
apb_bootret_deassert(dev);
 
/* On DB3 clock was not mandatory */
-   if (gpio_is_valid(apb->clk_en_gpio))
-   gpio_set_value(apb->clk_en_gpio, 1);
+   if (apb->clk_en)
+   gpiod_set_value(apb->clk_en, 1);
 
usleep_range(100, 200);
 
/* deassert reset to APB : Active-low signal */
-   deassert_reset(apb->resetn_gpio);
+   deassert_reset(apb->resetn);
 
apb->state = ARCHE_PLATFORM_STATE_ACTIVE;
 
@@ -119,6 +118,7 @@ static int fw_flashing_seq(struct platform_device *pdev)
struct device *dev = >dev;
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
int ret;
+   unsigned long flags;
 
if (apb->init_disabled ||
apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
@@ -136,25 +136,20 @@ static int fw_flashing_seq(struct platform_device *pdev)
return ret;
}
 
-   if (gpio_is_valid(apb->spi_en_gpio)) {
-   unsigned long flags;
+   if (apb->spi_en_polarity_high)
+   flags = GPIOD_OUT_HIGH;
+   else
+   flags = GPIOD_OUT_LOW;
 
-   if (apb->spi_en_polarity_high)
-   flags = GPIOF_OUT_INIT_HIGH;
-   else
-   flags = GPIOF_OUT_INIT_LOW;
-
-   ret = devm_gpio_request_one(dev, apb->spi_en_gpio,
-   flags, "apb_spi_en");
-   if (ret) {
-   dev_err(dev, "Failed requesting SPI bus en gpio %d\n",
-   apb->spi_en_gpio);
-   return ret;
-   }
+   apb->spi_en = devm_gpiod_get(dev, "gb,spi-en-gpio", flags);
+   if (IS_ERR(apb->spi_en)) {
+   ret = PTR_ERR(apb->spi_en);
+   dev_err(dev, "Failed requesting SPI bus en GPIO: %d\n", ret);
+   return ret;
}
 
/* for flashing device should be in reset state */
-   assert_reset(apb->resetn_gpio);
+   assert_reset(apb->resetn);
apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING;
 
return 0;
@@ -177,8 +172,8 @@ static int standby_boot_seq(struct platform_device *pdev)
return 0;
 
if (apb->state == 

[PATCH v3 1/3] staging: greybus: gpio: switch GPIO portions to use GPIOLIB_IRQCHIP

2018-11-22 Thread Nishad Kamdar
Convert the GPIO driver to use the GPIO irqchip library
GPIOLIB_IRQCHIP instead of reimplementing the same.

Signed-off-by: Nishad Kamdar 
---
Changes in v2:
 - Retained irq.h and irqdomain.h headers.
 - Dropped function gb_gpio_irqchip_add() and
   called gpiochip_irqchip_add() from probe().
 - Referred 
https://lkml.kernel.org/r/1476054589-28422-1-git-send-email-linus.wall...@linaro.org.
---
 drivers/staging/greybus/Kconfig |   1 +
 drivers/staging/greybus/gpio.c  | 184 
 2 files changed, 24 insertions(+), 161 deletions(-)

diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig
index ab096bcef98c..b571e4e8060b 100644
--- a/drivers/staging/greybus/Kconfig
+++ b/drivers/staging/greybus/Kconfig
@@ -148,6 +148,7 @@ if GREYBUS_BRIDGED_PHY
 config GREYBUS_GPIO
tristate "Greybus GPIO Bridged PHY driver"
depends on GPIOLIB
+   select GPIOLIB_IRQCHIP
---help---
  Select this option if you have a device that follows the
  Greybus GPIO Bridged PHY Class specification.
diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c
index b1d4698019a1..2ec54744171d 100644
--- a/drivers/staging/greybus/gpio.c
+++ b/drivers/staging/greybus/gpio.c
@@ -9,9 +9,9 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
 
 #include "greybus.h"
@@ -39,15 +39,8 @@ struct gb_gpio_controller {
 
struct gpio_chipchip;
struct irq_chip irqc;
-   struct irq_chip *irqchip;
-   struct irq_domain   *irqdomain;
-   unsigned intirq_base;
-   irq_flow_handler_t  irq_handler;
-   unsigned intirq_default_type;
struct mutexirq_lock;
 };
-#define gpio_chip_to_gb_gpio_controller(chip) \
-   container_of(chip, struct gb_gpio_controller, chip)
 #define irq_data_to_gpio_chip(d) (d->domain->host_data)
 
 static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc)
@@ -276,7 +269,7 @@ static void _gb_gpio_irq_set_type(struct gb_gpio_controller 
*ggc,
 static void gb_gpio_irq_mask(struct irq_data *d)
 {
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
-   struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+   struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = >lines[d->hwirq];
 
line->masked = true;
@@ -286,7 +279,7 @@ static void gb_gpio_irq_mask(struct irq_data *d)
 static void gb_gpio_irq_unmask(struct irq_data *d)
 {
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
-   struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+   struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = >lines[d->hwirq];
 
line->masked = false;
@@ -296,7 +289,7 @@ static void gb_gpio_irq_unmask(struct irq_data *d)
 static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
-   struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+   struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = >lines[d->hwirq];
struct device *dev = >gbphy_dev->dev;
u8 irq_type;
@@ -334,7 +327,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, 
unsigned int type)
 static void gb_gpio_irq_bus_lock(struct irq_data *d)
 {
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
-   struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+   struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
 
mutex_lock(>irq_lock);
 }
@@ -342,7 +335,7 @@ static void gb_gpio_irq_bus_lock(struct irq_data *d)
 static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d)
 {
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
-   struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+   struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = >lines[d->hwirq];
 
if (line->irq_type_pending) {
@@ -391,7 +384,7 @@ static int gb_gpio_request_handler(struct gb_operation *op)
return -EINVAL;
}
 
-   irq = irq_find_mapping(ggc->irqdomain, event->which);
+   irq = irq_find_mapping(ggc->chip.irq.domain, event->which);
if (!irq) {
dev_err(dev, "failed to find IRQ\n");
return -EINVAL;
@@ -411,21 +404,21 @@ static int gb_gpio_request_handler(struct gb_operation 
*op)
 
 static int gb_gpio_request(struct gpio_chip *chip, unsigned int offset)
 {
-   struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+   struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
 
return gb_gpio_activate_operation(ggc, (u8)offset);
 }
 
 static void gb_gpio_free(struct gpio_chip *chip, unsigned int offset)
 {
-   struct 

[PATCH v3 0/3] greybus: gpio: Switch to the gpio descriptor interface

2018-11-22 Thread Nishad Kamdar
This patch series converts uses of the old GPIO API to the GPIO
descriptor API. It also converts the GPIO driver to use the
GPIO irqchip library GPIOLIB_IRQCHIP instead of repimplementing
the same.

Changes in v3:
 - Combines the latest versions of the three greybus patches together
   in a patch series.

Nishad Kamdar (3):
  staging: greybus: gpio: switch GPIO portions to use GPIOLIB_IRQCHIP
  staging: greybus: arche-apb-ctrl.c: Switch to the gpio descriptor
interface
  staging: greybus: arche-platform: Switch to the gpio descriptor
interface

 drivers/staging/greybus/Kconfig  |   1 +
 drivers/staging/greybus/arche-apb-ctrl.c | 159 
 drivers/staging/greybus/arche-platform.c | 119 +--
 drivers/staging/greybus/gpio.c   | 184 +++
 4 files changed, 130 insertions(+), 333 deletions(-)

-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH] staging: greybus: arche-platform: Switch to the gpio descriptor interface

2018-11-22 Thread Nishad Kamdar
On Tue, Nov 20, 2018 at 10:49:54AM +0100, Greg Kroah-Hartman wrote:
> On Sat, Nov 17, 2018 at 04:40:27PM +0100, Johan Hovold wrote:
> > On Sat, Nov 17, 2018 at 12:41:11PM +0530, Nishad Kamdar wrote:
> > > On Fri, Nov 16, 2018 at 05:06:22PM +0100, Johan Hovold wrote:
> > > > On Fri, Nov 16, 2018 at 08:47:44PM +0530, Nishad Kamdar wrote:
> > > > > Use the gpiod interface instead of the deprecated
> > > > > old non-descriptor interface.
> > > > > 
> > > > > Signed-off-by: Nishad Kamdar 
> > > > > ---
> > > > 
> > > > Always include a change log here after the cut-off line so we know what
> > > > changed since previous versions.
> > > > 
> > > > Also include the patch revision in the Subject (e.g. "[PATCH v3]
> > > > staging: greybus: ...").
> > > > 
> > > 
> > > Ok, but this is the first patch version that I submitted
> > > for greybus: arche-platform.
> > 
> > Ah, sorry. I thought this was an update of the arche-apb-ctrl patch.
> 
> Me too.
> 
> I am totally confused as to what is, and is not, the latest versions of
> all of these patches :(
> 
> Nishad, can you resend all of your pending greybus patches, as a patch
> series, as "v3" so that I know which to properly review?  I've dropped
> all of your others from my review queue now.
> 
> thanks,
> 
> greg k-h

Ok, I'll do that.

Thanks for the review.

Regards,
Nishad
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 06/13] ARM: dts: imx7s: add mipi phy power domain

2018-11-22 Thread Rui Miguel Silva
Add power domain index 0 related with mipi-phy to imx7s.

While at it rename pcie power-domain node to remove pgc prefix.

Signed-off-by: Rui Miguel Silva 
---
 arch/arm/boot/dts/imx7s.dtsi | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index aa8df7d93b2e..6e2e4f99cdb0 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -608,7 +608,13 @@
#address-cells = <1>;
#size-cells = <0>;
 
-   pgc_pcie_phy: pgc-power-domain@1 {
+   pgc_mipi_phy: power-domain@0 {
+   #power-domain-cells = <0>;
+   reg = <0>;
+   power-supply = <_1p0d>;
+   };
+
+   pgc_pcie_phy: power-domain@1 {
#power-domain-cells = <0>;
reg = <1>;
power-supply = <_1p0d>;
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 03/13] media: staging/imx7: add imx7 CSI subdev driver

2018-11-22 Thread Rui Miguel Silva
This add the media entity subdevice and control driver for the i.MX7
CMOS Sensor Interface.

Signed-off-by: Rui Miguel Silva 
---
 drivers/staging/media/imx/Kconfig  |9 +-
 drivers/staging/media/imx/Makefile |2 +
 drivers/staging/media/imx/imx7-media-csi.c | 1354 
 3 files changed, 1364 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/media/imx/imx7-media-csi.c

diff --git a/drivers/staging/media/imx/Kconfig 
b/drivers/staging/media/imx/Kconfig
index bfc17de56b17..36b276ea2ecc 100644
--- a/drivers/staging/media/imx/Kconfig
+++ b/drivers/staging/media/imx/Kconfig
@@ -11,7 +11,7 @@ config VIDEO_IMX_MEDIA
  driver for the i.MX5/6 SOC.
 
 if VIDEO_IMX_MEDIA
-menu "i.MX5/6 Media Sub devices"
+menu "i.MX5/6/7 Media Sub devices"
 
 config VIDEO_IMX_CSI
tristate "i.MX5/6 Camera Sensor Interface driver"
@@ -20,5 +20,12 @@ config VIDEO_IMX_CSI
---help---
  A video4linux camera sensor interface driver for i.MX5/6.
 
+config VIDEO_IMX7_CSI
+   tristate "i.MX7 Camera Sensor Interface driver"
+   depends on VIDEO_IMX_MEDIA && VIDEO_DEV && I2C
+   default y
+   help
+ Enable support for video4linux camera sensor interface driver for
+ i.MX7.
 endmenu
 endif
diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index a30b3033f9a3..074f016d3519 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-ic.o
 
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
+
+obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
new file mode 100644
index ..9f0a37766cbb
--- /dev/null
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -0,0 +1,1354 @@
+// SPDX-License-Identifier: GPL
+/*
+ * V4L2 Capture CSI Subdev for Freescale i.MX7 SOC
+ *
+ * Copyright (c) 2018 Linaro Ltd
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include "imx-media.h"
+
+#define IMX7_CSI_PAD_SINK  0
+#define IMX7_CSI_PAD_SRC   1
+#define IMX7_CSI_PADS_NUM  2
+
+/* reset values */
+#define CSICR1_RESET_VAL   0x4800
+#define CSICR2_RESET_VAL   0x0
+#define CSICR3_RESET_VAL   0x0
+
+/* csi control reg 1 */
+#define BIT_SWAP16_EN  BIT(31)
+#define BIT_EXT_VSYNC  BIT(30)
+#define BIT_EOF_INT_EN BIT(29)
+#define BIT_PRP_IF_EN  BIT(28)
+#define BIT_CCIR_MODE  BIT(27)
+#define BIT_COF_INT_EN BIT(26)
+#define BIT_SF_OR_INTENBIT(25)
+#define BIT_RF_OR_INTENBIT(24)
+#define BIT_SFF_DMA_DONE_INTEN  BIT(22)
+#define BIT_STATFF_INTEN   BIT(21)
+#define BIT_FB2_DMA_DONE_INTEN  BIT(20)
+#define BIT_FB1_DMA_DONE_INTEN  BIT(19)
+#define BIT_RXFF_INTEN BIT(18)
+#define BIT_SOF_POLBIT(17)
+#define BIT_SOF_INTEN  BIT(16)
+#define BIT_MCLKDIV(0xF << 12)
+#define BIT_HSYNC_POL  BIT(11)
+#define BIT_CCIR_ENBIT(10)
+#define BIT_MCLKEN BIT(9)
+#define BIT_FCCBIT(8)
+#define BIT_PACK_DIR   BIT(7)
+#define BIT_CLR_STATFIFO   BIT(6)
+#define BIT_CLR_RXFIFO BIT(5)
+#define BIT_GCLK_MODE  BIT(4)
+#define BIT_INV_DATA   BIT(3)
+#define BIT_INV_PCLK   BIT(2)
+#define BIT_REDGE  BIT(1)
+#define BIT_PIXEL_BIT  BIT(0)
+
+#define SHIFT_MCLKDIV  12
+
+/* control reg 3 */
+#define BIT_FRMCNT (0x << 16)
+#define BIT_FRMCNT_RST BIT(15)
+#define BIT_DMA_REFLASH_RFFBIT(14)
+#define BIT_DMA_REFLASH_SFFBIT(13)
+#define BIT_DMA_REQ_EN_RFF BIT(12)
+#define BIT_DMA_REQ_EN_SFF BIT(11)
+#define BIT_STATFF_LEVEL   (0x7 << 8)
+#define BIT_HRESP_ERR_EN   BIT(7)
+#define BIT_RXFF_LEVEL (0x7 << 4)
+#define BIT_TWO_8BIT_SENSORBIT(3)
+#define BIT_ZERO_PACK_EN   BIT(2)
+#define BIT_ECC_INT_EN BIT(1)
+#define BIT_ECC_AUTO_ENBIT(0)
+
+#define SHIFT_FRMCNT   16
+#define SHIFT_RXFIFO_LEVEL 4
+
+/* csi status reg */
+#define BIT_ADDR_CH_ERR_INTBIT(28)
+#define BIT_FIELD0_INT BIT(27)
+#define BIT_FIELD1_INT BIT(26)
+#define BIT_SFF_OR_INT BIT(25)
+#define BIT_RFF_OR_INT BIT(24)
+#define BIT_DMA_TSF_DONE_SFF   BIT(22)
+#define BIT_STATFF_INT BIT(21)
+#define BIT_DMA_TSF_DONE_FB2   BIT(20)
+#define BIT_DMA_TSF_DONE_FB1   BIT(19)
+#define BIT_RXFF_INT   BIT(18)
+#define BIT_EOF_INTBIT(17)
+#define BIT_SOF_INTBIT(16)
+#define BIT_F2_INT BIT(15)
+#define BIT_F1_INT BIT(14)
+#define 

[PATCH v9 02/13] media: staging/imx: rearrange group id to take in account IPU

2018-11-22 Thread Rui Miguel Silva
Some imx system do not have IPU, so prepare the imx media drivers to
support this kind of devices. Rename the group ids to include an _IPU_
prefix, add a new group id to support systems with only a CSI without
IPU, and also rename the create internal links to make it clear that
only systems with IPU have internal subdevices.

Signed-off-by: Rui Miguel Silva 
---
 drivers/staging/media/imx/imx-ic-common.c |  6 ++---
 drivers/staging/media/imx/imx-ic-prp.c| 16 ++---
 drivers/staging/media/imx/imx-media-csi.c |  6 ++---
 drivers/staging/media/imx/imx-media-dev.c | 22 ++
 .../staging/media/imx/imx-media-internal-sd.c | 20 
 drivers/staging/media/imx/imx-media-utils.c   | 12 +-
 drivers/staging/media/imx/imx-media.h | 23 ++-
 7 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index cfdd4900a3be..765919487a73 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -41,13 +41,13 @@ static int imx_ic_probe(struct platform_device *pdev)
pdata = priv->dev->platform_data;
priv->ipu_id = pdata->ipu_id;
switch (pdata->grp_id) {
-   case IMX_MEDIA_GRP_ID_IC_PRP:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
priv->task_id = IC_TASK_PRP;
break;
-   case IMX_MEDIA_GRP_ID_IC_PRPENC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
priv->task_id = IC_TASK_ENCODER;
break;
-   case IMX_MEDIA_GRP_ID_IC_PRPVF:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
priv->task_id = IC_TASK_VIEWFINDER;
break;
default:
diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 98923fc844ce..2702548f83cf 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -77,7 +77,7 @@ static int prp_start(struct prp_priv *priv)
priv->ipu = priv->md->ipu[ic_priv->ipu_id];
 
/* set IC to receive from CSI or VDI depending on source */
-   src_is_vdic = !!(priv->src_sd->grp_id & IMX_MEDIA_GRP_ID_VDIC);
+   src_is_vdic = !!(priv->src_sd->grp_id & IMX_MEDIA_GRP_ID_IPU_VDIC);
 
ipu_set_ic_src_mux(priv->ipu, priv->csi_id, src_is_vdic);
 
@@ -237,8 +237,8 @@ static int prp_link_setup(struct media_entity *entity,
ret = -EBUSY;
goto out;
}
-   if (priv->sink_sd_prpenc && (remote_sd->grp_id &
-IMX_MEDIA_GRP_ID_VDIC)) {
+   if (priv->sink_sd_prpenc &&
+   (remote_sd->grp_id & IMX_MEDIA_GRP_ID_IPU_VDIC)) {
ret = -EINVAL;
goto out;
}
@@ -259,7 +259,7 @@ static int prp_link_setup(struct media_entity *entity,
goto out;
}
if (priv->src_sd && (priv->src_sd->grp_id &
-IMX_MEDIA_GRP_ID_VDIC)) {
+IMX_MEDIA_GRP_ID_IPU_VDIC)) {
ret = -EINVAL;
goto out;
}
@@ -309,13 +309,13 @@ static int prp_link_validate(struct v4l2_subdev *sd,
return ret;
 
csi = imx_media_find_upstream_subdev(priv->md, _priv->sd.entity,
-IMX_MEDIA_GRP_ID_CSI);
+IMX_MEDIA_GRP_ID_IPU_CSI);
if (IS_ERR(csi))
csi = NULL;
 
mutex_lock(>lock);
 
-   if (priv->src_sd->grp_id & IMX_MEDIA_GRP_ID_VDIC) {
+   if (priv->src_sd->grp_id & IMX_MEDIA_GRP_ID_IPU_VDIC) {
/*
 * the ->PRPENC link cannot be enabled if the source
 * is the VDIC
@@ -334,10 +334,10 @@ static int prp_link_validate(struct v4l2_subdev *sd,
 
if (csi) {
switch (csi->grp_id) {
-   case IMX_MEDIA_GRP_ID_CSI0:
+   case IMX_MEDIA_GRP_ID_IPU_CSI0:
priv->csi_id = 0;
break;
-   case IMX_MEDIA_GRP_ID_CSI1:
+   case IMX_MEDIA_GRP_ID_IPU_CSI1:
priv->csi_id = 1;
break;
default:
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 4223f8d418ae..a12fa1dd989e 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1029,10 +1029,10 @@ static int csi_link_setup(struct media_entity *entity,
 
remote_sd = media_entity_to_v4l2_subdev(remote->entity);
 

[PATCH v9 11/13] media: staging/imx: add i.MX7 entries to TODO file

2018-11-22 Thread Rui Miguel Silva
Add some i.MX7 related entries to TODO file.

Signed-off-by: Rui Miguel Silva 
---
 drivers/staging/media/imx/TODO | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index aeeb15494a49..6f29b5ca5324 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -45,3 +45,12 @@
 
  Which means a port must not contain mixed-use endpoints, they
  must all refer to media links between V4L2 subdevices.
+
+- i.MX7: all of the above, since it uses the imx media core
+
+- i.MX7: use Frame Interval Monitor
+
+- i.MX7: runtime testing with parallel sensor, links setup and streaming
+
+- i.MX7: runtime testing with different formats, for the time only 10-bit bayer
+  is tested
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 07/13] ARM: dts: imx7s: add multiplexer controls

2018-11-22 Thread Rui Miguel Silva
The IOMUXC General Purpose Register has bitfield to control video bus
multiplexer to control the CSI input between the MIPI-CSI2 and parallel
interface. Add that register and mask.

Signed-off-by: Rui Miguel Silva 
Reviewed-by: Philipp Zabel 
---
 arch/arm/boot/dts/imx7s.dtsi | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 6e2e4f99cdb0..174635a73fb6 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -499,8 +499,15 @@
 
gpr: iomuxc-gpr@3034 {
compatible = "fsl,imx7d-iomuxc-gpr",
-   "fsl,imx6q-iomuxc-gpr", "syscon";
+   "fsl,imx6q-iomuxc-gpr", "syscon",
+   "simple-mfd";
reg = <0x3034 0x1>;
+
+   mux: mux-controller {
+   compatible = "mmio-mux";
+   #mux-control-cells = <0>;
+   mux-reg-masks = <0x14 0x0010>;
+   };
};
 
ocotp: ocotp-ctrl@3035 {
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 13/13] media: MAINTAINERS: add entry for Freescale i.MX7 media driver

2018-11-22 Thread Rui Miguel Silva
Add maintainer entry for the imx7 media csi, mipi csis driver,
dt-bindings and documentation.

Signed-off-by: Rui Miguel Silva 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0abecc528dac..afa2ad3c5600 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9134,6 +9134,17 @@ T:   git git://linuxtv.org/media_tree.git
 S: Maintained
 F: drivers/media/platform/imx-pxp.[ch]
 
+MEDIA DRIVERS FOR FREESCALE IMX7
+M: Rui Miguel Silva 
+L: linux-me...@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: Documentation/devicetree/bindings/media/imx7-csi.txt
+F: Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt
+F: Documentation/media/v4l-drivers/imx7.rst
+F: drivers/staging/media/imx/imx7-media-csi.c
+F: drivers/staging/media/imx/imx7-mipi-csis.c
+
 MEDIA DRIVERS FOR HELENE
 M: Abylay Ospan 
 L: linux-me...@vger.kernel.org
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 08/13] ARM: dts: imx7: Add video mux, csi and mipi_csi and connections

2018-11-22 Thread Rui Miguel Silva
This patch adds the device tree nodes for csi, video multiplexer and
mipi-csi besides the graph connecting the necessary endpoints to make
the media capture entities to work in imx7 Warp board.

Signed-off-by: Rui Miguel Silva 
---
 arch/arm/boot/dts/imx7s-warp.dts | 51 
 arch/arm/boot/dts/imx7s.dtsi | 27 +
 2 files changed, 78 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts
index f7ba2c0a24ad..757856a3964b 100644
--- a/arch/arm/boot/dts/imx7s-warp.dts
+++ b/arch/arm/boot/dts/imx7s-warp.dts
@@ -276,6 +276,57 @@
status = "okay";
 };
 
+ {
+   csi_mux {
+   compatible = "video-mux";
+   mux-controls = < 0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@1 {
+   reg = <1>;
+
+   csi_mux_from_mipi_vc0: endpoint {
+   remote-endpoint = <_vc0_to_csi_mux>;
+   };
+   };
+
+   port@2 {
+   reg = <2>;
+
+   csi_mux_to_csi: endpoint {
+   remote-endpoint = <_from_csi_mux>;
+   };
+   };
+   };
+};
+
+ {
+   status = "okay";
+
+   port {
+   csi_from_csi_mux: endpoint {
+   remote-endpoint = <_mux_to_csi>;
+   };
+   };
+};
+
+_csi {
+   clock-frequency = <16600>;
+   status = "okay";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   fsl,csis-hs-settle = <3>;
+
+   port@1 {
+   reg = <1>;
+
+   mipi_vc0_to_csi_mux: endpoint {
+   remote-endpoint = <_mux_from_mipi_vc0>;
+   };
+   };
+};
+
  {
pinctrl-names = "default";
pinctrl-0 = <_wdog>;
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 174635a73fb6..0c495082e2bf 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "imx7d-pinfunc.h"
 
 / {
@@ -711,6 +712,17 @@
status = "disabled";
};
 
+   csi: csi@3071 {
+   compatible = "fsl,imx7-csi";
+   reg = <0x3071 0x1>;
+   interrupts = ;
+   clocks = < IMX7D_CLK_DUMMY>,
+   < IMX7D_CSI_MCLK_ROOT_CLK>,
+   < IMX7D_CLK_DUMMY>;
+   clock-names = "axi", "mclk", "dcic";
+   status = "disabled";
+   };
+
lcdif: lcdif@3073 {
compatible = "fsl,imx7d-lcdif", 
"fsl,imx28-lcdif";
reg = <0x3073 0x1>;
@@ -720,6 +732,21 @@
clock-names = "pix", "axi";
status = "disabled";
};
+
+   mipi_csi: mipi-csi@3075 {
+   compatible = "fsl,imx7-mipi-csi2";
+   reg = <0x3075 0x1>;
+   interrupts = ;
+   clocks = < IMX7D_IPG_ROOT_CLK>,
+   < IMX7D_MIPI_CSI_ROOT_CLK>,
+   < IMX7D_MIPI_DPHY_ROOT_CLK>;
+   clock-names = "pclk", "wrap", "phy";
+   power-domains = <_mipi_phy>;
+   phy-supply = <_1p0d>;
+   resets = < IMX7_RESET_MIPI_PHY_MRST>;
+   reset-names = "mrst";
+   status = "disabled";
+   };
};
 
aips3: aips-bus@3080 {
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 10/13] media: imx7.rst: add documentation for i.MX7 media driver

2018-11-22 Thread Rui Miguel Silva
Add rst document to describe the i.MX7 media driver and also a working
example from the Warp7 board usage with a OV2680 sensor.

Signed-off-by: Rui Miguel Silva 
---
 Documentation/media/v4l-drivers/imx7.rst  | 157 ++
 Documentation/media/v4l-drivers/index.rst |   1 +
 2 files changed, 158 insertions(+)
 create mode 100644 Documentation/media/v4l-drivers/imx7.rst

diff --git a/Documentation/media/v4l-drivers/imx7.rst 
b/Documentation/media/v4l-drivers/imx7.rst
new file mode 100644
index ..cd1195d391c5
--- /dev/null
+++ b/Documentation/media/v4l-drivers/imx7.rst
@@ -0,0 +1,157 @@
+i.MX7 Video Capture Driver
+==
+
+Introduction
+
+
+The i.MX7 contrary to the i.MX5/6 family does not contain an Image Processing
+Unit (IPU); because of that the capabilities to perform operations or
+manipulation of the capture frames are less feature rich.
+
+For image capture the i.MX7 has three units:
+- CMOS Sensor Interface (CSI)
+- Video Multiplexer
+- MIPI CSI-2 Receiver
+
+::
+   |\
+   MIPI Camera Input ---> MIPI CSI-2 --- > | \
+   |  \
+   | M |
+   | U | -->  CSI ---> Capture
+   | X |
+   |  /
+   Parallel Camera Input > | /
+   |/
+
+For additional information, please refer to the latest versions of the i.MX7
+reference manual [#f1]_.
+
+Entities
+
+
+imx7-mipi-csi2
+--
+
+This is the MIPI CSI-2 receiver entity. It has one sink pad to receive the 
pixel
+data from MIPI CSI-2 camera sensor. It has one source pad, corresponding to the
+virtual channel 0. This module is compliant to previous version of Samsung
+D-phy, and supports two D-PHY Rx Data lanes.
+
+csi_mux
+---
+
+This is the video multiplexer. It has two sink pads to select from either 
camera
+sensor with a parallel interface or from MIPI CSI-2 virtual channel 0.  It has
+a single source pad that routes to the CSI.
+
+csi
+---
+
+The CSI enables the chip to connect directly to external CMOS image sensor. CSI
+can interface directly with Parallel and MIPI CSI-2 buses. It has 256 x 64 FIFO
+to store received image pixel data and embedded DMA controllers to transfer 
data
+from the FIFO through AHB bus.
+
+This entity has one sink pad that receives from the csi_mux entity and a single
+source pad that routes video frames directly to memory buffers. This pad is
+routed to a capture device node.
+
+Usage Notes
+---
+
+To aid in configuration and for backward compatibility with V4L2 applications
+that access controls only from video device nodes, the capture device 
interfaces
+inherit controls from the active entities in the current pipeline, so controls
+can be accessed either directly from the subdev or from the active capture
+device interface. For example, the sensor controls are available either from 
the
+sensor subdevs or from the active capture device.
+
+Warp7 with OV2680
+-
+
+On this platform an OV2680 MIPI CSI-2 module is connected to the internal MIPI
+CSI-2 receiver. The following example configures a video capture pipeline with
+an output of 800x600, and BGGR 10 bit bayer format:
+
+.. code-block:: none
+   # Setup links
+   media-ctl -l "'ov2680 1-0036':0 -> 'imx7-mipi-csis.0':0[1]"
+   media-ctl -l "'imx7-mipi-csis.0':1 -> 'csi_mux':1[1]"
+   media-ctl -l "'csi_mux':2 -> 'csi':0[1]"
+   media-ctl -l "'csi':1 -> 'csi capture':0[1]"
+
+   # Configure pads for pipeline
+   media-ctl -V "'ov2680 1-0036':0 [fmt:SBGGR10_1X10/800x600 field:none]"
+   media-ctl -V "'csi_mux':1 [fmt:SBGGR10_1X10/800x600 field:none]"
+   media-ctl -V "'csi_mux':2 [fmt:SBGGR10_1X10/800x600 field:none]"
+   media-ctl -V "'imx7-mipi-csis.0':0 [fmt:SBGGR10_1X10/800x600 field:none]"
+   media-ctl -V "'csi':0 [fmt:SBGGR10_1X10/800x600 field:none]"
+
+After this streaming can start. The v4l2-ctl tool can be used to select any of
+the resolutions supported by the sensor.
+
+.. code-block:: none
+root@imx7s-warp:~# media-ctl -p
+Media controller API version 4.17.0
+
+Media device information
+
+driver  imx-media
+model   imx-media
+serial
+bus info
+hw revision 0x0
+driver version  4.17.0
+
+Device topology
+- entity 1: csi (2 pads, 2 links)
+   type V4L2 subdev subtype Unknown flags 0
+   device node name /dev/v4l-subdev0
+   pad0: Sink
+   [fmt:SBGGR10_1X10/800x600 field:none]
+   <- "csi_mux":2 [ENABLED]
+   pad1: Source
+   [fmt:SBGGR10_1X10/800x600 field:none]
+   -> "csi capture":0 [ENABLED]
+
+- entity 4: csi capture (1 pad, 1 link)
+   type Node subtype 

[PATCH v9 12/13] media: video-mux: add bayer formats

2018-11-22 Thread Rui Miguel Silva
Add non vendor bayer formats to the  allowed format array.

Signed-off-by: Rui Miguel Silva 
---
 drivers/media/platform/video-mux.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/media/platform/video-mux.c 
b/drivers/media/platform/video-mux.c
index c33900e3c23e..0ba30756e1e4 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -263,6 +263,26 @@ static int video_mux_set_format(struct v4l2_subdev *sd,
case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
case MEDIA_BUS_FMT_JPEG_1X8:
case MEDIA_BUS_FMT_AHSV_1X32:
+   case MEDIA_BUS_FMT_SBGGR8_1X8:
+   case MEDIA_BUS_FMT_SGBRG8_1X8:
+   case MEDIA_BUS_FMT_SGRBG8_1X8:
+   case MEDIA_BUS_FMT_SRGGB8_1X8:
+   case MEDIA_BUS_FMT_SBGGR10_1X10:
+   case MEDIA_BUS_FMT_SGBRG10_1X10:
+   case MEDIA_BUS_FMT_SGRBG10_1X10:
+   case MEDIA_BUS_FMT_SRGGB10_1X10:
+   case MEDIA_BUS_FMT_SBGGR12_1X12:
+   case MEDIA_BUS_FMT_SGBRG12_1X12:
+   case MEDIA_BUS_FMT_SGRBG12_1X12:
+   case MEDIA_BUS_FMT_SRGGB12_1X12:
+   case MEDIA_BUS_FMT_SBGGR14_1X14:
+   case MEDIA_BUS_FMT_SGBRG14_1X14:
+   case MEDIA_BUS_FMT_SGRBG14_1X14:
+   case MEDIA_BUS_FMT_SRGGB14_1X14:
+   case MEDIA_BUS_FMT_SBGGR16_1X16:
+   case MEDIA_BUS_FMT_SGBRG16_1X16:
+   case MEDIA_BUS_FMT_SGRBG16_1X16:
+   case MEDIA_BUS_FMT_SRGGB16_1X16:
break;
default:
sdformat->format.code = MEDIA_BUS_FMT_Y8_1X8;
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 05/13] media: dt-bindings: add bindings for i.MX7 media driver

2018-11-22 Thread Rui Miguel Silva
Add bindings documentation for i.MX7 media drivers.
The imx7 MIPI CSI2 and imx7 CMOS Sensor Interface.

Signed-off-by: Rui Miguel Silva 
Reviewed-by: Rob Herring 
Acked-by: Sakari Ailus 
---
 .../devicetree/bindings/media/imx7-csi.txt| 45 ++
 .../bindings/media/imx7-mipi-csi2.txt | 90 +++
 2 files changed, 135 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/imx7-csi.txt
 create mode 100644 Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt

diff --git a/Documentation/devicetree/bindings/media/imx7-csi.txt 
b/Documentation/devicetree/bindings/media/imx7-csi.txt
new file mode 100644
index ..3c07bc676bc3
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/imx7-csi.txt
@@ -0,0 +1,45 @@
+Freescale i.MX7 CMOS Sensor Interface
+=
+
+csi node
+
+
+This is device node for the CMOS Sensor Interface (CSI) which enables the chip
+to connect directly to external CMOS image sensors.
+
+Required properties:
+
+- compatible: "fsl,imx7-csi";
+- reg   : base address and length of the register set for the device;
+- interrupts: should contain CSI interrupt;
+- clocks: list of clock specifiers, see
+Documentation/devicetree/bindings/clock/clock-bindings.txt for details;
+- clock-names   : must contain "axi", "mclk" and "dcic" entries, matching
+ entries in the clock property;
+
+The device node shall contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in:
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+In the following example a remote endpoint is a video multiplexer.
+
+example:
+
+csi: csi@3071 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+compatible = "fsl,imx7-csi";
+reg = <0x3071 0x1>;
+interrupts = ;
+clocks = < IMX7D_CLK_DUMMY>,
+< IMX7D_CSI_MCLK_ROOT_CLK>,
+< IMX7D_CLK_DUMMY>;
+clock-names = "axi", "mclk", "dcic";
+
+port {
+csi_from_csi_mux: endpoint {
+remote-endpoint = <_mux_to_csi>;
+};
+};
+};
diff --git a/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt 
b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt
new file mode 100644
index ..71fd74ed3ec8
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt
@@ -0,0 +1,90 @@
+Freescale i.MX7 Mipi CSI2
+=
+
+mipi_csi2 node
+--
+
+This is the device node for the MIPI CSI-2 receiver core in i.MX7 SoC. It is
+compatible with previous version of Samsung D-phy.
+
+Required properties:
+
+- compatible: "fsl,imx7-mipi-csi2";
+- reg   : base address and length of the register set for the device;
+- interrupts: should contain MIPI CSIS interrupt;
+- clocks: list of clock specifiers, see
+Documentation/devicetree/bindings/clock/clock-bindings.txt for details;
+- clock-names   : must contain "pclk", "wrap" and "phy" entries, matching
+  entries in the clock property;
+- power-domains : a phandle to the power domain, see
+  Documentation/devicetree/bindings/power/power_domain.txt for details.
+- reset-names   : should include following entry "mrst";
+- resets: a list of phandle, should contain reset entry of
+  reset-names;
+- phy-supply: from the generic phy bindings, a phandle to a regulator that
+ provides power to MIPI CSIS core;
+
+Optional properties:
+
+- clock-frequency : The IP's main (system bus) clock frequency in Hz, default
+   value when this property is not specified is 166 MHz;
+- fsl,csis-hs-settle : differential receiver (HS-RX) settle time;
+
+The device node should contain two 'port' child nodes with one child 'endpoint'
+node, according to the bindings defined in:
+ Documentation/devicetree/bindings/ media/video-interfaces.txt.
+ The following are properties specific to those nodes.
+
+port node
+-
+
+- reg: (required) can take the values 0 or 1, where 0 shall be
+ related to the sink port and port 1 shall be the source
+ one;
+
+endpoint node
+-
+
+- data-lanes: (required) an array specifying active physical MIPI-CSI2
+   data input lanes and their mapping to logical lanes; this
+shall only be applied to port 0 (sink port), the array's
+content is unused only its length is meaningful,
+in this case the maximum length supported is 

[PATCH v9 04/13] media: staging/imx7: add MIPI CSI-2 receiver subdev for i.MX7

2018-11-22 Thread Rui Miguel Silva
Adds MIPI CSI-2 subdev for i.MX7 to connect with sensors with a MIPI
CSI-2 interface.

Signed-off-by: Rui Miguel Silva 
---
 drivers/staging/media/imx/Makefile |1 +
 drivers/staging/media/imx/imx7-mipi-csis.c | 1135 
 2 files changed, 1136 insertions(+)
 create mode 100644 drivers/staging/media/imx/imx7-mipi-csis.c

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index 074f016d3519..d2d909a36239 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
+obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-mipi-csis.o
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
new file mode 100644
index ..56963d0c2043
--- /dev/null
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -0,0 +1,1135 @@
+// SPDX-License-Identifier: GPL
+/*
+ * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver
+ *
+ * Copyright (C) 2018 Linaro Ltd
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "imx-media.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+#define CSIS_DRIVER_NAME   "imx7-mipi-csis"
+#define CSIS_SUBDEV_NAME   CSIS_DRIVER_NAME
+
+#define CSIS_PAD_SINK  0
+#define CSIS_PAD_SOURCE1
+#define CSIS_PADS_NUM  2
+
+#define MIPI_CSIS_DEF_PIX_WIDTH640
+#define MIPI_CSIS_DEF_PIX_HEIGHT   480
+
+/* Register map definition */
+
+/* CSIS common control */
+#define MIPI_CSIS_CMN_CTRL 0x04
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW   BIT(16)
+#define MIPI_CSIS_CMN_CTRL_INTER_MODE  BIT(10)
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL  BIT(2)
+#define MIPI_CSIS_CMN_CTRL_RESET   BIT(1)
+#define MIPI_CSIS_CMN_CTRL_ENABLE  BIT(0)
+
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET  8
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK(3 << 8)
+
+/* CSIS clock control */
+#define MIPI_CSIS_CLK_CTRL 0x08
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x)((x) << 28)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x)((x) << 24)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x)((x) << 20)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x)((x) << 16)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK  (0xf << 4)
+#define MIPI_CSIS_CLK_CTRL_WCLK_SRCBIT(0)
+
+/* CSIS Interrupt mask */
+#define MIPI_CSIS_INTMSK   0x10
+#define MIPI_CSIS_INTMSK_EVEN_BEFORE   BIT(31)
+#define MIPI_CSIS_INTMSK_EVEN_AFTERBIT(30)
+#define MIPI_CSIS_INTMSK_ODD_BEFOREBIT(29)
+#define MIPI_CSIS_INTMSK_ODD_AFTER BIT(28)
+#define MIPI_CSIS_INTMSK_FRAME_START   BIT(24)
+#define MIPI_CSIS_INTMSK_FRAME_END BIT(20)
+#define MIPI_CSIS_INTMSK_ERR_SOT_HSBIT(16)
+#define MIPI_CSIS_INTMSK_ERR_LOST_FS   BIT(12)
+#define MIPI_CSIS_INTMSK_ERR_LOST_FE   BIT(8)
+#define MIPI_CSIS_INTMSK_ERR_OVER  BIT(4)
+#define MIPI_CSIS_INTMSK_ERR_WRONG_CFG BIT(3)
+#define MIPI_CSIS_INTMSK_ERR_ECC   BIT(2)
+#define MIPI_CSIS_INTMSK_ERR_CRC   BIT(1)
+#define MIPI_CSIS_INTMSK_ERR_UNKNOWN   BIT(0)
+
+/* CSIS Interrupt source */
+#define MIPI_CSIS_INTSRC   0x14
+#define MIPI_CSIS_INTSRC_EVEN_BEFORE   BIT(31)
+#define MIPI_CSIS_INTSRC_EVEN_AFTERBIT(30)
+#define MIPI_CSIS_INTSRC_EVEN  BIT(30)
+#define MIPI_CSIS_INTSRC_ODD_BEFOREBIT(29)
+#define MIPI_CSIS_INTSRC_ODD_AFTER BIT(28)
+#define MIPI_CSIS_INTSRC_ODD   (0x3 << 28)
+#define MIPI_CSIS_INTSRC_NON_IMAGE_DATA(0xf << 28)
+#define MIPI_CSIS_INTSRC_FRAME_START   BIT(24)
+#define MIPI_CSIS_INTSRC_FRAME_END BIT(20)
+#define MIPI_CSIS_INTSRC_ERR_SOT_HSBIT(16)
+#define MIPI_CSIS_INTSRC_ERR_LOST_FS   BIT(12)
+#define MIPI_CSIS_INTSRC_ERR_LOST_FE   BIT(8)
+#define MIPI_CSIS_INTSRC_ERR_OVER  BIT(4)
+#define MIPI_CSIS_INTSRC_ERR_WRONG_CFG BIT(3)
+#define MIPI_CSIS_INTSRC_ERR_ECC   BIT(2)
+#define MIPI_CSIS_INTSRC_ERR_CRC   BIT(1)
+#define MIPI_CSIS_INTSRC_ERR_UNKNOWN   BIT(0)
+#define MIPI_CSIS_INTSRC_ERRORS0xf
+
+/* D-PHY status control */
+#define MIPI_CSIS_DPHYSTATUS   0x20
+#define MIPI_CSIS_DPHYSTATUS_ULPS_DAT  BIT(8)
+#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_DAT BIT(4)
+#define MIPI_CSIS_DPHYSTATUS_ULPS_CLK  BIT(1)
+#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_CLK BIT(0)
+
+/* D-PHY common control */
+#define MIPI_CSIS_DPHYCTRL 0x24

[PATCH v9 09/13] ARM: dts: imx7s-warp: add ov2680 sensor node

2018-11-22 Thread Rui Miguel Silva
Warp7 comes with a Omnivision OV2680 sensor, add the node here to make
complete the camera data path for this system. Add the needed regulator
to the analog voltage supply, the port and endpoints in mipi_csi node
and the pinctrl for the reset gpio.

Signed-off-by: Rui Miguel Silva 
---
 arch/arm/boot/dts/imx7s-warp.dts | 44 
 1 file changed, 44 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts
index 757856a3964b..4ada85850411 100644
--- a/arch/arm/boot/dts/imx7s-warp.dts
+++ b/arch/arm/boot/dts/imx7s-warp.dts
@@ -54,6 +54,14 @@
regulator-always-on;
};
 
+   reg_peri_3p15v: regulator-peri-3p15v {
+   compatible = "regulator-fixed";
+   regulator-name = "peri_3p15v_reg";
+   regulator-min-microvolt = <315>;
+   regulator-max-microvolt = <315>;
+   regulator-always-on;
+   };
+
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "imx7-sgtl5000";
@@ -177,6 +185,27 @@
pinctrl-names = "default";
pinctrl-0 = <_i2c2>;
status = "okay";
+
+   ov2680: camera@36 {
+   compatible = "ovti,ov2680";
+   pinctrl-names = "default";
+   pinctrl-0 = <_ov2680>;
+   reg = <0x36>;
+   clocks = <>;
+   clock-names = "xvclk";
+   reset-gpios = < 3 GPIO_ACTIVE_LOW>;
+   DOVDD-supply = <_reg>;
+   DVDD-supply = <_reg>;
+   AVDD-supply = <_peri_3p15v>;
+
+   port {
+   ov2680_to_mipi: endpoint {
+   remote-endpoint = <_from_sensor>;
+   clock-lanes = <0>;
+   data-lanes = <1>;
+   };
+   };
+   };
 };
 
  {
@@ -318,6 +347,15 @@
#size-cells = <0>;
fsl,csis-hs-settle = <3>;
 
+   port@0 {
+   reg = <0>;
+
+   mipi_from_sensor: endpoint {
+   remote-endpoint = <_to_mipi>;
+   data-lanes = <1>;
+   };
+   };
+
port@1 {
reg = <1>;
 
@@ -381,6 +419,12 @@
>;
};
 
+   pinctrl_ov2680: ov2660grp {
+   fsl,pins = <
+   MX7D_PAD_LPSR_GPIO1_IO03__GPIO1_IO3 0x14
+   >;
+   };
+
pinctrl_sai1: sai1grp {
fsl,pins = <
MX7D_PAD_SAI1_RX_DATA__SAI1_RX_DATA00x1f
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v9 00/13] media: staging/imx7: add i.MX7 media driver

2018-11-22 Thread Rui Miguel Silva
Hi,
This series introduces the Media driver to work with the i.MX7 SoC. it uses the
already existing imx media core drivers but since the i.MX7, contrary to
i.MX5/6, do not have an IPU and because of that some changes in the imx media
core are made along this series to make it support that case.

This patches adds CSI and MIPI-CSI2 drivers for i.MX7, along with several
configurations changes for this to work as a capture subsystem. Some bugs are
also fixed along the line. And necessary documentation.

For a more detailed view of the capture paths, pads links in the i.MX7 please
take a look at the documentation in PATCH 10.

The system used to test and develop this was the Warp7 board with an OV2680
sensor, which output format is 10-bit bayer. So, only MIPI interface was
tested, a scenario with an parallel input would nice to have.


Bellow goes an example of the output of the pads and links and the output of
v4l2-compliance testing.

The v4l-utils version used is:
v4l2-compliance SHA   : 044d5ab7b0d02683070d01a369c73d462d7a0cee from Nov 19th

The Media Driver fail some tests but this failures are coming from code out of
scope of this series (imx-capture), and some from the sensor OV2680
but that I think not related with the sensor driver but with the testing and
core.

The csi and mipi-csi entities pass all compliance tests.

Cheers,
Rui

v8->v9:
Hans Verkuil:
 - Fix issues detected by checkpatch strict, still some left:
 - bigger kconfig option description
 - some alignement parenthesis that were left as they are, to be more
 readable 
 - added new patch (PATCH13) for Maintainers update
 - SPDX in documentation rst file
Sakari Ailus:
 - remove pad check in csi, this is done by core already
 - destroy mutex in probe error path (add label)
 - swap order in driver release
 - initialize endpoint in stack
 - use clk_bulk
kbuild test robot:
 - add the missing imx-media-dev-common.c in patch 1/13
 - remove OWNER of module csis
Myself:
 - add MAINTAINERS entries - new patch

v7->v8:
Myself:
 - rebase to latest linux-next (s/V4L2_MBUS_CSI2/V4L2_MBUS_CSI2_DPHY/)
 - Rebuild and test with latest v4l2-compliance
 - add Sakari reviewed-by tag to dt-bindings

v6->v7:
Myself:
 - Clock patches removed from this version since they were already merged
 - Rebuild and test with the latest v4l2-compliance
 - Add patch to video-mux regarding bayer formats
 - remove reference to dependent patch serie (was already merged)

Sakari Ailus:
 - add port and endpoint explanantions
 - fix some wording should -> shall

v5->v6:
Rob Herring:
 - rename power-domain node name from: pgc-power-domain to power-domain
 - change mux-control-cells to 0
 - remove bus-width from mipi bindings and dts
 - remove err... regarding clock names line
 - remove clk-settle from example
 - split mipi-csi2 and csi bindings per file
 - add OF graph description to CSI

Philipp Zabel:
 - rework group IDs and rename them with an _IPU_ prefix, this allowed to remove
   the ipu_present flag need.

v4->v5:
Sakari Ailus:
 - fix remove of the capture entries in dts bindings in the right patch

Stephen Boyd:
 - Send all series to clk list

v3->v4:
Philipp Zabel:
 - refactor initialization code from media device probe to be possible to used
   from other modules
 - Remove index of csi from all accurrencs (dts, code, documentation)
 - Remove need for capture node for imx7
 - fix pinctrl for ov2680
 - add reviewed tag to add multiplexer controls patch

Fabio Estevam:
 - remove always on from new regulator

Randy Dunlap:
 - several text editing fixes in documentation

Myself:
 - rebase on top of v4 of Steve series
 - change CSI probe to initialize imx media device
 - remove csi mux parallel endpoint from mux to avoid warning message

v2->v3:
Philipp Zabel:
 - use of_match_device in imx-media-dev instead of of_device_match
 - fix number of data lanes from 4 to 2
 - change the clock definitions and use of mipi
 - move hs-settle from endpoint

Rob Herring:
 - fix phy-supply description
 - add vendor properties
 - fix examples indentations

Stephen Boyd: patch 3/14
 - fix double sign-off
 - add fixes tag

Dong Aisheng: patch 3/14
 - fix double sign-off
 - add Acked-by tag

Shawn Guo:
patch 4/14
 - remove line breakage in parent redifiniton
 - added Acked-by tag

 - dropped CMA area increase and add more verbose information in case of
   dma allocation failure
patch 9/14
 - remove extra line between cells and reg masks

Myself:
 - rework on frame end in csi
 - add rxcount in csi driver
 - add power supplies to ov2680 node and fix gpio polarity

v1->v2:
Dan Carpenter:
 - fix return paths and codes;
 - fix clk_frequency validation and return code;
 - handle the csi remove (release resources that was missing)
 - revert the logic arround the ipu_present flag

Philipp Zabel:
 - drop patch that changed the rgb formats and address the pixel/bus format in
   mipi_csis code.

MySelf:
 - add patch that add ov2680 node to the warp7 dts, so the all data path is
   

[PATCH v9 01/13] media: staging/imx: refactor imx media device probe

2018-11-22 Thread Rui Miguel Silva
Refactor and move media device initialization code to a new common
module, so it can be used by other devices, this will allow for example
a near to introduce imx7 CSI driver, to use this media device.

Signed-off-by: Rui Miguel Silva 
---
 drivers/staging/media/imx/Makefile|   1 +
 .../staging/media/imx/imx-media-dev-common.c  | 102 ++
 drivers/staging/media/imx/imx-media-dev.c |  88 ---
 drivers/staging/media/imx/imx-media-of.c  |   6 +-
 drivers/staging/media/imx/imx-media.h |  15 +++
 5 files changed, 141 insertions(+), 71 deletions(-)
 create mode 100644 drivers/staging/media/imx/imx-media-dev-common.c

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index 698a4210316e..a30b3033f9a3 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o
+imx-media-objs += imx-media-dev-common.o
 imx-media-common-objs := imx-media-utils.o imx-media-fim.o
 imx-media-ic-objs := imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o
 
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
new file mode 100644
index ..55fe94fb72f2
--- /dev/null
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL
+/*
+ * V4L2 Media Controller Driver for Freescale common i.MX5/6/7 SOC
+ *
+ * Copyright (c) 2018 Linaro Ltd
+ * Copyright (c) 2016 Mentor Graphics Inc.
+ */
+
+#include 
+#include 
+#include "imx-media.h"
+
+static const struct v4l2_async_notifier_operations imx_media_subdev_ops = {
+   .bound = imx_media_subdev_bound,
+   .complete = imx_media_probe_complete,
+};
+
+static const struct media_device_ops imx_media_md_ops = {
+   .link_notify = imx_media_link_notify,
+};
+
+struct imx_media_dev *imx_media_dev_init(struct device *dev)
+{
+   struct imx_media_dev *imxmd;
+   int ret;
+
+   imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL);
+   if (!imxmd)
+   return ERR_PTR(-ENOMEM);
+
+   dev_set_drvdata(dev, imxmd);
+
+   strlcpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model));
+   imxmd->md.ops = _media_md_ops;
+   imxmd->md.dev = dev;
+
+   mutex_init(>mutex);
+
+   imxmd->v4l2_dev.mdev = >md;
+   strlcpy(imxmd->v4l2_dev.name, "imx-media",
+   sizeof(imxmd->v4l2_dev.name));
+
+   media_device_init(>md);
+
+   ret = v4l2_device_register(dev, >v4l2_dev);
+   if (ret < 0) {
+   v4l2_err(>v4l2_dev,
+"Failed to register v4l2_device: %d\n", ret);
+   goto cleanup;
+   }
+
+   dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
+
+   INIT_LIST_HEAD(>vdev_list);
+
+   v4l2_async_notifier_init(>notifier);
+
+   return imxmd;
+
+cleanup:
+   media_device_cleanup(>md);
+
+   return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(imx_media_dev_init);
+
+int imx_media_dev_notifier_register(struct imx_media_dev *imxmd)
+{
+   int ret;
+
+   /* no subdevs? just bail */
+   if (list_empty(>notifier.asd_list)) {
+   v4l2_err(>v4l2_dev, "no subdevs\n");
+   return -ENODEV;
+   }
+
+   /* prepare the async subdev notifier and register it */
+   imxmd->notifier.ops = _media_subdev_ops;
+   ret = v4l2_async_notifier_register(>v4l2_dev,
+  >notifier);
+   if (ret) {
+   v4l2_err(>v4l2_dev,
+"v4l2_async_notifier_register failed with %d\n", ret);
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(imx_media_dev_notifier_register);
+
+void imx_media_dev_cleanup(struct imx_media_dev *imxmd)
+{
+   v4l2_device_unregister(>v4l2_dev);
+   media_device_cleanup(>md);
+}
+EXPORT_SYMBOL_GPL(imx_media_dev_cleanup);
+
+void imx_media_dev_notifier_unregister(struct imx_media_dev *imxmd)
+{
+   v4l2_async_notifier_cleanup(>notifier);
+}
+EXPORT_SYMBOL_GPL(imx_media_dev_notifier_unregister);
diff --git a/drivers/staging/media/imx/imx-media-dev.c 
b/drivers/staging/media/imx/imx-media-dev.c
index 4b344a4a3706..21f65af5c738 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -116,9 +116,9 @@ static int imx_media_get_ipu(struct imx_media_dev *imxmd,
 }
 
 /* async subdev bound notifier */
-static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
- struct v4l2_subdev *sd,
- struct v4l2_async_subdev *asd)
+int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
+  struct v4l2_subdev *sd,
+  struct v4l2_async_subdev *asd)
 {
struct imx_media_dev *imxmd = notifier2dev(notifier);

Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 21:23, Greg Kroah-Hartman wrote:
> On Thu, Nov 22, 2018 at 09:01:31PM +0800, Gao Xiang wrote:
>> Hi Greg,
>>
>> On 2018/11/22 20:00, Gao Xiang wrote:
>>> Hi Greg,
>>>
>>> On 2018/11/22 19:26, Greg Kroah-Hartman wrote:
 Don't make people rebuild your code with different options for
 debugging.  That will never work in the 'real world' when people start
 using the code.  You need to have things enabled for people all the
 time, which is why we have dynamic debugging in the kernel now, and not
 a zillion different "DRIVER_DEBUG" build options anymore.
>>> Actually, current erofs handle differently for beta users (in eng mode)
>>> and commercial users.
>>>
>>> CONFIG_EROFS_FS_DEBUG is enable for all beta users, after an observed
>>> expression is false, we could get the whole memorydump as early as possible.
>>> But for commercial users, there are no such observing points to promise
>>> the kernel stability and performance.
>>>
>>> It has helped us to find several bug, and I cannot find some alternative way
>>> to get the the first scene of the accident...
>>
>> I'm about to send v2 of this patchset... I need to get your opinion...
>>
>> I think for the current erofs development state, I tend to leave such a
>> developping switch because the code could be modified frequently,
>> many potential bugs could be avoid when this debugging mode is on and
>> it will be dropped after erofs becomes more stable...
> 
> You have two competing issues here.  You need to have some sort of debug
> build that allows you to get feedback from users, and you need to
> provide a solid, reliable system for those not wanting to debug
> anything.

Yes, you are right :)

> 
> If you use a kernel build option, then you can do what you are doing
> now, just that do not expect for any user that has problems with the
> filesystem, they will rebuild the code just to try to help debug it.
> That is going to require run-time debugging to be enabled as they will
> not usually have built their own kernel/module at all.

Yes, actually the current Android system have 2 modes -- eng and commerical 
build
for all versions.

A large number of beta users will receive eng build, and many buges were 
observed
from these users. That is the debugging benefit what Android system does now.

I do not expect real users to rebuild kernels for debugging, I think after the 
Android
use case, erofs has become solid enough. For commerical builds, it will have 
enough
error handing case found by Android users and developers.

> 
> For now, keep doing what you are doing, I just started to worry when I
> saw the initial BUG_ON() as we had just talked about these at the
> Maintainers summit a few weeks ago, and how we need to get rid of them
> from the kernel as they are a crutch that we need to solve.

Thanks for understanding...

Thanks,
Gao Xiang

> 
> thanks, and sorry for the noise.  Please resend this series again,
> 
> greg k-h
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 6/8] staging: rtl8188eu: add spaces around '>>' and '&'

2018-11-22 Thread Michael Straube
Add spaces around '>>' and '&' to follow kernel coding style.
Reported by checkpatch.

Signed-off-by: Michael Straube 
---
 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index 73d2d312e8ab..4821ce2fa762 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -173,7 +173,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct 
sk_buff *pskb)
pkt_copy = NULL;
 
if (transfer_len > 0 && pkt_cnt == 0)
-   pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
+   pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
 
} while ((transfer_len > 0) && (pkt_cnt > 0));
 
@@ -299,7 +299,7 @@ u8 usb_read8(struct adapter *adapter, u32 addr)
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
 
-   wvalue = (u16)(addr&0x);
+   wvalue = (u16)(addr & 0x);
len = 1;
 
usbctrl_vendorreq(adapter, request, wvalue, index, , len, 
requesttype);
@@ -319,11 +319,11 @@ u16 usb_read16(struct adapter *adapter, u32 addr)
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
-   wvalue = (u16)(addr&0x);
+   wvalue = (u16)(addr & 0x);
len = 2;
usbctrl_vendorreq(adapter, request, wvalue, index, , len, 
requesttype);
 
-   return (u16)(le32_to_cpu(data)&0x);
+   return (u16)(le32_to_cpu(data) & 0x);
 }
 
 u32 usb_read32(struct adapter *adapter, u32 addr)
@@ -339,7 +339,7 @@ u32 usb_read32(struct adapter *adapter, u32 addr)
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
 
-   wvalue = (u16)(addr&0x);
+   wvalue = (u16)(addr & 0x);
len = 4;
 
usbctrl_vendorreq(adapter, request, wvalue, index, , len, 
requesttype);
@@ -520,7 +520,7 @@ int usb_write8(struct adapter *adapter, u32 addr, u8 val)
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
-   wvalue = (u16)(addr&0x);
+   wvalue = (u16)(addr & 0x);
len = 1;
data = val;
return usbctrl_vendorreq(adapter, request, wvalue,
@@ -540,7 +540,7 @@ int usb_write16(struct adapter *adapter, u32 addr, u16 val)
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
 
-   wvalue = (u16)(addr&0x);
+   wvalue = (u16)(addr & 0x);
len = 2;
 
data = cpu_to_le32(val & 0x);
@@ -562,7 +562,7 @@ int usb_write32(struct adapter *adapter, u32 addr, u32 val)
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
 
-   wvalue = (u16)(addr&0x);
+   wvalue = (u16)(addr & 0x);
len = 4;
data = cpu_to_le32(val);
 
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 8/8] staging: rtl8188eu: remove variable from rtl8188eu_xmit_tasklet()

2018-11-22 Thread Michael Straube
The local variable ret is only used to test the return value of the
call to rtl8188eu_xmitframe_complete(). Use the function directly in
the if test and remove the variable ret.

Signed-off-by: Michael Straube 
---
 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index 9a732adbf1b1..7dc7028c1cd5 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -796,7 +796,6 @@ void rtl8188eu_recv_tasklet(void *priv)
 
 void rtl8188eu_xmit_tasklet(void *priv)
 {
-   int ret = false;
struct adapter *adapt = priv;
struct xmit_priv *pxmitpriv = >xmitpriv;
 
@@ -811,9 +810,7 @@ void rtl8188eu_xmit_tasklet(void *priv)
break;
}
 
-   ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv);
-
-   if (!ret)
+   if (!rtl8188eu_xmitframe_complete(adapt, pxmitpriv))
break;
}
 }
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 5/8] staging: rtl8188eu: remove unnecessary parentheses

2018-11-22 Thread Michael Straube
Remove unnecessary parentheses in usb_ops_linux.c.
Reported by checkpatch.

Signed-off-by: Michael Straube 
---
 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index 75b7d8c2cc50..73d2d312e8ab 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -25,7 +25,8 @@ static void interrupt_handler_8188eu(struct adapter *adapt, 
u16 pkt_len, u8 *pbu
 
/*  C2H Event */
if (pbuf[0] != 0)
-   memcpy(&(haldata->C2hArray[0]), 
&(pbuf[USB_INTR_CONTENT_C2H_OFFSET]), 16);
+   memcpy(>C2hArray[0],
+  [USB_INTR_CONTENT_C2H_OFFSET], 16);
 }
 
 static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 3/8] staging: rtl8188eu: remove braces from single if else statement

2018-11-22 Thread Michael Straube
Remove braces from single line if else statement.
Reported by checkpatch.

Signed-off-by: Michael Straube 
---
 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index d792301a5ac2..5a41766bba68 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -259,11 +259,10 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 
request, u16 value, u16 i
len, status, *(u32 *)pdata, vendorreq_times);
 
if (status < 0) {
-   if (status == (-ESHUTDOWN) || status == 
-ENODEV) {
+   if (status == (-ESHUTDOWN) || status == -ENODEV)
adapt->bSurpriseRemoved = true;
-   } else {
+   else

adapt->HalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
-   }
} else { /*  status != len && status >= 0 */
if (status > 0) {
if (requesttype == 0x01) {
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 4/8] staging: rtl8188eu: correct spelling mistake in a comment

2018-11-22 Thread Michael Straube
Correct spelling mistake in a comment reported by checkpatch.
checksumed -> checksummed

Signed-off-by: Michael Straube 
---
 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index 5a41766bba68..75b7d8c2cc50 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -273,7 +273,7 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 
request, u16 value, u16 i
}
}
 
-   /*  firmware download is checksumed, don't retry */
+   /*  firmware download is checksummed, don't retry */
if ((value >= FW_8188E_START_ADDRESS && value <= 
FW_8188E_END_ADDRESS) || status == len)
break;
}
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 7/8] staging: rtl8188eu: cleanup declarations in usb_ops_linux.c

2018-11-22 Thread Michael Straube
Replace tabs with spaces and/or remove spaces in declarations
to cleanup whitespace.

Signed-off-by: Michael Straube 
---
 .../staging/rtl8188eu/os_dep/usb_ops_linux.c  | 40 +--
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index 4821ce2fa762..9a732adbf1b1 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -31,18 +31,18 @@ static void interrupt_handler_8188eu(struct adapter *adapt, 
u16 pkt_len, u8 *pbu
 
 static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
 {
-   u8  *pbuf;
-   u8  shift_sz = 0;
-   u16 pkt_cnt;
-   u32 pkt_offset, skb_len, alloc_sz;
-   s32 transfer_len;
-   struct recv_stat*prxstat;
-   struct phy_stat *pphy_status = NULL;
+   u8 *pbuf;
+   u8 shift_sz = 0;
+   u16 pkt_cnt;
+   u32 pkt_offset, skb_len, alloc_sz;
+   s32 transfer_len;
+   struct recv_stat *prxstat;
+   struct phy_stat *pphy_status = NULL;
struct sk_buff *pkt_copy = NULL;
-   struct recv_frame   *precvframe = NULL;
-   struct rx_pkt_attrib*pattrib = NULL;
+   struct recv_frame *precvframe = NULL;
+   struct rx_pkt_attrib *pattrib = NULL;
struct hal_data_8188e *haldata = adapt->HalData;
-   struct recv_priv*precvpriv = >recvpriv;
+   struct recv_priv *precvpriv = >recvpriv;
struct __queue *pfree_recv_queue = >free_recv_queue;
 
transfer_len = (s32)pskb->len;
@@ -201,7 +201,7 @@ unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 
addr)
 
 static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 
index, void *pdata, u16 len, u8 requesttype)
 {
-   struct dvobj_priv  *dvobjpriv = adapter_to_dvobj(adapt);
+   struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
struct usb_device *udev = dvobjpriv->pusbdev;
unsigned int pipe;
int status = 0;
@@ -349,8 +349,8 @@ u32 usb_read32(struct adapter *adapter, u32 addr)
 
 static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
 {
-   struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
-   struct adapter  *adapt = (struct adapter *)precvbuf->adapter;
+   struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
+   struct adapter *adapt = (struct adapter *)precvbuf->adapter;
struct recv_priv *precvpriv = >recvpriv;
 
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s!!!\n", __func__));
@@ -426,9 +426,9 @@ static void usb_read_port_complete(struct urb *purb, struct 
pt_regs *regs)
 u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf)
 {
struct urb *purb = NULL;
-   struct dvobj_priv   *pdvobj = adapter_to_dvobj(adapter);
-   struct recv_priv*precvpriv = >recvpriv;
-   struct usb_device   *pusbd = pdvobj->pusbdev;
+   struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
+   struct recv_priv *precvpriv = >recvpriv;
+   struct usb_device *pusbd = pdvobj->pusbdev;
int err;
unsigned int pipe;
u32 ret = _SUCCESS;
@@ -573,8 +573,8 @@ int usb_write32(struct adapter *adapter, u32 addr, u32 val)
 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
 {
struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
-   struct adapter  *padapter = pxmitbuf->padapter;
-   struct xmit_priv*pxmitpriv = >xmitpriv;
+   struct adapter *padapter = pxmitbuf->padapter;
+   struct xmit_priv *pxmitpriv = >xmitpriv;
 
switch (pxmitbuf->flags) {
case VO_QUEUE_INX:
@@ -662,8 +662,8 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 
cnt, struct xmit_buf
int status;
u32 ret = _FAIL;
struct urb *purb = NULL;
-   struct dvobj_priv   *pdvobj = adapter_to_dvobj(padapter);
-   struct xmit_priv*pxmitpriv = >xmitpriv;
+   struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
+   struct xmit_priv *pxmitpriv = >xmitpriv;
struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data;
struct usb_device *pusbd = pdvobj->pusbdev;
 
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/8] staging: rtl8188eu: use __func__ in usb_ops_linux.c

2018-11-22 Thread Michael Straube
Use __func__ instead of hardcoded function names.
Reported by checkpatch.

Signed-off-by: Michael Straube 
---
 .../staging/rtl8188eu/os_dep/usb_ops_linux.c  | 84 ---
 1 file changed, 53 insertions(+), 31 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index d6a499692e96..f8d2b141a6c6 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -52,14 +52,16 @@ static int recvbuf2recvframe(struct adapter *adapt, struct 
sk_buff *pskb)
 
do {
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-("recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 
4:0x%08x, 8:0x%08x, C:0x%08x\n",
- prxstat->rxdw0, prxstat->rxdw1, prxstat->rxdw2, 
prxstat->rxdw4));
+("%s: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, 
C:0x%08x\n",
+ __func__, prxstat->rxdw0, prxstat->rxdw1,
+ prxstat->rxdw2, prxstat->rxdw4));
 
prxstat = (struct recv_stat *)pbuf;
 
precvframe = rtw_alloc_recvframe(pfree_recv_queue);
if (!precvframe) {
-   RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, 
("recvbuf2recvframe: precvframe==NULL\n"));
+   RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+("%s: precvframe==NULL\n", __func__));
DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX 
Drop!\n", __func__, __LINE__);
goto _exit_recvbuf2recvframe;
}
@@ -83,7 +85,8 @@ static int recvbuf2recvframe(struct adapter *adapt, struct 
sk_buff *pskb)
pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + 
pattrib->shift_sz + pattrib->pkt_len;
 
if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
-   RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, 
("recvbuf2recvframe: pkt_len<=0\n"));
+   RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+("%s: pkt_len<=0\n", __func__));
DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> 
transfer_len\n", __func__, __LINE__);
rtw_free_recvframe(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
@@ -121,7 +124,8 @@ static int recvbuf2recvframe(struct adapter *adapt, struct 
sk_buff *pskb)
memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + 
RXDESC_SIZE), skb_len);
skb_put(precvframe->pkt, skb_len);
} else {
-   DBG_88E("recvbuf2recvframe: alloc_skb fail , drop frag 
frame\n");
+   DBG_88E("%s: alloc_skb fail , drop frag frame\n",
+   __func__);
rtw_free_recvframe(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
@@ -143,7 +147,8 @@ static int recvbuf2recvframe(struct adapter *adapt, struct 
sk_buff *pskb)
update_recvframe_phyinfo_88e(precvframe, 
pphy_status);
if (rtw_recv_entry(precvframe) != _SUCCESS) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-   ("recvbuf2recvframe: 
rtw_recv_entry(precvframe) != _SUCCESS\n"));
+("%s: rtw_recv_entry(precvframe) != 
_SUCCESS\n",
+__func__));
}
} else if (pattrib->pkt_rpt_type == TX_REPORT1) {
/* CCX-TXRPT ack for xmit mgmt frames. */
@@ -206,7 +211,9 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 
request, u16 value, u16 i
int vendorreq_times = 0;
 
if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
-   RT_TRACE(_module_hci_ops_os_c_, _drv_err_, 
("usbctrl_vendorreq:(adapt->bSurpriseRemoved 
||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
+   RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+("%s:(adapt->bSurpriseRemoved 
||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
+ __func__));
status = -EPERM;
goto exit;
}
@@ -348,12 +355,13 @@ static void usb_read_port_complete(struct urb *purb, 
struct pt_regs *regs)
struct adapter  *adapt = (struct adapter *)precvbuf->adapter;
struct recv_priv *precvpriv = >recvpriv;
 
-   RT_TRACE(_module_hci_ops_os_c_, _drv_err_, 
("usb_read_port_complete!!!\n"));
+   RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s!!!\n", __func__));
 
if (adapt->bSurpriseRemoved || adapt->bDriverStopped || 
adapt->bReadPortCancel) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-  

[PATCH 2/8] staging: rtl8188eu: cleanup line ending with a '('

2018-11-22 Thread Michael Straube
Cleanup line ending with a '(' to follow kernel coding style.
Reported by checkpatch.

Signed-off-by: Michael Straube 
---
 drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c 
b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
index f8d2b141a6c6..d792301a5ac2 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -155,13 +155,11 @@ static int recvbuf2recvframe(struct adapter *adapt, 
struct sk_buff *pskb)
handle_txrpt_ccx_88e(adapt, precvframe->pkt->data);
rtw_free_recvframe(precvframe, pfree_recv_queue);
} else if (pattrib->pkt_rpt_type == TX_REPORT2) {
-   ODM_RA_TxRPT2Handle_8188E(
-   >odmpriv,
-   precvframe->pkt->data,
-   pattrib->pkt_len,
-   pattrib->MacIDValidEntry[0],
-   pattrib->MacIDValidEntry[1]
-   );
+   ODM_RA_TxRPT2Handle_8188E(>odmpriv,
+ precvframe->pkt->data,
+ pattrib->pkt_len,
+ pattrib->MacIDValidEntry[0],
+ pattrib->MacIDValidEntry[1]);
rtw_free_recvframe(precvframe, pfree_recv_queue);
} else if (pattrib->pkt_rpt_type == HIS_REPORT) {
interrupt_handler_8188eu(adapt, pattrib->pkt_len, 
precvframe->pkt->data);
-- 
2.19.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 09:01:31PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 20:00, Gao Xiang wrote:
> > Hi Greg,
> > 
> > On 2018/11/22 19:26, Greg Kroah-Hartman wrote:
> >> Don't make people rebuild your code with different options for
> >> debugging.  That will never work in the 'real world' when people start
> >> using the code.  You need to have things enabled for people all the
> >> time, which is why we have dynamic debugging in the kernel now, and not
> >> a zillion different "DRIVER_DEBUG" build options anymore.
> > Actually, current erofs handle differently for beta users (in eng mode)
> > and commercial users.
> > 
> > CONFIG_EROFS_FS_DEBUG is enable for all beta users, after an observed
> > expression is false, we could get the whole memorydump as early as possible.
> > But for commercial users, there are no such observing points to promise
> > the kernel stability and performance.
> > 
> > It has helped us to find several bug, and I cannot find some alternative way
> > to get the the first scene of the accident...
> 
> I'm about to send v2 of this patchset... I need to get your opinion...
> 
> I think for the current erofs development state, I tend to leave such a
> developping switch because the code could be modified frequently,
> many potential bugs could be avoid when this debugging mode is on and
> it will be dropped after erofs becomes more stable...

You have two competing issues here.  You need to have some sort of debug
build that allows you to get feedback from users, and you need to
provide a solid, reliable system for those not wanting to debug
anything.

If you use a kernel build option, then you can do what you are doing
now, just that do not expect for any user that has problems with the
filesystem, they will rebuild the code just to try to help debug it.
That is going to require run-time debugging to be enabled as they will
not usually have built their own kernel/module at all.

For now, keep doing what you are doing, I just started to worry when I
saw the initial BUG_ON() as we had just talked about these at the
Maintainers summit a few weeks ago, and how we need to get rid of them
from the kernel as they are a crutch that we need to solve.

thanks, and sorry for the noise.  Please resend this series again,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 08:41:15PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 20:26, Greg Kroah-Hartman wrote:
> > Ugh, every page?  Ok, nevermind, I take back my objections.  You all are
> > crazy and need to do crazy things like this :)
> 
> ...Do you have some idea about this? ... I think it is fairly normal... :(
> 
> We have a large number of managed workgroups, the current use case is the 4k 
> compressed size,
> each compressed page has a workgroup, but erofs also has reclaim paths to 
> free them for low memory cases.
> 
> But since the structure (z_erofs_vle_workgroup, erofs_workgroup) is critical,
> I need to make it as small as possible.

I do not know "real" filesystems (i.e. ones that put stuff on disks),
only virtual ones (like sysfs/kernfs), so I do not know what to suggest
here, sorry.  I thought this was a much higner-level structure, if this
is per-compressed-page, then you are more than welcome to optimize for
this.  Good luck with your "fake" spinlocks though :)

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 20:00, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 19:26, Greg Kroah-Hartman wrote:
>> Don't make people rebuild your code with different options for
>> debugging.  That will never work in the 'real world' when people start
>> using the code.  You need to have things enabled for people all the
>> time, which is why we have dynamic debugging in the kernel now, and not
>> a zillion different "DRIVER_DEBUG" build options anymore.
> Actually, current erofs handle differently for beta users (in eng mode)
> and commercial users.
> 
> CONFIG_EROFS_FS_DEBUG is enable for all beta users, after an observed
> expression is false, we could get the whole memorydump as early as possible.
> But for commercial users, there are no such observing points to promise
> the kernel stability and performance.
> 
> It has helped us to find several bug, and I cannot find some alternative way
> to get the the first scene of the accident...

I'm about to send v2 of this patchset... I need to get your opinion...

I think for the current erofs development state, I tend to leave such a
developping switch because the code could be modified frequently,
many potential bugs could be avoid when this debugging mode is on and
it will be dropped after erofs becomes more stable...

Thanks,
Gao Xiang

> 
> Thanks,
> Gao Xiang
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] staging: iio: ad5933: replaced kfifo by triggered_buffer

2018-11-22 Thread Marcelo Schmitt
Previously, there was an implicit creation of a kfifo which was replaced
by a call to triggered_buffer_setup, which is already implemented in iio
infrastructure.

Signed-off-by: Marcelo Schmitt 
---
 .../staging/iio/impedance-analyzer/Kconfig|  2 +-
 .../staging/iio/impedance-analyzer/ad5933.c   | 25 ---
 2 files changed, 6 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/iio/impedance-analyzer/Kconfig 
b/drivers/staging/iio/impedance-analyzer/Kconfig
index dd97b6bb3fd0..d0af5aa55dc0 100644
--- a/drivers/staging/iio/impedance-analyzer/Kconfig
+++ b/drivers/staging/iio/impedance-analyzer/Kconfig
@@ -7,7 +7,7 @@ config AD5933
tristate "Analog Devices AD5933, AD5934 driver"
depends on I2C
select IIO_BUFFER
-   select IIO_KFIFO_BUF
+   select IIO_TRIGGERED_BUFFER
help
  Say yes here to build support for Analog Devices Impedance Converter,
  Network Analyzer, AD5933/4, provides direct access via sysfs.
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c 
b/drivers/staging/iio/impedance-analyzer/ad5933.c
index f9bcb8310e21..edb8b540bbf1 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -20,7 +20,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 /* AD5933/AD5934 Registers */
 #define AD5933_REG_CONTROL_HB  0x80/* R/W, 1 byte */
@@ -615,22 +615,6 @@ static const struct iio_buffer_setup_ops 
ad5933_ring_setup_ops = {
.postdisable = ad5933_ring_postdisable,
 };
 
-static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-   struct iio_buffer *buffer;
-
-   buffer = iio_kfifo_allocate();
-   if (!buffer)
-   return -ENOMEM;
-
-   iio_device_attach_buffer(indio_dev, buffer);
-
-   /* Ring buffer functions - here trigger setup related */
-   indio_dev->setup_ops = _ring_setup_ops;
-
-   return 0;
-}
-
 static void ad5933_work(struct work_struct *work)
 {
struct ad5933_state *st = container_of(work,
@@ -744,7 +728,8 @@ static int ad5933_probe(struct i2c_client *client,
indio_dev->channels = ad5933_channels;
indio_dev->num_channels = ARRAY_SIZE(ad5933_channels);
 
-   ret = ad5933_register_ring_funcs_and_init(indio_dev);
+   ret = iio_triggered_buffer_setup(indio_dev, NULL, NULL,
+_ring_setup_ops);
if (ret)
goto error_disable_reg;
 
@@ -759,7 +744,7 @@ static int ad5933_probe(struct i2c_client *client,
return 0;
 
 error_unreg_ring:
-   iio_kfifo_free(indio_dev->buffer);
+   iio_triggered_buffer_cleanup(indio_dev);
 error_disable_reg:
regulator_disable(st->reg);
 
@@ -772,7 +757,7 @@ static int ad5933_remove(struct i2c_client *client)
struct ad5933_state *st = iio_priv(indio_dev);
 
iio_device_unregister(indio_dev);
-   iio_kfifo_free(indio_dev->buffer);
+   iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(st->reg);
 
return 0;
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 20:26, Greg Kroah-Hartman wrote:
> Ugh, every page?  Ok, nevermind, I take back my objections.  You all are
> crazy and need to do crazy things like this :)

...Do you have some idea about this? ... I think it is fairly normal... :(

We have a large number of managed workgroups, the current use case is the 4k 
compressed size,
each compressed page has a workgroup, but erofs also has reclaim paths to free 
them for low memory cases.

But since the structure (z_erofs_vle_workgroup, erofs_workgroup) is critical,
I need to make it as small as possible.

Thanks,
Gao Xiang
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 07:43:50PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 19:06, Greg Kroah-Hartman wrote:
> > On Thu, Nov 22, 2018 at 06:42:52PM +0800, Gao Xiang wrote:
> >> Hi Greg,
> >>
> >> On 2018/11/22 18:17, Greg Kroah-Hartman wrote:
> >>> Any specific reason why you are not using the refcount.h api instead of
> >>> "doing it yourself" with atomic_inc/dec()?
> >>>
> >>> I'm not rejecting this, just curious.
> >> As I explained in the previous email,
> >> Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, 
> >> unfreeze}'
> >>
> >> we need such a function when the value is >= 0, it plays as a refcount,
> >> but when the refcount == EROFS_LOCKED_MAGIC (<0, but not 0 as refcount.h),
> >> and actually there is no need to introduce a seperate spinlock_t because
> >> we don't actually care about its performance (rarely locked). and
> >> the corresponding struct is too large for now, we need to decrease its 
> >> size.
> > Why do you need to decrease the size?  How many of these structures are
> > created?
> 
> As I said in the previous email, every compressed page will have a managed 
> structure
> called erofs_workgroup, and it is heavily allocated like page/inode/dentry in 
> the erofs.

Ugh, every page?  Ok, nevermind, I take back my objections.  You all are
crazy and need to do crazy things like this :)

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 19:26, Greg Kroah-Hartman wrote:
> Don't make people rebuild your code with different options for
> debugging.  That will never work in the 'real world' when people start
> using the code.  You need to have things enabled for people all the
> time, which is why we have dynamic debugging in the kernel now, and not
> a zillion different "DRIVER_DEBUG" build options anymore.

Actually, current erofs handle differently for beta users (in eng mode)
and commercial users.

CONFIG_EROFS_FS_DEBUG is enable for all beta users, after an observed
expression is false, we could get the whole memorydump as early as possible.
But for commercial users, there are no such observing points to promise
the kernel stability and performance.

It has helped us to find several bug, and I cannot find some alternative way
to get the the first scene of the accident...

Thanks,
Gao Xiang
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 19:06, Greg Kroah-Hartman wrote:
> On Thu, Nov 22, 2018 at 06:42:52PM +0800, Gao Xiang wrote:
>> Hi Greg,
>>
>> On 2018/11/22 18:17, Greg Kroah-Hartman wrote:
>>> Any specific reason why you are not using the refcount.h api instead of
>>> "doing it yourself" with atomic_inc/dec()?
>>>
>>> I'm not rejecting this, just curious.
>> As I explained in the previous email,
>> Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, 
>> unfreeze}'
>>
>> we need such a function when the value is >= 0, it plays as a refcount,
>> but when the refcount == EROFS_LOCKED_MAGIC (<0, but not 0 as refcount.h),
>> and actually there is no need to introduce a seperate spinlock_t because
>> we don't actually care about its performance (rarely locked). and
>> the corresponding struct is too large for now, we need to decrease its size.
> Why do you need to decrease the size?  How many of these structures are
> created?

As I said in the previous email, every compressed page will have a managed 
structure
called erofs_workgroup, and it is heavily allocated like page/inode/dentry in 
the erofs.

> 
> And you will care about the performance when a lock is being held, as is
> evident by your logic to try to fix those issues in this patch series.
> Using a "real" lock will solve all of that and keep you from having to
> implement it all "by hand".

The function is much like lockref (aligned_u64 lock_count;) with the exception 
as my previous email
explained.

Thanks,
Gao Xiang

> 
> thanks,
> 
> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 19:26, Greg Kroah-Hartman wrote:
> On Thu, Nov 22, 2018 at 07:11:08PM +0800, Gao Xiang wrote:
>> Hi Greg,
>>
>> On 2018/11/22 19:05, Greg Kroah-Hartman wrote:
>>> On Thu, Nov 22, 2018 at 06:34:10PM +0800, Gao Xiang wrote:
 Hi Greg,

 On 2018/11/22 18:23, Greg Kroah-Hartman wrote:
>> +
>> +DBG_BUGON(work->nr_pages);
>> +DBG_BUGON(work->vcnt);
> How can these ever be triggered?  I understand the need for debugging
> code when you are writing code, but at this point it shouldn't be needed
> anymore, right?

 I need to avoid some fields is not 0 when the new workgroup is created 
 (because
 work->nr_pages and work->vcnt == 0 usually after the previous workgroup is 
 freed).
 But that is not obvious, it is promised by the current logic.
>>>
>>> Then delete these lines if they can never happen :)
>>
>> I don't know how to observe such a race in our beta test and community users.
> 
>   /*
>* Let developers know something went really wrong with their
>* initialization code
>*/
>   if (!work->nr_pages) {
>   pr_err("nr_pages == NULL!");
>   WARN_ON(1);
>   }
>   if (!work->vcnt) {
>   pr_err("vcnt == NULL!");
>   WARN_ON(1);
>   }
> 
> or something like that.
> 
> Don't make people rebuild your code with different options for
> debugging.  That will never work in the 'real world' when people start
> using the code.  You need to have things enabled for people all the
> time, which is why we have dynamic debugging in the kernel now, and not
> a zillion different "DRIVER_DEBUG" build options anymore.
> 
>> Because if the kernel is crashed, we could collect the whole kernel dump to 
>> observe the memory
>> and all registers, if we only have some warning, it will be not easy to get 
>> the state as early as possible.
> 
> When the kernel crashes, geting a dump is hard on almost all hardware.
> It is only rare systems that you can get a kernel dump.

This piece of code is already used in our hisilicon beta test, all memorydump,
registers, stack can be collected.

Apart from that, I observed many f2fs bugs are observed in this way and
many erofs bugs are collected in that way...sigh...

Thanks,
Gao Xiang


> 
> thanks,
> 
> greg k-h
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 07:11:08PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 19:05, Greg Kroah-Hartman wrote:
> > On Thu, Nov 22, 2018 at 06:34:10PM +0800, Gao Xiang wrote:
> >> Hi Greg,
> >>
> >> On 2018/11/22 18:23, Greg Kroah-Hartman wrote:
>  +
>  +DBG_BUGON(work->nr_pages);
>  +DBG_BUGON(work->vcnt);
> >>> How can these ever be triggered?  I understand the need for debugging
> >>> code when you are writing code, but at this point it shouldn't be needed
> >>> anymore, right?
> >>
> >> I need to avoid some fields is not 0 when the new workgroup is created 
> >> (because
> >> work->nr_pages and work->vcnt == 0 usually after the previous workgroup is 
> >> freed).
> >> But that is not obvious, it is promised by the current logic.
> > 
> > Then delete these lines if they can never happen :)
> 
> I don't know how to observe such a race in our beta test and community users.

/*
 * Let developers know something went really wrong with their
 * initialization code
 */
if (!work->nr_pages) {
pr_err("nr_pages == NULL!");
WARN_ON(1);
}
if (!work->vcnt) {
pr_err("vcnt == NULL!");
WARN_ON(1);
}

or something like that.

Don't make people rebuild your code with different options for
debugging.  That will never work in the 'real world' when people start
using the code.  You need to have things enabled for people all the
time, which is why we have dynamic debugging in the kernel now, and not
a zillion different "DRIVER_DEBUG" build options anymore.

> Because if the kernel is crashed, we could collect the whole kernel dump to 
> observe the memory
> and all registers, if we only have some warning, it will be not easy to get 
> the state as early as possible.

When the kernel crashes, geting a dump is hard on almost all hardware.
It is only rare systems that you can get a kernel dump.

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 19:05, Greg Kroah-Hartman wrote:
> As I said in another email, doing two things with one variable is odd as
> those are two different types of functions.

I think lockref_put_or_lock do the similar thing, it is heavily used in 
dcache.c, but
1) 0 is special for us, we need lock it on a < 0 value rather than 0.
2) spinlock_t is too large for us because every compressed page will have the 
structure,
   but the locking rarely happens.

Thanks,
Gao Xiang

> 
> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH] staging: iio: ad7780: Add gain & filter gpio support

2018-11-22 Thread Popa, Stefan Serban
On Mi, 2018-11-21 at 16:04 -0200, Giuliano Belinassi wrote:
> Previously, the AD7780 driver only supported gpio for the 'powerdown'
> pin. This commit adds suppport for the 'gain' and 'filter' pin.
Hey,

Comments inline.
> 
> Signed-off-by: Giuliano Belinassi 
> ---
>  drivers/staging/iio/adc/ad7780.c   | 61 --
>  include/linux/iio/adc/ad_sigma_delta.h |  5 +++
>  2 files changed, 62 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/staging/iio/adc/ad7780.c
> b/drivers/staging/iio/adc/ad7780.c
> index c4a85789c2db..69794f06dbcd 100644
> --- a/drivers/staging/iio/adc/ad7780.c
> +++ b/drivers/staging/iio/adc/ad7780.c
> @@ -39,6 +39,9 @@
>  #define AD7170_PATTERN   (AD7780_PAT0 | AD7170_PAT2)
>  #define AD7170_PATTERN_MASK  (AD7780_PAT0 | AD7780_PAT1 |
> AD7170_PAT2)
>  
> +#define AD7780_GAIN_GPIO 0
> +#define AD7780_FILTER_GPIO   1
> +
>  struct ad7780_chip_info {
>   struct iio_chan_specchannel;
>   unsigned intpattern_mask;
> @@ -50,6 +53,8 @@ struct ad7780_state {
>   const struct ad7780_chip_info   *chip_info;
>   struct regulator*reg;
>   struct gpio_desc*powerdown_gpio;
> + struct gpio_desc*gain_gpio;
> + struct gpio_desc*filter_gpio;
>   unsigned intgain;
>  
>   struct ad_sigma_delta sd;
> @@ -115,18 +120,51 @@ static int ad7780_read_raw(struct iio_dev
> *indio_dev,
>   return -EINVAL;
>  }
>  
> +static int ad7780_write_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int val,
> + int val2,
> + long m)
> +{
> + struct ad7780_state *st = iio_priv(indio_dev);
> +
> + if (m != IIO_CHAN_INFO_RAW)
> + return -EINVAL;
> +
> + if (st->chip_info->is_ad778x) {
> + switch(val) {
> + case AD7780_GAIN_GPIO:

I think that instead of setting the gain directly, we should use
the IIO_CHAN_INFO_SCALE attribute. At page 12 of the ad7780 datasheet there
is a formula from which the output code can be calculated:
Code = 2^(N − 1)
× [(AIN × Gain /VREF) + 1]. So, by setting the scale from user space, the
driver can calculate the correct gain by using the formula above. Also, it
would be useful to introduce scale available.
Furthermore, there is a new
ad7124 adc driver which does this exact thing. Take a look here: https://gi
thub.com/analogdevicesinc/linux/blob/master/drivers/iio/adc/ad7124.c#L337.

> + gpiod_set_value(st->gain_gpio, val2);
> + break;
> + case AD7780_FILTER_GPIO:

The attribute that should be used to configure the filter gpio is
IIO_CHAN_INFO_SAMP_FREQ. So, we should have 10 Hz and 16.7 Hz available
sampling frequencies. If from user space the 10 Hz sampling freq is
requested, then we set the FILTER pin high, while for 16.7 Hz the FILTER
pin will be low.

> + gpiod_set_value(st->filter_gpio, val2);
> + break;
> + default:
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
>  static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
>    unsigned int raw_sample)
>  {
>   struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
>   const struct ad7780_chip_info *chip_info = st->chip_info;
> + int val;
>  
>   if ((raw_sample & AD7780_ERR) ||
>   ((raw_sample & chip_info->pattern_mask) != chip_info-
> >pattern))
>   return -EIO;
>  
>   if (chip_info->is_ad778x) {
> - if (raw_sample & AD7780_GAIN)
> + val = raw_sample & AD7780_GAIN;
> +
> + if (val != gpiod_get_value(st->gain_gpio))
> + return -EIO;
> +
> + if (val)
>   st->gain = 1;
>   else
>   st->gain = 128;
> @@ -141,18 +179,20 @@ static const struct ad_sigma_delta_info
> ad7780_sigma_delta_info = {
>   .has_registers = false,
>  };
>  
> -#define AD7780_CHANNEL(bits, wordsize) \
> +#define AD7170_CHANNEL(bits, wordsize) \
>   AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, wordsize - bits)
> +#define AD7780_CHANNEL(bits, wordsize) \
> + AD_SD_CHANNEL_GAIN_FILTER(1, 0, 0, bits, 32, wordsize - bits)
>  
>  static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
>   [ID_AD7170] = {
> - .channel = AD7780_CHANNEL(12, 24),
> + .channel = AD7170_CHANNEL(12, 24),
>   .pattern = AD7170_PATTERN,
>   .pattern_mask = AD7170_PATTERN_MASK,
>   .is_ad778x = false,
>   },
>   [ID_AD7171] = {
> - .channel = AD7780_CHANNEL(16, 24),
> + .channel = AD7170_CHANNEL(16, 24),
>   .pattern = AD7170_PATTERN,
>   .pattern_mask = AD7170_PATTERN_MASK,
>    

Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 19:05, Greg Kroah-Hartman wrote:
> On Thu, Nov 22, 2018 at 06:34:10PM +0800, Gao Xiang wrote:
>> Hi Greg,
>>
>> On 2018/11/22 18:23, Greg Kroah-Hartman wrote:
 +
 +  DBG_BUGON(work->nr_pages);
 +  DBG_BUGON(work->vcnt);
>>> How can these ever be triggered?  I understand the need for debugging
>>> code when you are writing code, but at this point it shouldn't be needed
>>> anymore, right?
>>
>> I need to avoid some fields is not 0 when the new workgroup is created 
>> (because
>> work->nr_pages and work->vcnt == 0 usually after the previous workgroup is 
>> freed).
>> But that is not obvious, it is promised by the current logic.
> 
> Then delete these lines if they can never happen :)

I don't know how to observe such a race in our beta test and community users.

Because if the kernel is crashed, we could collect the whole kernel dump to 
observe the memory
and all registers, if we only have some warning, it will be not easy to get the 
state as early as possible.

Thank,
Gao Xiang

> 
>> In order to not introduce such a issue in the future, or there are some 
>> potential
>> race (work->nr_pages and work->vcnt != 0 when the previous workgroup == 0), 
>> it need
>> to be noticed to developpers as early as possible.
> 
> Then make it a real call, do not wrap it in odd macros that do not
> really explain why it is "debugging only".  Your code is "real" now,
> make the logic real for all developers and users.
> 
> thanks,
> 
> greg k-h
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 06:42:52PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 18:17, Greg Kroah-Hartman wrote:
> > Any specific reason why you are not using the refcount.h api instead of
> > "doing it yourself" with atomic_inc/dec()?
> > 
> > I'm not rejecting this, just curious.
> 
> As I explained in the previous email,
> Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, 
> unfreeze}'
> 
> we need such a function when the value is >= 0, it plays as a refcount,
> but when the refcount == EROFS_LOCKED_MAGIC (<0, but not 0 as refcount.h),
> and actually there is no need to introduce a seperate spinlock_t because
> we don't actually care about its performance (rarely locked). and
> the corresponding struct is too large for now, we need to decrease its size.

Why do you need to decrease the size?  How many of these structures are
created?

And you will care about the performance when a lock is being held, as is
evident by your logic to try to fix those issues in this patch series.
Using a "real" lock will solve all of that and keep you from having to
implement it all "by hand".

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 06:29:34PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 18:21, Greg Kroah-Hartman wrote:
> > On Tue, Nov 20, 2018 at 10:34:19PM +0800, Gao Xiang wrote:
> >> There are two minor issues in the current freeze interface:
> >>
> >>1) Freeze interfaces have not related with CONFIG_DEBUG_SPINLOCK,
> >>   therefore fix the incorrect conditions;
> >>
> >>2) For SMP platforms, it should also disable preemption before
> >>   doing atomic_cmpxchg in case that some high priority tasks
> >>   preempt between atomic_cmpxchg and disable_preempt, then spin
> >>   on the locked refcount later.
> > 
> > spinning on a refcount implies that you are trying to do your own type
> > of locking.  Why not use the in-kernel locking api instead?  It will
> > always do better than trying to do your own logic as the developers
> > there know locking across all types of cpus better than filesystem
> > developers :)
> 
> It is because refcount also plays a role as a spinlock on a specific value
> (== EROFS_LOCKED_MAGIC), no need to introduce such a value since the spin
> window is small.

As I said in another email, doing two things with one variable is odd as
those are two different types of functions.

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 06:34:10PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 18:23, Greg Kroah-Hartman wrote:
> >> +
> >> +  DBG_BUGON(work->nr_pages);
> >> +  DBG_BUGON(work->vcnt);
> > How can these ever be triggered?  I understand the need for debugging
> > code when you are writing code, but at this point it shouldn't be needed
> > anymore, right?
> 
> I need to avoid some fields is not 0 when the new workgroup is created 
> (because
> work->nr_pages and work->vcnt == 0 usually after the previous workgroup is 
> freed).
> But that is not obvious, it is promised by the current logic.

Then delete these lines if they can never happen :)

> In order to not introduce such a issue in the future, or there are some 
> potential
> race (work->nr_pages and work->vcnt != 0 when the previous workgroup == 0), 
> it need
> to be noticed to developpers as early as possible.

Then make it a real call, do not wrap it in odd macros that do not
really explain why it is "debugging only".  Your code is "real" now,
make the logic real for all developers and users.

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 06:29:34PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 18:21, Greg Kroah-Hartman wrote:
> > On Tue, Nov 20, 2018 at 10:34:19PM +0800, Gao Xiang wrote:
> >> There are two minor issues in the current freeze interface:
> >>
> >>1) Freeze interfaces have not related with CONFIG_DEBUG_SPINLOCK,
> >>   therefore fix the incorrect conditions;
> >>
> >>2) For SMP platforms, it should also disable preemption before
> >>   doing atomic_cmpxchg in case that some high priority tasks
> >>   preempt between atomic_cmpxchg and disable_preempt, then spin
> >>   on the locked refcount later.
> > 
> > spinning on a refcount implies that you are trying to do your own type
> > of locking.  Why not use the in-kernel locking api instead?  It will
> > always do better than trying to do your own logic as the developers
> > there know locking across all types of cpus better than filesystem
> > developers :)
> 
> It is because refcount also plays a role as a spinlock on a specific value
> (== EROFS_LOCKED_MAGIC), no need to introduce such a value since the spin
> window is small.

Do not try to overload a reference count as a spinlock, you will run
into problems and in the end have to implement everything that the core
locking code has done.

Your use of this is highly suspect, what happens when you use a "real"
spinlock and a "real" reference count instead?  Those are two different
things from a logical point of view and you are mixing them together
which is odd.

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 01/10] staging: erofs: fix `trace_erofs_readpage' position

2018-11-22 Thread Greg Kroah-Hartman
On Thu, Nov 22, 2018 at 06:49:53PM +0800, Gao Xiang wrote:
> Hi Greg,
> 
> On 2018/11/22 18:19, Greg Kroah-Hartman wrote:
> > On Tue, Nov 20, 2018 at 10:34:16PM +0800, Gao Xiang wrote:
> >> `trace_erofs_readpage' should be placed in .readpage()
> >> rather than in the internal `z_erofs_do_read_page'.
> > Why?  What happens with the code today?
> trace_erofs_readpage is used to trace .readpage() interface (it represents 
> sync read)
> hook rather than its internal implementation z_erofs_do_read_page (which both 
> .readpage()
> and .readpages() uses it). Chen Gong places the tracepoint to a wrong place 
> by mistake.
> And we found it by our internal test using this tracepoint.

Ok, you should put this in the changelog text when you redo this series.

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 05/10] staging: erofs: add a full barrier in erofs_workgroup_unfreeze

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 18:22, Greg Kroah-Hartman wrote:
> Please document this memory barrier.  It does not make much sense to
> me...

Because we need to make the other observers noticing the latest values modified
in this locking period before unfreezing the whole workgroup, one way is to use
a memory barrier and the other way is to use ACQUIRE and RELEASE. we selected
the first one.

Hmmm...ok, I will add a simple message to explain this, but I think that is
plain enough for a lock...

Thanks,
Gao Xiang

> 
> thanks,
> 
> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 01/10] staging: erofs: fix `trace_erofs_readpage' position

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 18:19, Greg Kroah-Hartman wrote:
> On Tue, Nov 20, 2018 at 10:34:16PM +0800, Gao Xiang wrote:
>> `trace_erofs_readpage' should be placed in .readpage()
>> rather than in the internal `z_erofs_do_read_page'.
> Why?  What happens with the code today?
trace_erofs_readpage is used to trace .readpage() interface (it represents sync 
read)
hook rather than its internal implementation z_erofs_do_read_page (which both 
.readpage()
and .readpages() uses it). Chen Gong places the tracepoint to a wrong place by 
mistake.
And we found it by our internal test using this tracepoint.

> 
>> Fixes: 284db12cfda3 ("staging: erofs: add trace points for reading zipped 
>> data")
> Should this get into 4.20-final?
I think so, which is not very important but I think it should be fixed...

Thanks,
Gao Xiang

> 
> thanks,
> 
> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] staging: vboxvideo: Rename uint32_t type to u32

2018-11-22 Thread Ricardo Reis Marques Silva
Issue found by checkpatch.

CHECK: Prefer kernel type 'u32' over 'uint32_t'
+static const uint32_t vbox_cursor_plane_formats[] = {

CHECK: Prefer kernel type 'u32' over 'uint32_t'
+static const uint32_t vbox_primary_plane_formats[] = {

CHECK: Prefer kernel type 'u32' over 'uint32_t'
+   const uint32_t *formats;

Signed-off-by: Ricardo Reis Marques Silva 
---
 drivers/staging/vboxvideo/vbox_mode.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/vboxvideo/vbox_mode.c 
b/drivers/staging/vboxvideo/vbox_mode.c
index 06e921844b1e..c43bec4628ae 100644
--- a/drivers/staging/vboxvideo/vbox_mode.c
+++ b/drivers/staging/vboxvideo/vbox_mode.c
@@ -479,7 +479,7 @@ static void vbox_cursor_cleanup_fb(struct drm_plane *plane,
vbox_bo_unpin(bo);
 }
 
-static const uint32_t vbox_cursor_plane_formats[] = {
+static const u32 vbox_cursor_plane_formats[] = {
DRM_FORMAT_ARGB,
 };
 
@@ -500,7 +500,7 @@ static const struct drm_plane_funcs vbox_cursor_plane_funcs 
= {
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
 
-static const uint32_t vbox_primary_plane_formats[] = {
+static const u32 vbox_primary_plane_formats[] = {
DRM_FORMAT_XRGB,
DRM_FORMAT_ARGB,
 };
@@ -529,7 +529,7 @@ static struct drm_plane *vbox_create_plane(struct 
vbox_private *vbox,
const struct drm_plane_helper_funcs *helper_funcs = NULL;
const struct drm_plane_funcs *funcs;
struct drm_plane *plane;
-   const uint32_t *formats;
+   const u32 *formats;
int num_formats;
int err;
 
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 18:17, Greg Kroah-Hartman wrote:
> Any specific reason why you are not using the refcount.h api instead of
> "doing it yourself" with atomic_inc/dec()?
> 
> I'm not rejecting this, just curious.

As I explained in the previous email,
Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, 
unfreeze}'

we need such a function when the value is >= 0, it plays as a refcount,
but when the refcount == EROFS_LOCKED_MAGIC (<0, but not 0 as refcount.h),
and actually there is no need to introduce a seperate spinlock_t because
we don't actually care about its performance (rarely locked). and
the corresponding struct is too large for now, we need to decrease its size.

Thanks,
Gao Xiang

> 
> thanks,
> 
> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 08/10] staging: erofs: locked before registering for all new workgroups

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 18:24, Greg Kroah-Hartman wrote:
>> +/* lock all primary followed works before visible to others */
>> +if (unlikely(!mutex_trylock(>lock)))
>> +/* for a new workgroup, try_lock *never* fails */
>> +DBG_BUGON(1);
> Again, drop this, if it never fails, then there's no need for this.  If
> it can fail, then properly handle it.
> 
> And trylock can fail, so this needs to be fixed.

OK, I will drop this.

Thanks,
Gao Xiang

> 
> thanks,
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 18:23, Greg Kroah-Hartman wrote:
>> +
>> +DBG_BUGON(work->nr_pages);
>> +DBG_BUGON(work->vcnt);
> How can these ever be triggered?  I understand the need for debugging
> code when you are writing code, but at this point it shouldn't be needed
> anymore, right?

I need to avoid some fields is not 0 when the new workgroup is created (because
work->nr_pages and work->vcnt == 0 usually after the previous workgroup is 
freed).
But that is not obvious, it is promised by the current logic.

In order to not introduce such a issue in the future, or there are some 
potential
race (work->nr_pages and work->vcnt != 0 when the previous workgroup == 0), it 
need
to be noticed to developpers as early as possible.

Thanks,
Gao Xiang

> 
> thanks,
> 
> greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'

2018-11-22 Thread Gao Xiang
Hi Greg,

On 2018/11/22 18:21, Greg Kroah-Hartman wrote:
> On Tue, Nov 20, 2018 at 10:34:19PM +0800, Gao Xiang wrote:
>> There are two minor issues in the current freeze interface:
>>
>>1) Freeze interfaces have not related with CONFIG_DEBUG_SPINLOCK,
>>   therefore fix the incorrect conditions;
>>
>>2) For SMP platforms, it should also disable preemption before
>>   doing atomic_cmpxchg in case that some high priority tasks
>>   preempt between atomic_cmpxchg and disable_preempt, then spin
>>   on the locked refcount later.
> 
> spinning on a refcount implies that you are trying to do your own type
> of locking.  Why not use the in-kernel locking api instead?  It will
> always do better than trying to do your own logic as the developers
> there know locking across all types of cpus better than filesystem
> developers :)

It is because refcount also plays a role as a spinlock on a specific value
(== EROFS_LOCKED_MAGIC), no need to introduce such a value since the spin
window is small.

Thanks,
Gao Xiang

> 
> thanks,
> 
> greg k-h
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 08/10] staging: erofs: locked before registering for all new workgroups

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:23PM +0800, Gao Xiang wrote:
> Let's make sure that the one registering a workgroup will also
> take the primary work lock at first for two reasons:
>   1) There's no need to introduce such a race window (and consequently
>  overhead) between registering and locking, other tasks could break
>  in by chance, and the race seems unnecessary (no benefit at all);
> 
>   2) It's better to take the primary work when a workgroup
>  is registered to apply the cache managed policy, for example,
>  if some other tasks break in, it could turn into the in-place
>  decompression rather than use as the cached decompression.
> 
> Reviewed-by: Chao Yu 
> Signed-off-by: Gao Xiang 
> ---
>  drivers/staging/erofs/unzip_vle.c | 8 ++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/staging/erofs/unzip_vle.c 
> b/drivers/staging/erofs/unzip_vle.c
> index 4e5843e8ee35..a1376f3c6065 100644
> --- a/drivers/staging/erofs/unzip_vle.c
> +++ b/drivers/staging/erofs/unzip_vle.c
> @@ -420,18 +420,22 @@ z_erofs_vle_work_register(const struct 
> z_erofs_vle_work_finder *f,
>   work = z_erofs_vle_grab_primary_work(grp);
>   work->pageofs = f->pageofs;
>  
> + /* lock all primary followed works before visible to others */
> + if (unlikely(!mutex_trylock(>lock)))
> + /* for a new workgroup, try_lock *never* fails */
> + DBG_BUGON(1);

Again, drop this, if it never fails, then there's no need for this.  If
it can fail, then properly handle it.

And trylock can fail, so this needs to be fixed.

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 07/10] staging: erofs: separate into init_once / always

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:22PM +0800, Gao Xiang wrote:
> `z_erofs_vle_workgroup' is heavily generated in the decompression,
> for example, it resets 32 bytes redundantly for 64-bit platforms
> even through Z_EROFS_VLE_INLINE_PAGEVECS + Z_EROFS_CLUSTER_MAX_PAGES,
> default 4, pages are stored in `z_erofs_vle_workgroup'.
> 
> As an another example, `struct mutex' takes 72 bytes for our kirin
> 64-bit platforms, it's unnecessary to be reseted at first and
> be initialized each time.
> 
> Let's avoid filling all `z_erofs_vle_workgroup' with 0 at first
> since most fields are reinitialized to meaningful values later,
> and pagevec is no need to initialized at all.
> 
> Reviewed-by: Chao Yu 
> Signed-off-by: Gao Xiang 
> ---
>  drivers/staging/erofs/unzip_vle.c | 34 +-
>  1 file changed, 29 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/staging/erofs/unzip_vle.c 
> b/drivers/staging/erofs/unzip_vle.c
> index ede3383ac601..4e5843e8ee35 100644
> --- a/drivers/staging/erofs/unzip_vle.c
> +++ b/drivers/staging/erofs/unzip_vle.c
> @@ -43,12 +43,38 @@ static inline int init_unzip_workqueue(void)
>   return z_erofs_workqueue ? 0 : -ENOMEM;
>  }
>  
> +static void init_once(void *ptr)
> +{
> + struct z_erofs_vle_workgroup *grp = ptr;
> + struct z_erofs_vle_work *const work =
> + z_erofs_vle_grab_primary_work(grp);
> + unsigned int i;
> +
> + mutex_init(>lock);
> + work->nr_pages = 0;
> + work->vcnt = 0;
> + for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i)
> + grp->compressed_pages[i] = NULL;
> +}
> +
> +static void init_always(struct z_erofs_vle_workgroup *grp)
> +{
> + struct z_erofs_vle_work *const work =
> + z_erofs_vle_grab_primary_work(grp);
> +
> + atomic_set(>obj.refcount, 1);
> + grp->flags = 0;
> +
> + DBG_BUGON(work->nr_pages);
> + DBG_BUGON(work->vcnt);

How can these ever be triggered?  I understand the need for debugging
code when you are writing code, but at this point it shouldn't be needed
anymore, right?

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 05/10] staging: erofs: add a full barrier in erofs_workgroup_unfreeze

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:20PM +0800, Gao Xiang wrote:
> Just like other generic locks, insert a full barrier
> in case of memory reorder.
> 
> Reviewed-by: Chao Yu 
> Signed-off-by: Gao Xiang 
> ---
>  drivers/staging/erofs/internal.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/staging/erofs/internal.h 
> b/drivers/staging/erofs/internal.h
> index 2e0ef92c138b..f77653d33633 100644
> --- a/drivers/staging/erofs/internal.h
> +++ b/drivers/staging/erofs/internal.h
> @@ -209,6 +209,7 @@ static inline bool erofs_workgroup_try_to_freeze(struct 
> erofs_workgroup *grp,
>  static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
>   int orig_val)
>  {
> + smp_mb();

Please document this memory barrier.  It does not make much sense to
me...

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/10] staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:19PM +0800, Gao Xiang wrote:
> There are two minor issues in the current freeze interface:
> 
>1) Freeze interfaces have not related with CONFIG_DEBUG_SPINLOCK,
>   therefore fix the incorrect conditions;
> 
>2) For SMP platforms, it should also disable preemption before
>   doing atomic_cmpxchg in case that some high priority tasks
>   preempt between atomic_cmpxchg and disable_preempt, then spin
>   on the locked refcount later.

spinning on a refcount implies that you are trying to do your own type
of locking.  Why not use the in-kernel locking api instead?  It will
always do better than trying to do your own logic as the developers
there know locking across all types of cpus better than filesystem
developers :)

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 03/10] staging: erofs: atomic_cond_read_relaxed on ref-locked workgroup

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:18PM +0800, Gao Xiang wrote:
> It's better to use atomic_cond_read_relaxed, which is implemented
> in hardware instructions to monitor a variable changes currently
> for ARM64, instead of open-coded busy waiting.
> 
> Reviewed-by: Chao Yu 
> Signed-off-by: Gao Xiang 
> ---
>  drivers/staging/erofs/internal.h | 30 ++
>  1 file changed, 18 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/staging/erofs/internal.h 
> b/drivers/staging/erofs/internal.h
> index 89dbd0888e53..eb80ba44d072 100644
> --- a/drivers/staging/erofs/internal.h
> +++ b/drivers/staging/erofs/internal.h
> @@ -221,23 +221,29 @@ static inline void erofs_workgroup_unfreeze(
>   preempt_enable();
>  }
>  
> +#if defined(CONFIG_SMP)
> +static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup 
> *grp)
> +{
> + return atomic_cond_read_relaxed(>refcount,
> + VAL != EROFS_LOCKED_MAGIC);
> +}
> +#else
> +static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup 
> *grp)
> +{
> + int v = atomic_read(>refcount);

Again, why not use the refcount api instead of doing this yourself?

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 01/10] staging: erofs: fix `trace_erofs_readpage' position

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:16PM +0800, Gao Xiang wrote:
> `trace_erofs_readpage' should be placed in .readpage()
> rather than in the internal `z_erofs_do_read_page'.

Why?  What happens with the code today?

> 
> Fixes: 284db12cfda3 ("staging: erofs: add trace points for reading zipped 
> data")

Should this get into 4.20-final?

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:17PM +0800, Gao Xiang wrote:
> When the managed cache is enabled, the last reference count
> of a workgroup must be used for its workstation.
> 
> Otherwise, it could lead to incorrect (un)freezes in
> the reclaim path, and it would be harmful.
> 
> A typical race as follows:
> 
> Thread 1 (In the reclaim path)  Thread 2
> workgroup_freeze(grp, 1)refcnt = 1
> ...
> workgroup_unfreeze(grp, 1)  refcnt = 1
> workgroup_get(grp)  refcnt = 2 (x)
> workgroup_put(grp)  refcnt = 1 (x)
> ...unexpected behaviors
> 
> * grp is detached but still used, which violates cache-managed
>   freeze constraint.
> 
> Reviewed-by: Chao Yu 
> Signed-off-by: Gao Xiang 
> ---
>  drivers/staging/erofs/internal.h |   1 +
>  drivers/staging/erofs/utils.c| 131 
> +++
>  2 files changed, 93 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/staging/erofs/internal.h 
> b/drivers/staging/erofs/internal.h
> index 57575c7f5635..89dbd0888e53 100644
> --- a/drivers/staging/erofs/internal.h
> +++ b/drivers/staging/erofs/internal.h
> @@ -250,6 +250,7 @@ static inline bool erofs_workgroup_get(struct 
> erofs_workgroup *grp, int *ocnt)
>  }
>  
>  #define __erofs_workgroup_get(grp)   atomic_inc(&(grp)->refcount)
> +#define __erofs_workgroup_put(grp)   atomic_dec(&(grp)->refcount)
>  
>  extern int erofs_workgroup_put(struct erofs_workgroup *grp);
>  
> diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c
> index ea8a962e5c95..90de8d9195b7 100644
> --- a/drivers/staging/erofs/utils.c
> +++ b/drivers/staging/erofs/utils.c
> @@ -83,12 +83,21 @@ int erofs_register_workgroup(struct super_block *sb,
>  
>   grp = xa_tag_pointer(grp, tag);
>  
> - err = radix_tree_insert(>workstn_tree,
> - grp->index, grp);
> + /*
> +  * Bump up reference count before making this workgroup
> +  * visible to other users in order to avoid potential UAF
> +  * without serialized by erofs_workstn_lock.
> +  */
> + __erofs_workgroup_get(grp);
>  
> - if (!err) {
> - __erofs_workgroup_get(grp);
> - }
> + err = radix_tree_insert(>workstn_tree,
> + grp->index, grp);
> + if (unlikely(err))
> + /*
> +  * it's safe to decrease since the workgroup isn't visible
> +  * and refcount >= 2 (cannot be freezed).
> +  */
> + __erofs_workgroup_put(grp);
>  
>   erofs_workstn_unlock(sbi);
>   radix_tree_preload_end();
> @@ -97,19 +106,91 @@ int erofs_register_workgroup(struct super_block *sb,
>  
>  extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp);
>  
> +static void  __erofs_workgroup_free(struct erofs_workgroup *grp)
> +{
> + atomic_long_dec(_global_shrink_cnt);
> + erofs_workgroup_free_rcu(grp);
> +}
> +
>  int erofs_workgroup_put(struct erofs_workgroup *grp)
>  {
>   int count = atomic_dec_return(>refcount);
>  
>   if (count == 1)
>   atomic_long_inc(_global_shrink_cnt);
> - else if (!count) {
> - atomic_long_dec(_global_shrink_cnt);
> - erofs_workgroup_free_rcu(grp);
> - }
> + else if (!count)
> + __erofs_workgroup_free(grp);
>   return count;
>  }
>  
> +#ifdef EROFS_FS_HAS_MANAGED_CACHE
> +/* for cache-managed case, customized reclaim paths exist */
> +static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp)
> +{
> + erofs_workgroup_unfreeze(grp, 0);
> + __erofs_workgroup_free(grp);
> +}
> +
> +bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
> + struct erofs_workgroup *grp,
> + bool cleanup)
> +{
> + /*
> +  * for managed cache enabled, the refcount of workgroups
> +  * themselves could be < 0 (freezed). So there is no guarantee
> +  * that all refcount > 0 if managed cache is enabled.
> +  */
> + if (!erofs_workgroup_try_to_freeze(grp, 1))
> + return false;
> +
> + /*
> +  * note that all cached pages should be unlinked
> +  * before delete it from the radix tree.
> +  * Otherwise some cached pages of an orphan old workgroup
> +  * could be still linked after the new one is available.
> +  */
> + if (erofs_try_to_free_all_cached_pages(sbi, grp)) {
> + erofs_workgroup_unfreeze(grp, 1);
> + return false;
> + }
> +
> + /* it is impossible to fail after we freeze the workgroup */
> + BUG_ON(xa_untag_pointer(radix_tree_delete(>workstn_tree,
> +   grp->index)) != grp);
> +

It is not a good idea to crash the system.  Please try to recover from
this, a BUG_ON() implies that the developer has no idea how to handle
this type of 

Re: [PATCH 02/10] staging: erofs: fix race when the managed cache is enabled

2018-11-22 Thread Greg Kroah-Hartman
On Tue, Nov 20, 2018 at 10:34:17PM +0800, Gao Xiang wrote:
> When the managed cache is enabled, the last reference count
> of a workgroup must be used for its workstation.
> 
> Otherwise, it could lead to incorrect (un)freezes in
> the reclaim path, and it would be harmful.
> 
> A typical race as follows:
> 
> Thread 1 (In the reclaim path)  Thread 2
> workgroup_freeze(grp, 1)refcnt = 1
> ...
> workgroup_unfreeze(grp, 1)  refcnt = 1
> workgroup_get(grp)  refcnt = 2 (x)
> workgroup_put(grp)  refcnt = 1 (x)
> ...unexpected behaviors
> 
> * grp is detached but still used, which violates cache-managed
>   freeze constraint.
> 
> Reviewed-by: Chao Yu 
> Signed-off-by: Gao Xiang 
> ---
>  drivers/staging/erofs/internal.h |   1 +
>  drivers/staging/erofs/utils.c| 131 
> +++
>  2 files changed, 93 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/staging/erofs/internal.h 
> b/drivers/staging/erofs/internal.h
> index 57575c7f5635..89dbd0888e53 100644
> --- a/drivers/staging/erofs/internal.h
> +++ b/drivers/staging/erofs/internal.h
> @@ -250,6 +250,7 @@ static inline bool erofs_workgroup_get(struct 
> erofs_workgroup *grp, int *ocnt)
>  }
>  
>  #define __erofs_workgroup_get(grp)   atomic_inc(&(grp)->refcount)
> +#define __erofs_workgroup_put(grp)   atomic_dec(&(grp)->refcount)

Any specific reason why you are not using the refcount.h api instead of
"doing it yourself" with atomic_inc/dec()?

I'm not rejecting this, just curious.

thanks,

greg k-h
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2] makedumpfile: exclude pages that are logically offline

2018-11-22 Thread David Hildenbrand
Linux marks pages that are logically offline via a page flag (map count).
Such pages e.g. include pages infated as part of a balloon driver or
pages that were not actually onlined when onlining the whole section.

While the hypervisor usually allows to read such inflated memory, we
basically read and dump data that is completely irrelevant. Also, this
might result in quite some overhead in the hypervisor. In addition,
we saw some problems under Hyper-V, whereby we can crash the kernel by
dumping, when reading memory of a partially onlined memory segment
(for memory added by the Hyper-V balloon driver).

Therefore, don't read and dump pages that are marked as being logically
offline.

Signed-off-by: David Hildenbrand 
---

v1 -> v2:
- Fix PAGE_BUDDY_MAPCOUNT_VALUE vs. PAGE_OFFLINE_MAPCOUNT_VALUE

 makedumpfile.c | 34 ++
 makedumpfile.h |  1 +
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 8923538..a5f2ea9 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -88,6 +88,7 @@ mdf_pfn_t pfn_cache_private;
 mdf_pfn_t pfn_user;
 mdf_pfn_t pfn_free;
 mdf_pfn_t pfn_hwpoison;
+mdf_pfn_t pfn_offline;
 
 mdf_pfn_t num_dumped;
 
@@ -249,6 +250,21 @@ isHugetlb(unsigned long dtor)
 && (SYMBOL(free_huge_page) == dtor));
 }
 
+static int
+isOffline(unsigned long flags, unsigned int _mapcount)
+{
+   if (NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE) == NOT_FOUND_NUMBER)
+   return FALSE;
+
+   if (flags & (1UL << NUMBER(PG_slab)))
+   return FALSE;
+
+   if (_mapcount == (int)NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE))
+   return TRUE;
+
+   return FALSE;
+}
+
 static int
 is_cache_page(unsigned long flags)
 {
@@ -2287,6 +2303,8 @@ write_vmcoreinfo_data(void)
WRITE_NUMBER("PG_hwpoison", PG_hwpoison);
 
WRITE_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
+   WRITE_NUMBER("PAGE_OFFLINE_MAPCOUNT_VALUE",
+PAGE_OFFLINE_MAPCOUNT_VALUE);
WRITE_NUMBER("phys_base", phys_base);
 
WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
@@ -2687,6 +2705,7 @@ read_vmcoreinfo(void)
READ_SRCFILE("pud_t", pud_t);
 
READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
+   READ_NUMBER("PAGE_OFFLINE_MAPCOUNT_VALUE", PAGE_OFFLINE_MAPCOUNT_VALUE);
READ_NUMBER("phys_base", phys_base);
 #ifdef __aarch64__
READ_NUMBER("VA_BITS", VA_BITS);
@@ -6041,6 +6060,12 @@ __exclude_unnecessary_pages(unsigned long mem_map,
else if (isHWPOISON(flags)) {
pfn_counter = _hwpoison;
}
+   /*
+* Exclude pages that are logically offline.
+*/
+   else if (isOffline(flags, _mapcount)) {
+   pfn_counter = _offline;
+   }
/*
 * Unexcludable page
 */
@@ -7522,7 +7547,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, 
struct cache_data *cd_page)
 */
if (info->flag_cyclic) {
pfn_zero = pfn_cache = pfn_cache_private = 0;
-   pfn_user = pfn_free = pfn_hwpoison = 0;
+   pfn_user = pfn_free = pfn_hwpoison = pfn_offline = 0;
pfn_memhole = info->max_mapnr;
}
 
@@ -8804,7 +8829,7 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data 
*cd_header, struct cache_d
 * Reset counter for debug message.
 */
pfn_zero = pfn_cache = pfn_cache_private = 0;
-   pfn_user = pfn_free = pfn_hwpoison = 0;
+   pfn_user = pfn_free = pfn_hwpoison = pfn_offline = 0;
pfn_memhole = info->max_mapnr;
 
/*
@@ -9749,7 +9774,7 @@ print_report(void)
pfn_original = info->max_mapnr - pfn_memhole;
 
pfn_excluded = pfn_zero + pfn_cache + pfn_cache_private
-   + pfn_user + pfn_free + pfn_hwpoison;
+   + pfn_user + pfn_free + pfn_hwpoison + pfn_offline;
shrinking = (pfn_original - pfn_excluded) * 100;
shrinking = shrinking / pfn_original;
 
@@ -9763,6 +9788,7 @@ print_report(void)
REPORT_MSG("User process data pages : 0x%016llx\n", pfn_user);
REPORT_MSG("Free pages  : 0x%016llx\n", pfn_free);
REPORT_MSG("Hwpoison pages  : 0x%016llx\n", pfn_hwpoison);
+   REPORT_MSG("Offline pages   : 0x%016llx\n", pfn_offline);
REPORT_MSG("  Remaining pages  : 0x%016llx\n",
pfn_original - pfn_excluded);
REPORT_MSG("  (The number of pages is reduced to %lld%%.)\n",
@@ -9790,7 +9816,7 @@ print_mem_usage(void)
pfn_original = info->max_mapnr - pfn_memhole;
 
pfn_excluded = pfn_zero + pfn_cache + pfn_cache_private
-   + pfn_user + pfn_free + pfn_hwpoison;
+   + pfn_user + pfn_free + pfn_hwpoison + pfn_offline;

[PATCH v2 6/8] vmw_balloon: mark inflated pages PG_offline

2018-11-22 Thread David Hildenbrand
Mark inflated and never onlined pages PG_offline, to tell the world that
the content is stale and should not be dumped.

Cc: Xavier Deguillard 
Cc: Nadav Amit 
Cc: Arnd Bergmann 
Cc: Greg Kroah-Hartman 
Cc: Julien Freche 
Cc: Andrew Morton 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Acked-by: Nadav Amit 
Signed-off-by: David Hildenbrand 
---
 drivers/misc/vmw_balloon.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index e6126a4b95d3..877611b5659b 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -556,6 +556,36 @@ vmballoon_page_in_frames(enum vmballoon_page_size_type 
page_size)
return 1 << vmballoon_page_order(page_size);
 }
 
+/**
+ * vmballoon_mark_page_offline() - mark a page as offline
+ * @page: pointer for the page.
+ * @page_size: the size of the page.
+ */
+static void
+vmballoon_mark_page_offline(struct page *page,
+   enum vmballoon_page_size_type page_size)
+{
+   int i;
+
+   for (i = 0; i < vmballoon_page_in_frames(page_size); i++)
+   __SetPageOffline(page + i);
+}
+
+/**
+ * vmballoon_mark_page_online() - mark a page as online
+ * @page: pointer for the page.
+ * @page_size: the size of the page.
+ */
+static void
+vmballoon_mark_page_online(struct page *page,
+  enum vmballoon_page_size_type page_size)
+{
+   int i;
+
+   for (i = 0; i < vmballoon_page_in_frames(page_size); i++)
+   __ClearPageOffline(page + i);
+}
+
 /**
  * vmballoon_send_get_target() - Retrieve desired balloon size from the host.
  *
@@ -612,6 +642,7 @@ static int vmballoon_alloc_page_list(struct vmballoon *b,
 ctl->page_size);
 
if (page) {
+   vmballoon_mark_page_offline(page, ctl->page_size);
/* Success. Add the page to the list and continue. */
list_add(>lru, >pages);
continue;
@@ -850,6 +881,7 @@ static void vmballoon_release_page_list(struct list_head 
*page_list,
 
list_for_each_entry_safe(page, tmp, page_list, lru) {
list_del(>lru);
+   vmballoon_mark_page_online(page, page_size);
__free_pages(page, vmballoon_page_order(page_size));
}
 
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 7/8] PM / Hibernate: use pfn_to_online_page()

2018-11-22 Thread David Hildenbrand
Let's use pfn_to_online_page() instead of pfn_to_page() when checking
for saveable pages to not save/restore offline memory sections.

Cc: "Rafael J. Wysocki" 
Cc: Pavel Machek 
Cc: Len Brown 
Cc: Andrew Morton 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Suggested-by: Michal Hocko 
Acked-by: Michal Hocko 
Acked-by: Pavel Machek 
Acked-by: Rafael J. Wysocki 
Signed-off-by: David Hildenbrand 
---
 kernel/power/snapshot.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 640b2034edd6..87e6dd57819f 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1215,8 +1215,8 @@ static struct page *saveable_highmem_page(struct zone 
*zone, unsigned long pfn)
if (!pfn_valid(pfn))
return NULL;
 
-   page = pfn_to_page(pfn);
-   if (page_zone(page) != zone)
+   page = pfn_to_online_page(pfn);
+   if (!page || page_zone(page) != zone)
return NULL;
 
BUG_ON(!PageHighMem(page));
@@ -1277,8 +1277,8 @@ static struct page *saveable_page(struct zone *zone, 
unsigned long pfn)
if (!pfn_valid(pfn))
return NULL;
 
-   page = pfn_to_page(pfn);
-   if (page_zone(page) != zone)
+   page = pfn_to_online_page(pfn);
+   if (!page || page_zone(page) != zone)
return NULL;
 
BUG_ON(PageHighMem(page));
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 4/8] xen/balloon: mark inflated pages PG_offline

2018-11-22 Thread David Hildenbrand
Mark inflated and never onlined pages PG_offline, to tell the world that
the content is stale and should not be dumped.

Cc: Boris Ostrovsky 
Cc: Juergen Gross 
Cc: Stefano Stabellini 
Cc: Andrew Morton 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Signed-off-by: David Hildenbrand 
---
 drivers/xen/balloon.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 12148289debd..14dd6b814db3 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -425,6 +425,7 @@ static int xen_bring_pgs_online(struct page *pg, unsigned 
int order)
for (i = 0; i < size; i++) {
p = pfn_to_page(start_pfn + i);
__online_page_set_limits(p);
+   __SetPageOffline(p);
__balloon_append(p);
}
mutex_unlock(_mutex);
@@ -493,6 +494,7 @@ static enum bp_state increase_reservation(unsigned long 
nr_pages)
xenmem_reservation_va_mapping_update(1, , _list[i]);
 
/* Relinquish the page back to the allocator. */
+   __ClearPageOffline(page);
free_reserved_page(page);
}
 
@@ -519,6 +521,7 @@ static enum bp_state decrease_reservation(unsigned long 
nr_pages, gfp_t gfp)
state = BP_EAGAIN;
break;
}
+   __SetPageOffline(page);
adjust_managed_page_count(page, -1);
xenmem_reservation_scrub_page(page);
list_add(>lru, );
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 8/8] PM / Hibernate: exclude all PageOffline() pages

2018-11-22 Thread David Hildenbrand
The content of pages that are marked PG_offline is not of interest
(e.g. inflated by a balloon driver), let's skip these pages.

In saveable_highmem_page(), move the PageReserved() check to a new
check along with the PageOffline() check to separate it from the
swsusp checks.

Cc: "Rafael J. Wysocki" 
Cc: Pavel Machek 
Cc: Len Brown 
Cc: Andrew Morton 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Acked-by: Pavel Machek 
Acked-by: Rafael J. Wysocki 
Signed-off-by: David Hildenbrand 
---
 kernel/power/snapshot.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 87e6dd57819f..4802b039b89f 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1221,8 +1221,10 @@ static struct page *saveable_highmem_page(struct zone 
*zone, unsigned long pfn)
 
BUG_ON(!PageHighMem(page));
 
-   if (swsusp_page_is_forbidden(page) ||  swsusp_page_is_free(page) ||
-   PageReserved(page))
+   if (swsusp_page_is_forbidden(page) ||  swsusp_page_is_free(page))
+   return NULL;
+
+   if (PageReserved(page) || PageOffline(page))
return NULL;
 
if (page_is_guard(page))
@@ -1286,6 +1288,9 @@ static struct page *saveable_page(struct zone *zone, 
unsigned long pfn)
if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
return NULL;
 
+   if (PageOffline(page))
+   return NULL;
+
if (PageReserved(page)
&& (!kernel_page_present(page) || pfn_is_nosave(pfn)))
return NULL;
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 5/8] hv_balloon: mark inflated pages PG_offline

2018-11-22 Thread David Hildenbrand
Mark inflated and never onlined pages PG_offline, to tell the world that
the content is stale and should not be dumped.

Cc: "K. Y. Srinivasan" 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: Kairui Song 
Cc: Vitaly Kuznetsov 
Cc: Andrew Morton 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Acked-by: Pankaj gupta 
Signed-off-by: David Hildenbrand 
---
 drivers/hv/hv_balloon.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 211f3fe3a038..47719862e57f 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -681,8 +681,13 @@ static struct notifier_block hv_memory_nb = {
 /* Check if the particular page is backed and can be onlined and online it. */
 static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg)
 {
-   if (!has_pfn_is_backed(has, page_to_pfn(pg)))
+   if (!has_pfn_is_backed(has, page_to_pfn(pg))) {
+   if (!PageOffline(pg))
+   __SetPageOffline(pg);
return;
+   }
+   if (PageOffline(pg))
+   __ClearPageOffline(pg);
 
/* This frame is currently backed; online the page. */
__online_page_set_limits(pg);
@@ -1201,6 +1206,7 @@ static void free_balloon_pages(struct hv_dynmem_device 
*dm,
 
for (i = 0; i < num_pages; i++) {
pg = pfn_to_page(i + start_frame);
+   __ClearPageOffline(pg);
__free_page(pg);
dm->num_pages_ballooned--;
}
@@ -1213,7 +1219,7 @@ static unsigned int alloc_balloon_pages(struct 
hv_dynmem_device *dm,
struct dm_balloon_response *bl_resp,
int alloc_unit)
 {
-   unsigned int i = 0;
+   unsigned int i, j;
struct page *pg;
 
if (num_pages < alloc_unit)
@@ -1245,6 +1251,10 @@ static unsigned int alloc_balloon_pages(struct 
hv_dynmem_device *dm,
if (alloc_unit != 1)
split_page(pg, get_order(alloc_unit << PAGE_SHIFT));
 
+   /* mark all pages offline */
+   for (j = 0; j < (1 << get_order(alloc_unit << PAGE_SHIFT)); j++)
+   __SetPageOffline(pg + j);
+
bl_resp->range_count++;
bl_resp->range_array[i].finfo.start_page =
page_to_pfn(pg);
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 3/8] kexec: export PG_offline to VMCOREINFO

2018-11-22 Thread David Hildenbrand
Right now, pages inflated as part of a balloon driver will be dumped
by dump tools like makedumpfile. While XEN is able to check in the
crash kernel whether a certain pfn is actuall backed by memory in the
hypervisor (see xen_oldmem_pfn_is_ram) and optimize this case, dumps of
other balloon inflated memory will essentially result in zero pages getting
allocated by the hypervisor and the dump getting filled with this data.

The allocation and reading of zero pages can directly be avoided if a
dumping tool could know which pages only contain stale information not to
be dumped.

We now have PG_offline which can be (and already is by virtio-balloon)
used for marking pages as logically offline. Follow up patches will
make use of this flag also in other balloon implementations.

Let's export PG_offline via PAGE_OFFLINE_MAPCOUNT_VALUE, so
makedumpfile can directly skip pages that are logically offline and the
content therefore stale. (we export is as a macro to match how it is
done for PG_buddy. This way it is clearer that this is not actually a flag
but only a very specific mapcount value to represent page types).

Please note that this is also helpful for a problem we were seeing under
Hyper-V: Dumping logically offline memory (pages kept fake offline while
onlining a section via online_page_callback) would under some condicions
result in a kernel panic when dumping them.

Cc: Andrew Morton 
Cc: Dave Young 
Cc: "Kirill A. Shutemov" 
Cc: Baoquan He 
Cc: Omar Sandoval 
Cc: Arnd Bergmann 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Cc: Lianbo Jiang 
Cc: Borislav Petkov 
Cc: Kazuhito Hagio 
Acked-by: Michael S. Tsirkin 
Acked-by: Dave Young 
Signed-off-by: David Hildenbrand 
---
 kernel/crash_core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 933cb3e45b98..093c9f917ed0 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -464,6 +464,8 @@ static int __init crash_save_vmcoreinfo_init(void)
VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
 #ifdef CONFIG_HUGETLB_PAGE
VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
+#define PAGE_OFFLINE_MAPCOUNT_VALUE(~PG_offline)
+   VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE);
 #endif
 
arch_crash_save_vmcoreinfo();
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 1/8] mm: balloon: update comment about isolation/migration/compaction

2018-11-22 Thread David Hildenbrand
Commit b1123ea6d3b3 ("mm: balloon: use general non-lru movable page
feature") reworked balloon handling to make use of the general
non-lru movable page feature. The big comment block in
balloon_compaction.h contains quite some outdated information. Let's fix
this.

Cc: Andrew Morton 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: "Michael S. Tsirkin" 
Acked-by: Michael S. Tsirkin 
Signed-off-by: David Hildenbrand 
---
 include/linux/balloon_compaction.h | 26 +-
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/include/linux/balloon_compaction.h 
b/include/linux/balloon_compaction.h
index 53051f3d8f25..cbe50da5a59d 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -4,15 +4,18 @@
  *
  * Common interface definitions for making balloon pages movable by compaction.
  *
- * Despite being perfectly possible to perform ballooned pages migration, they
- * make a special corner case to compaction scans because balloon pages are not
- * enlisted at any LRU list like the other pages we do compact / migrate.
+ * Balloon page migration makes use of the general non-lru movable page
+ * feature.
+ *
+ * page->private is used to reference the responsible balloon device.
+ * page->mapping is used in context of non-lru page migration to reference
+ * the address space operations for page isolation/migration/compaction.
  *
  * As the page isolation scanning step a compaction thread does is a lockless
  * procedure (from a page standpoint), it might bring some racy situations 
while
  * performing balloon page compaction. In order to sort out these racy 
scenarios
  * and safely perform balloon's page compaction and migration we must, always,
- * ensure following these three simple rules:
+ * ensure following these simple rules:
  *
  *   i. when updating a balloon's page ->mapping element, strictly do it under
  *  the following lock order, independently of the far superior
@@ -21,19 +24,8 @@
  *   +--spin_lock_irq(_dev_info->pages_lock);
  * ... page->mapping updates here ...
  *
- *  ii. before isolating or dequeueing a balloon page from the balloon device
- *  pages list, the page reference counter must be raised by one and the
- *  extra refcount must be dropped when the page is enqueued back into
- *  the balloon device page list, thus a balloon page keeps its reference
- *  counter raised only while it is under our special handling;
- *
- * iii. after the lockless scan step have selected a potential balloon page for
- *  isolation, re-test the PageBalloon mark and the PagePrivate flag
- *  under the proper page lock, to ensure isolating a valid balloon page
- *  (not yet isolated, nor under release procedure)
- *
- *  iv. isolation or dequeueing procedure must clear PagePrivate flag under
- *  page lock together with removing page from balloon device page list.
+ *  ii. isolation or dequeueing procedure must remove the page from balloon
+ *  device page list under b_dev_info->pages_lock.
  *
  * The functions provided by this interface are placed to help on coping with
  * the aforementioned balloon page corner case, as well as to ensure the simple
-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 0/8] mm/kdump: allow to exclude pages that are logically offline

2018-11-22 Thread David Hildenbrand
Right now, pages inflated as part of a balloon driver will be dumped
by dump tools like makedumpfile. While XEN is able to check in the
crash kernel whether a certain pfn is actually backed by memory in the
hypervisor (see xen_oldmem_pfn_is_ram) and optimize this case, dumps of
virtio-balloon, hv-balloon and VMWare balloon inflated memory will
essentially result in zero pages getting allocated by the hypervisor and
the dump getting filled with this data.

The allocation and reading of zero pages can directly be avoided if a
dumping tool could know which pages only contain stale information not to
be dumped.

Also for XEN, calling into the kernel and asking the hypervisor if a
pfn is backed can be avoided if the duming tool would skip such pages
right from the beginning.

Dumping tools have no idea whether a given page is part of a balloon driver
and shall not be dumped. Esp. PG_reserved cannot be used for that purpose
as all memory allocated during early boot is also PG_reserved, see
discussion at [1]. So some other way of indication is required and a new
page flag is frowned upon.

We have PG_balloon (MAPCOUNT value), which is essentially unused now. I
suggest renaming it to something more generic (PG_offline) to mark pages as
logically offline. This flag can than e.g. also be used by virtio-mem in
the future to mark subsections as offline. Or by other code that wants to
put pages logically offline (e.g. later maybe poisoned pages that shall
no longer be used).

This series converts PG_balloon to PG_offline, allows dumping tools to
query the value to detect such pages and marks pages in the hv-balloon
and XEN balloon properly as PG_offline. Note that virtio-balloon already
set pages to PG_balloon (and now PG_offline).

Please note that this is also helpful for a problem we were seeing under
Hyper-V: Dumping logically offline memory (pages kept fake offline while
onlining a section via online_page_callback) would under some condicions
result in a kernel panic when dumping them.

As I don't have access to neither XEN nor Hyper-V nor VMWare installations,
this was only tested with the virtio-balloon and pages were properly
skipped when dumping. I'll also attach the makedumpfile patch to this
series.

[1] https://lkml.org/lkml/2018/7/20/566

v1 -> v2:
- "kexec: export PG_offline to VMCOREINFO"
-- Add description why it is exported as a macro
- "vmw_balloon: mark inflated pages PG_offline"
-- Use helper function + adapt comments
- "PM / Hibernate: exclude all PageOffline() pages"
-- Perform the check separate from swsusp checks.
- Added RBs/ACKs


David Hildenbrand (8):
  mm: balloon: update comment about isolation/migration/compaction
  mm: convert PG_balloon to PG_offline
  kexec: export PG_offline to VMCOREINFO
  xen/balloon: mark inflated pages PG_offline
  hv_balloon: mark inflated pages PG_offline
  vmw_balloon: mark inflated pages PG_offline
  PM / Hibernate: use pfn_to_online_page()
  PM / Hibernate: exclude all PageOffline() pages

 Documentation/admin-guide/mm/pagemap.rst |  9 ---
 drivers/hv/hv_balloon.c  | 14 --
 drivers/misc/vmw_balloon.c   | 32 ++
 drivers/xen/balloon.c|  3 +++
 fs/proc/page.c   |  4 +--
 include/linux/balloon_compaction.h   | 34 +---
 include/linux/page-flags.h   | 11 +---
 include/uapi/linux/kernel-page-flags.h   |  2 +-
 kernel/crash_core.c  |  2 ++
 kernel/power/snapshot.c  | 17 +++-
 tools/vm/page-types.c|  2 +-
 11 files changed, 90 insertions(+), 40 deletions(-)

-- 
2.17.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 2/8] mm: convert PG_balloon to PG_offline

2018-11-22 Thread David Hildenbrand
PG_balloon was introduced to implement page migration/compaction for pages
inflated in virtio-balloon. Nowadays, it is only a marker that a page is
part of virtio-balloon and therefore logically offline.

We also want to make use of this flag in other balloon drivers - for
inflated pages or when onlining a section but keeping some pages offline
(e.g. used right now by XEN and Hyper-V via set_online_page_callback()).

We are going to expose this flag to dump tools like makedumpfile. But
instead of exposing PG_balloon, let's generalize the concept of marking
pages as logically offline, so it can be reused for other purposes
later on.

Rename PG_balloon to PG_offline. This is an indicator that the page is
logically offline, the content stale and that it should not be touched
(e.g. a hypervisor would have to allocate backing storage in order for the
guest to dump an unused page).  We can then e.g. exclude such pages from
dumps.

We replace and reuse KPF_BALLOON (23), as this shouldn't really harm
(and for now the semantics stay the same).  In following patches, we will
make use of this bit also in other balloon drivers. While at it, document
PGTABLE.

Cc: Jonathan Corbet 
Cc: Alexey Dobriyan 
Cc: Mike Rapoport 
Cc: Andrew Morton 
Cc: Christian Hansen 
Cc: Vlastimil Babka 
Cc: "Kirill A. Shutemov" 
Cc: Stephen Rothwell 
Cc: Matthew Wilcox 
Cc: "Michael S. Tsirkin" 
Cc: Michal Hocko 
Cc: Pavel Tatashin 
Cc: Alexander Duyck 
Cc: Naoya Horiguchi 
Cc: Miles Chen 
Cc: David Rientjes 
Cc: Konstantin Khlebnikov 
Cc: Kazuhito Hagio 
Acked-by: Konstantin Khlebnikov 
Acked-by: Michael S. Tsirkin 
Acked-by: Pankaj gupta 
Signed-off-by: David Hildenbrand 
---
 Documentation/admin-guide/mm/pagemap.rst |  9 ++---
 fs/proc/page.c   |  4 ++--
 include/linux/balloon_compaction.h   |  8 
 include/linux/page-flags.h   | 11 +++
 include/uapi/linux/kernel-page-flags.h   |  2 +-
 tools/vm/page-types.c|  2 +-
 6 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/Documentation/admin-guide/mm/pagemap.rst 
b/Documentation/admin-guide/mm/pagemap.rst
index 3f7bade2c231..340a5aee9b80 100644
--- a/Documentation/admin-guide/mm/pagemap.rst
+++ b/Documentation/admin-guide/mm/pagemap.rst
@@ -75,9 +75,10 @@ number of times a page is mapped.
 20. NOPAGE
 21. KSM
 22. THP
-23. BALLOON
+23. OFFLINE
 24. ZERO_PAGE
 25. IDLE
+26. PGTABLE
 
  * ``/proc/kpagecgroup``.  This file contains a 64-bit inode number of the
memory cgroup each page is charged to, indexed by PFN. Only available when
@@ -118,8 +119,8 @@ Short descriptions to the page flags
 identical memory pages dynamically shared between one or more processes
 22 - THP
 contiguous pages which construct transparent hugepages
-23 - BALLOON
-balloon compaction page
+23 - OFFLINE
+page is logically offline
 24 - ZERO_PAGE
 zero page for pfn_zero or huge_zero page
 25 - IDLE
@@ -128,6 +129,8 @@ Short descriptions to the page flags
 Note that this flag may be stale in case the page was accessed via
 a PTE. To make sure the flag is up-to-date one has to read
 ``/sys/kernel/mm/page_idle/bitmap`` first.
+26 - PGTABLE
+page is in use as a page table
 
 IO related page flags
 -
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 6c517b11acf8..378401af4d9d 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -152,8 +152,8 @@ u64 stable_page_flags(struct page *page)
else if (page_count(page) == 0 && is_free_buddy_page(page))
u |= 1 << KPF_BUDDY;
 
-   if (PageBalloon(page))
-   u |= 1 << KPF_BALLOON;
+   if (PageOffline(page))
+   u |= 1 << KPF_OFFLINE;
if (PageTable(page))
u |= 1 << KPF_PGTABLE;
 
diff --git a/include/linux/balloon_compaction.h 
b/include/linux/balloon_compaction.h
index cbe50da5a59d..f111c780ef1d 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -95,7 +95,7 @@ extern int balloon_page_migrate(struct address_space *mapping,
 static inline void balloon_page_insert(struct balloon_dev_info *balloon,
   struct page *page)
 {
-   __SetPageBalloon(page);
+   __SetPageOffline(page);
__SetPageMovable(page, balloon->inode->i_mapping);
set_page_private(page, (unsigned long)balloon);
list_add(>lru, >pages);
@@ -111,7 +111,7 @@ static inline void balloon_page_insert(struct 
balloon_dev_info *balloon,
  */
 static inline void balloon_page_delete(struct page *page)
 {
-   __ClearPageBalloon(page);
+   __ClearPageOffline(page);
__ClearPageMovable(page);
set_page_private(page, 0);
/*
@@ -141,13 +141,13 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
 static inline void balloon_page_insert(struct balloon_dev_info *balloon,
   struct page *page)
 {
-   

Re: [PATCH v8 03/12] media: staging/imx7: add imx7 CSI subdev driver

2018-11-22 Thread Rui Miguel Silva

Hi Sakari,
thanks for all the reviews.

On Wed 21 Nov 2018 at 22:29, Sakari Ailus wrote:

Hi Rui,

On Wed, Nov 21, 2018 at 11:15:49AM +, Rui Miguel Silva 
wrote:
This add the media entity subdevice and control driver for the 
i.MX7

CMOS Sensor Interface.

Signed-off-by: Rui Miguel Silva 
---
 drivers/staging/media/imx/Kconfig  |9 +-
 drivers/staging/media/imx/Makefile |2 +
 drivers/staging/media/imx/imx7-media-csi.c | 1352 
 

 3 files changed, 1362 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/media/imx/imx7-media-csi.c

diff --git a/drivers/staging/media/imx/Kconfig 
b/drivers/staging/media/imx/Kconfig

index bfc17de56b17..40a11f988fc6 100644
--- a/drivers/staging/media/imx/Kconfig
+++ b/drivers/staging/media/imx/Kconfig
@@ -11,7 +11,7 @@ config VIDEO_IMX_MEDIA
  driver for the i.MX5/6 SOC.
 
 if VIDEO_IMX_MEDIA

-menu "i.MX5/6 Media Sub devices"
+menu "i.MX5/6/7 Media Sub devices"
 
 config VIDEO_IMX_CSI

tristate "i.MX5/6 Camera Sensor Interface driver"
@@ -20,5 +20,12 @@ config VIDEO_IMX_CSI
---help---
 	  A video4linux camera sensor interface driver for 
 i.MX5/6.
 
+config VIDEO_IMX7_CSI

+   tristate "i.MX7 Camera Sensor Interface driver"
+   depends on VIDEO_IMX_MEDIA && VIDEO_DEV && I2C


If you need V4L2 fwnode, you should select V4L2_FWNODE. (I 
ignore if it's

already selected by VIDEO_IMX_MEDIA.)


Yes it is selected by VIDEO_IMX_MEDIA.




+   default y
+   ---help---
+ A video4linux camera sensor interface driver for i.MX7.
+
 endmenu
 endif
diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile

index a30b3033f9a3..074f016d3519 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_VIDEO_IMX_MEDIA) += 
imx-media-ic.o
 
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o

 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
+
+obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c

new file mode 100644
index ..ec5a20880bb6
--- /dev/null
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -0,0 +1,1352 @@
+// SPDX-License-Identifier: GPL
+/*
+ * V4L2 Capture CSI Subdev for Freescale i.MX7 SOC
+ *
+ * Copyright (c) 2018 Linaro Ltd
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include "imx-media.h"
+
+#define IMX7_CSI_PAD_SINK  0
+#define IMX7_CSI_PAD_SRC   1
+#define IMX7_CSI_PADS_NUM  2
+
+/* reset values */
+#define CSICR1_RESET_VAL   0x4800
+#define CSICR2_RESET_VAL   0x0
+#define CSICR3_RESET_VAL   0x0
+
+/* csi control reg 1 */
+#define BIT_SWAP16_EN  BIT(31)
+#define BIT_EXT_VSYNC  BIT(30)
+#define BIT_EOF_INT_EN BIT(29)
+#define BIT_PRP_IF_EN  BIT(28)
+#define BIT_CCIR_MODE  BIT(27)
+#define BIT_COF_INT_EN BIT(26)
+#define BIT_SF_OR_INTENBIT(25)
+#define BIT_RF_OR_INTENBIT(24)
+#define BIT_SFF_DMA_DONE_INTEN  BIT(22)
+#define BIT_STATFF_INTEN   BIT(21)
+#define BIT_FB2_DMA_DONE_INTEN  BIT(20)
+#define BIT_FB1_DMA_DONE_INTEN  BIT(19)
+#define BIT_RXFF_INTEN BIT(18)
+#define BIT_SOF_POLBIT(17)
+#define BIT_SOF_INTEN  BIT(16)
+#define BIT_MCLKDIV(0xF << 12)
+#define BIT_HSYNC_POL  BIT(11)
+#define BIT_CCIR_ENBIT(10)
+#define BIT_MCLKEN BIT(9)
+#define BIT_FCCBIT(8)
+#define BIT_PACK_DIR   BIT(7)
+#define BIT_CLR_STATFIFO   BIT(6)
+#define BIT_CLR_RXFIFO BIT(5)
+#define BIT_GCLK_MODE  BIT(4)
+#define BIT_INV_DATA   BIT(3)
+#define BIT_INV_PCLK   BIT(2)
+#define BIT_REDGE  BIT(1)
+#define BIT_PIXEL_BIT  BIT(0)
+
+#define SHIFT_MCLKDIV  12
+
+/* control reg 3 */
+#define BIT_FRMCNT (0x << 16)
+#define BIT_FRMCNT_RST BIT(15)
+#define BIT_DMA_REFLASH_RFFBIT(14)
+#define BIT_DMA_REFLASH_SFFBIT(13)
+#define BIT_DMA_REQ_EN_RFF BIT(12)
+#define BIT_DMA_REQ_EN_SFF BIT(11)
+#define BIT_STATFF_LEVEL   (0x7 << 8)
+#define BIT_HRESP_ERR_EN   BIT(7)
+#define BIT_RXFF_LEVEL (0x7 << 4)
+#define BIT_TWO_8BIT_SENSORBIT(3)
+#define BIT_ZERO_PACK_EN   BIT(2)
+#define BIT_ECC_INT_EN BIT(1)
+#define BIT_ECC_AUTO_ENBIT(0)
+
+#define SHIFT_FRMCNT   16
+#define SHIFT_RXFIFO_LEVEL 4
+
+/* csi status reg */
+#define BIT_ADDR_CH_ERR_INTBIT(28)
+#define BIT_FIELD0_INT BIT(27)
+#define BIT_FIELD1_INT BIT(26)
+#define BIT_SFF_OR_INT BIT(25)
+#define BIT_RFF_OR_INT BIT(24)
+#define BIT_DMA_TSF_DONE_SFF   BIT(22)
+#define 

Re: [PATCH v8 05/12] media: dt-bindings: add bindings for i.MX7 media driver

2018-11-22 Thread Rui Miguel Silva

Hi Sakari,
On Wed 21 Nov 2018 at 22:16, Sakari Ailus wrote:

Hi Rui,

On Wed, Nov 21, 2018 at 11:15:51AM +, Rui Miguel Silva 
wrote:

Add bindings documentation for i.MX7 media drivers.
The imx7 MIPI CSI2 and imx7 CMOS Sensor Interface.

Signed-off-by: Rui Miguel Silva 
Reviewed-by: Rob Herring 
Acked-by: Sakari Ailus 
---
 .../devicetree/bindings/media/imx7-csi.txt| 45 ++
 .../bindings/media/imx7-mipi-csi2.txt | 90 
 +++

 2 files changed, 135 insertions(+)
 create mode 100644 
 Documentation/devicetree/bindings/media/imx7-csi.txt
 create mode 100644 
 Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt


diff --git 
a/Documentation/devicetree/bindings/media/imx7-csi.txt 
b/Documentation/devicetree/bindings/media/imx7-csi.txt

new file mode 100644
index ..171b089ee91f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/imx7-csi.txt
@@ -0,0 +1,45 @@
+Freescale i.MX7 CMOS Sensor Interface
+=
+
+csi node
+
+
+This is device node for the CMOS Sensor Interface (CSI) which 
enables the chip

+to connect directly to external CMOS image sensors.
+
+Required properties:
+
+- compatible: "fsl,imx7-csi";
+- reg   : base address and length of the register set 
for the device;

+- interrupts: should contain CSI interrupt;
+- clocks: list of clock specifiers, see
+ 
Documentation/devicetree/bindings/clock/clock-bindings.txt for 
details;
+- clock-names   : must contain "axi", "mclk" and "dcic" 
entries, matching

+ entries in the clock property;
+
+The device node shall contain one 'port' child node with one 
child 'endpoint'

+node, according to the bindings defined in:
+ Documentation/devicetree/bindings/media/video-interfaces.txt.
+ 
+In the following example a remote endpoint is a video 
multiplexer.

+
+example:
+
+csi: csi@3071 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+compatible = "fsl,imx7-csi";
+reg = <0x3071 0x1>;
+interrupts = IRQ_TYPE_LEVEL_HIGH>;

+clocks = < IMX7D_CLK_DUMMY>,
+< 
IMX7D_CSI_MCLK_ROOT_CLK>,
+< 
IMX7D_CLK_DUMMY>;

+clock-names = "axi", "mclk", "dcic";
+
+port {
+csi_from_csi_mux: endpoint {
+remote-endpoint = 
<_mux_to_csi>;

+};
+};
+};
diff --git 
a/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt 
b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt

new file mode 100644
index ..71fd74ed3ec8
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt

@@ -0,0 +1,90 @@
+Freescale i.MX7 Mipi CSI2
+=
+
+mipi_csi2 node
+--
+
+This is the device node for the MIPI CSI-2 receiver core in 
i.MX7 SoC. It is

+compatible with previous version of Samsung D-phy.
+
+Required properties:
+
+- compatible: "fsl,imx7-mipi-csi2";
+- reg   : base address and length of the register set 
for the device;

+- interrupts: should contain MIPI CSIS interrupt;
+- clocks: list of clock specifiers, see
+ 
Documentation/devicetree/bindings/clock/clock-bindings.txt for 
details;
+- clock-names   : must contain "pclk", "wrap" and "phy" 
entries, matching

+  entries in the clock property;
+- power-domains : a phandle to the power domain, see
+ 
Documentation/devicetree/bindings/power/power_domain.txt for 
details.

+- reset-names   : should include following entry "mrst";
+- resets: a list of phandle, should contain reset 
entry of

+  reset-names;
+- phy-supply: from the generic phy bindings, a phandle to 
a regulator that

+ provides power to MIPI CSIS core;
+
+Optional properties:
+
+- clock-frequency : The IP's main (system bus) clock frequency 
in Hz, default
+		value when this property is not specified is 
166 MHz;
+- fsl,csis-hs-settle : differential receiver (HS-RX) settle 
time;

+
+The device node should contain two 'port' child nodes with one 
child 'endpoint'

+node, according to the bindings defined in:
+ Documentation/devicetree/bindings/ 
media/video-interfaces.txt.


Extra space. The two lines are also prefixed by a space; is that 
intended?


Yes, that will be fix by going over the checkpatch strict.




+ The following are properties specific to those nodes.
+
+port node
+-
+
+- reg		  : (required) can take the values 0 or 1, 
where 0 shall be
+ related to the sink port and port 1 shall 
be the source

+ one;
+
+endpoint node
+-
+
+- data-lanes: (required) an array specifying 

  1   2   >