struct mlxsw_sp *mlxsw_sp;
        struct list_head analyzed_ports_list;
        struct mutex analyzed_ports_lock; /* Protects analyzed_ports_list */
+       struct list_head trigger_entries_list;
        atomic_t active_entries_count;
        int entries_count;
        struct mlxsw_sp_span_entry entries[];
        bool ingress;
 };
 
+struct mlxsw_sp_span_trigger_entry {
+       struct list_head list; /* Member of trigger_entries_list */
+       refcount_t ref_count;
+       u8 local_port;
+       enum mlxsw_sp_span_trigger trigger;
+       struct mlxsw_sp_span_trigger_parms parms;
+};
+
 static void mlxsw_sp_span_respin_work(struct work_struct *work);
 
 static u64 mlxsw_sp_span_occ_get(void *priv)
        atomic_set(&span->active_entries_count, 0);
        mutex_init(&span->analyzed_ports_lock);
        INIT_LIST_HEAD(&span->analyzed_ports_list);
+       INIT_LIST_HEAD(&span->trigger_entries_list);
        span->mlxsw_sp = mlxsw_sp;
        mlxsw_sp->span = span;
 
 
                WARN_ON_ONCE(!list_empty(&curr->bound_ports_list));
        }
+       WARN_ON_ONCE(!list_empty(&mlxsw_sp->span->trigger_entries_list));
        WARN_ON_ONCE(!list_empty(&mlxsw_sp->span->analyzed_ports_list));
        mutex_destroy(&mlxsw_sp->span->analyzed_ports_lock);
        kfree(mlxsw_sp->span);
 out_unlock:
        mutex_unlock(&mlxsw_sp->span->analyzed_ports_lock);
 }
+
+static int
+__mlxsw_sp_span_trigger_entry_bind(struct mlxsw_sp_span *span,
+                                  struct mlxsw_sp_span_trigger_entry *
+                                  trigger_entry, bool enable)
+{
+       char mpar_pl[MLXSW_REG_MPAR_LEN];
+       enum mlxsw_reg_mpar_i_e i_e;
+
+       switch (trigger_entry->trigger) {
+       case MLXSW_SP_SPAN_TRIGGER_INGRESS:
+               i_e = MLXSW_REG_MPAR_TYPE_INGRESS;
+               break;
+       case MLXSW_SP_SPAN_TRIGGER_EGRESS:
+               i_e = MLXSW_REG_MPAR_TYPE_EGRESS;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+
+       mlxsw_reg_mpar_pack(mpar_pl, trigger_entry->local_port, i_e, enable,
+                           trigger_entry->parms.span_id);
+       return mlxsw_reg_write(span->mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
+}
+
+static int
+mlxsw_sp_span_trigger_entry_bind(struct mlxsw_sp_span *span,
+                                struct mlxsw_sp_span_trigger_entry *
+                                trigger_entry)
+{
+       return __mlxsw_sp_span_trigger_entry_bind(span, trigger_entry, true);
+}
+
+static void
+mlxsw_sp_span_trigger_entry_unbind(struct mlxsw_sp_span *span,
+                                  struct mlxsw_sp_span_trigger_entry *
+                                  trigger_entry)
+{
+       __mlxsw_sp_span_trigger_entry_bind(span, trigger_entry, false);
+}
+
+static struct mlxsw_sp_span_trigger_entry *
+mlxsw_sp_span_trigger_entry_create(struct mlxsw_sp_span *span,
+                                  enum mlxsw_sp_span_trigger trigger,
+                                  struct mlxsw_sp_port *mlxsw_sp_port,
+                                  const struct mlxsw_sp_span_trigger_parms
+                                  *parms)
+{
+       struct mlxsw_sp_span_trigger_entry *trigger_entry;
+       int err;
+
+       trigger_entry = kzalloc(sizeof(*trigger_entry), GFP_KERNEL);
+       if (!trigger_entry)
+               return ERR_PTR(-ENOMEM);
+
+       refcount_set(&trigger_entry->ref_count, 1);
+       trigger_entry->local_port = mlxsw_sp_port->local_port;
+       trigger_entry->trigger = trigger;
+       memcpy(&trigger_entry->parms, parms, sizeof(trigger_entry->parms));
+       list_add_tail(&trigger_entry->list, &span->trigger_entries_list);
+
+       err = mlxsw_sp_span_trigger_entry_bind(span, trigger_entry);
+       if (err)
+               goto err_trigger_entry_bind;
+
+       return trigger_entry;
+
+err_trigger_entry_bind:
+       list_del(&trigger_entry->list);
+       kfree(trigger_entry);
+       return ERR_PTR(err);
+}
+
+static void
+mlxsw_sp_span_trigger_entry_destroy(struct mlxsw_sp_span *span,
+                                   struct mlxsw_sp_span_trigger_entry *
+                                   trigger_entry)
+{
+       mlxsw_sp_span_trigger_entry_unbind(span, trigger_entry);
+       list_del(&trigger_entry->list);
+       kfree(trigger_entry);
+}
+
+static struct mlxsw_sp_span_trigger_entry *
+mlxsw_sp_span_trigger_entry_find(struct mlxsw_sp_span *span,
+                                enum mlxsw_sp_span_trigger trigger,
+                                struct mlxsw_sp_port *mlxsw_sp_port)
+{
+       struct mlxsw_sp_span_trigger_entry *trigger_entry;
+
+       list_for_each_entry(trigger_entry, &span->trigger_entries_list, list) {
+               if (trigger_entry->trigger == trigger &&
+                   trigger_entry->local_port == mlxsw_sp_port->local_port)
+                       return trigger_entry;
+       }
+
+       return NULL;
+}
+
+int mlxsw_sp_span_agent_bind(struct mlxsw_sp *mlxsw_sp,
+                            enum mlxsw_sp_span_trigger trigger,
+                            struct mlxsw_sp_port *mlxsw_sp_port,
+                            const struct mlxsw_sp_span_trigger_parms *parms)
+{
+       struct mlxsw_sp_span_trigger_entry *trigger_entry;
+       int err = 0;
+
+       ASSERT_RTNL();
+
+       if (!mlxsw_sp_span_entry_find_by_id(mlxsw_sp, parms->span_id))
+               return -EINVAL;
+
+       trigger_entry = mlxsw_sp_span_trigger_entry_find(mlxsw_sp->span,
+                                                        trigger,
+                                                        mlxsw_sp_port);
+       if (trigger_entry) {
+               if (trigger_entry->parms.span_id != parms->span_id)
+                       return -EINVAL;
+               refcount_inc(&trigger_entry->ref_count);
+               goto out;
+       }
+
+       trigger_entry = mlxsw_sp_span_trigger_entry_create(mlxsw_sp->span,
+                                                          trigger,
+                                                          mlxsw_sp_port,
+                                                          parms);
+       if (IS_ERR(trigger_entry))
+               err = PTR_ERR(trigger_entry);
+
+out:
+       return err;
+}
+
+void mlxsw_sp_span_agent_unbind(struct mlxsw_sp *mlxsw_sp,
+                               enum mlxsw_sp_span_trigger trigger,
+                               struct mlxsw_sp_port *mlxsw_sp_port,
+                               const struct mlxsw_sp_span_trigger_parms *parms)
+{
+       struct mlxsw_sp_span_trigger_entry *trigger_entry;
+
+       ASSERT_RTNL();
+
+       if (WARN_ON_ONCE(!mlxsw_sp_span_entry_find_by_id(mlxsw_sp,
+                                                        parms->span_id)))
+               return;
+
+       trigger_entry = mlxsw_sp_span_trigger_entry_find(mlxsw_sp->span,
+                                                        trigger,
+                                                        mlxsw_sp_port);
+       if (WARN_ON_ONCE(!trigger_entry))
+               return;
+
+       if (!refcount_dec_and_test(&trigger_entry->ref_count))
+               return;
+
+       mlxsw_sp_span_trigger_entry_destroy(mlxsw_sp->span, trigger_entry);
+}