mlxsw: core: Create a generic function to register / unregister traps
authorNogah Frankel <nogahf@mellanox.com>
Fri, 25 Nov 2016 09:33:30 +0000 (10:33 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sat, 26 Nov 2016 02:22:14 +0000 (21:22 -0500)
We have 2 types of HW traps to handle, rx traps and events.
The registration workflow for both is very similar. So it only make
sense to create one function to handle both.

This patch creates a struct to hold the data for both cases. It also
creates a registration and an un-registration functions that get this
generic struct as input.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core.h

index bcd7251385e3c560ddca469820860d713dbb8e97..a8cff78c7029ee54dc4deea8061ec9cd0debe17b 100644 (file)
@@ -1392,6 +1392,73 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core,
 }
 EXPORT_SYMBOL(mlxsw_core_event_listener_unregister);
 
+static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core,
+                                       const struct mlxsw_listener *listener,
+                                       void *priv)
+{
+       if (listener->is_event)
+               return mlxsw_core_event_listener_register(mlxsw_core,
+                                               &listener->u.event_listener,
+                                               priv);
+       else
+               return mlxsw_core_rx_listener_register(mlxsw_core,
+                                               &listener->u.rx_listener,
+                                               priv);
+}
+
+static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
+                                     const struct mlxsw_listener *listener,
+                                     void *priv)
+{
+       if (listener->is_event)
+               mlxsw_core_event_listener_unregister(mlxsw_core,
+                                                    &listener->u.event_listener,
+                                                    priv);
+       else
+               mlxsw_core_rx_listener_unregister(mlxsw_core,
+                                                 &listener->u.rx_listener,
+                                                 priv);
+}
+
+int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
+                            const struct mlxsw_listener *listener, void *priv)
+{
+       char hpkt_pl[MLXSW_REG_HPKT_LEN];
+       int err;
+
+       err = mlxsw_core_listener_register(mlxsw_core, listener, priv);
+       if (err)
+               return err;
+
+       mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id);
+       err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+       if (err)
+               goto err_trap_set;
+
+       return 0;
+
+err_trap_set:
+       mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
+       return err;
+}
+EXPORT_SYMBOL(mlxsw_core_trap_register);
+
+void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
+                               const struct mlxsw_listener *listener,
+                               void *priv)
+{
+       char hpkt_pl[MLXSW_REG_HPKT_LEN];
+
+       if (!listener->is_event) {
+               mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action,
+                                   listener->trap_id);
+               mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+       }
+
+       mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
+}
+EXPORT_SYMBOL(mlxsw_core_trap_unregister);
+
 static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
 {
        return atomic64_inc_return(&mlxsw_core->emad.tid);
index 3de8955a26fdbd9af84866b8376f8a2eb46d2235..66d97c4953096890564f9851827ad046877b8132 100644 (file)
@@ -90,6 +90,17 @@ struct mlxsw_event_listener {
        enum mlxsw_event_trap_id trap_id;
 };
 
+struct mlxsw_listener {
+       u16 trap_id;
+       union {
+               struct mlxsw_rx_listener rx_listener;
+               struct mlxsw_event_listener event_listener;
+       } u;
+       enum mlxsw_reg_hpkt_action action;
+       enum mlxsw_reg_hpkt_action unreg_action;
+       bool is_event;
+};
+
 int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
                                    const struct mlxsw_rx_listener *rxl,
                                    void *priv);
@@ -104,6 +115,13 @@ void mlxsw_core_event_listener_unregister(struct mlxsw_core *mlxsw_core,
                                          const struct mlxsw_event_listener *el,
                                          void *priv);
 
+int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
+                            const struct mlxsw_listener *listener,
+                            void *priv);
+void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
+                               const struct mlxsw_listener *listener,
+                               void *priv);
+
 typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload,
                                  size_t payload_len, unsigned long cb_priv);