Merge branch 'mhi-net-immutable' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / events.c
index 3ce17c3..d713ae2 100644 (file)
@@ -23,7 +23,7 @@ static int temp_warn(struct notifier_block *, unsigned long, void *);
 static int port_module(struct notifier_block *, unsigned long, void *);
 static int pcie_core(struct notifier_block *, unsigned long, void *);
 
-/* handler which forwards the event to events->nh, driver notifiers */
+/* handler which forwards the event to events->fw_nh, driver notifiers */
 static int forward_event(struct notifier_block *, unsigned long, void *);
 
 static struct mlx5_nb events_nbs_ref[] = {
@@ -55,12 +55,14 @@ struct mlx5_events {
        struct mlx5_core_dev *dev;
        struct workqueue_struct *wq;
        struct mlx5_event_nb  notifiers[ARRAY_SIZE(events_nbs_ref)];
-       /* driver notifier chain */
-       struct atomic_notifier_head nh;
+       /* driver notifier chain for fw events */
+       struct atomic_notifier_head fw_nh;
        /* port module events stats */
        struct mlx5_pme_stats pme_stats;
        /*pcie_core*/
        struct work_struct pcie_core_work;
+       /* driver notifier chain for sw events */
+       struct blocking_notifier_head sw_nh;
 };
 
 static const char *eqe_type_str(u8 type)
@@ -110,6 +112,8 @@ static const char *eqe_type_str(u8 type)
                return "MLX5_EVENT_TYPE_CMD";
        case MLX5_EVENT_TYPE_ESW_FUNCTIONS_CHANGED:
                return "MLX5_EVENT_TYPE_ESW_FUNCTIONS_CHANGED";
+       case MLX5_EVENT_TYPE_VHCA_STATE_CHANGE:
+               return "MLX5_EVENT_TYPE_VHCA_STATE_CHANGE";
        case MLX5_EVENT_TYPE_PAGE_REQUEST:
                return "MLX5_EVENT_TYPE_PAGE_REQUEST";
        case MLX5_EVENT_TYPE_PAGE_FAULT:
@@ -331,7 +335,7 @@ static int forward_event(struct notifier_block *nb, unsigned long event, void *d
 
        mlx5_core_dbg(events->dev, "Async eqe type %s, subtype (%d) forward to interfaces\n",
                      eqe_type_str(eqe->type), eqe->sub_type);
-       atomic_notifier_call_chain(&events->nh, event, data);
+       atomic_notifier_call_chain(&events->fw_nh, event, data);
        return NOTIFY_OK;
 }
 
@@ -342,7 +346,7 @@ int mlx5_events_init(struct mlx5_core_dev *dev)
        if (!events)
                return -ENOMEM;
 
-       ATOMIC_INIT_NOTIFIER_HEAD(&events->nh);
+       ATOMIC_INIT_NOTIFIER_HEAD(&events->fw_nh);
        events->dev = dev;
        dev->priv.events = events;
        events->wq = create_singlethread_workqueue("mlx5_events");
@@ -351,6 +355,7 @@ int mlx5_events_init(struct mlx5_core_dev *dev)
                return -ENOMEM;
        }
        INIT_WORK(&events->pcie_core_work, mlx5_pcie_event);
+       BLOCKING_INIT_NOTIFIER_HEAD(&events->sw_nh);
 
        return 0;
 }
@@ -383,11 +388,14 @@ void mlx5_events_stop(struct mlx5_core_dev *dev)
        flush_workqueue(events->wq);
 }
 
+/* This API is used only for processing and forwarding firmware
+ * events to mlx5 consumer.
+ */
 int mlx5_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb)
 {
        struct mlx5_events *events = dev->priv.events;
 
-       return atomic_notifier_chain_register(&events->nh, nb);
+       return atomic_notifier_chain_register(&events->fw_nh, nb);
 }
 EXPORT_SYMBOL(mlx5_notifier_register);
 
@@ -395,11 +403,41 @@ int mlx5_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *n
 {
        struct mlx5_events *events = dev->priv.events;
 
-       return atomic_notifier_chain_unregister(&events->nh, nb);
+       return atomic_notifier_chain_unregister(&events->fw_nh, nb);
 }
 EXPORT_SYMBOL(mlx5_notifier_unregister);
 
 int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data)
 {
-       return atomic_notifier_call_chain(&events->nh, event, data);
+       return atomic_notifier_call_chain(&events->fw_nh, event, data);
+}
+
+/* This API is used only for processing and forwarding driver-specific
+ * events to mlx5 consumers.
+ */
+int mlx5_blocking_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb)
+{
+       struct mlx5_events *events = dev->priv.events;
+
+       return blocking_notifier_chain_register(&events->sw_nh, nb);
+}
+
+int mlx5_blocking_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb)
+{
+       struct mlx5_events *events = dev->priv.events;
+
+       return blocking_notifier_chain_unregister(&events->sw_nh, nb);
+}
+
+int mlx5_blocking_notifier_call_chain(struct mlx5_core_dev *dev, unsigned int event,
+                                     void *data)
+{
+       struct mlx5_events *events = dev->priv.events;
+
+       return blocking_notifier_call_chain(&events->sw_nh, event, data);
+}
+
+void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work)
+{
+       queue_work(dev->priv.events->wq, work);
 }