pds_core: publish events to the clients
authorShannon Nelson <shannon.nelson@amd.com>
Wed, 19 Apr 2023 17:04:26 +0000 (10:04 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 21 Apr 2023 07:29:13 +0000 (08:29 +0100)
When the Core device gets an event from the device, or notices
the device FW to be up or down, it needs to send those events
on to the clients that have an event handler.  Add the code to
pass along the events to the clients.

The entry points pdsc_register_notify() and pdsc_unregister_notify()
are EXPORTed for other drivers that want to listen for these events.

Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/amd/pds_core/adminq.c
drivers/net/ethernet/amd/pds_core/core.c
drivers/net/ethernet/amd/pds_core/core.h
include/linux/pds/pds_common.h

index fb2ba3f62480208ce986132f7de2fa8b1b07faaf..045fe133f6ee9957479c67b72b61c8887fbc0afe 100644 (file)
@@ -29,11 +29,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
                case PDS_EVENT_LINK_CHANGE:
                        dev_info(pdsc->dev, "NotifyQ LINK_CHANGE ecode %d eid %lld\n",
                                 ecode, eid);
+                       pdsc_notify(PDS_EVENT_LINK_CHANGE, comp);
                        break;
 
                case PDS_EVENT_RESET:
                        dev_info(pdsc->dev, "NotifyQ RESET ecode %d eid %lld\n",
                                 ecode, eid);
+                       pdsc_notify(PDS_EVENT_RESET, comp);
                        break;
 
                case PDS_EVENT_XCVR:
index b2fca3b99f02d819b8988f4c6e701b4c6f98fe6b..483a070d96fa9c23f8a2986f9a4597b92b0a9eac 100644 (file)
@@ -6,6 +6,25 @@
 
 #include "core.h"
 
+static BLOCKING_NOTIFIER_HEAD(pds_notify_chain);
+
+int pdsc_register_notify(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&pds_notify_chain, nb);
+}
+EXPORT_SYMBOL_GPL(pdsc_register_notify);
+
+void pdsc_unregister_notify(struct notifier_block *nb)
+{
+       blocking_notifier_chain_unregister(&pds_notify_chain, nb);
+}
+EXPORT_SYMBOL_GPL(pdsc_unregister_notify);
+
+void pdsc_notify(unsigned long event, void *data)
+{
+       blocking_notifier_call_chain(&pds_notify_chain, event, data);
+}
+
 void pdsc_intr_free(struct pdsc *pdsc, int index)
 {
        struct pdsc_intr_info *intr_info;
@@ -494,12 +513,19 @@ void pdsc_stop(struct pdsc *pdsc)
 
 static void pdsc_fw_down(struct pdsc *pdsc)
 {
+       union pds_core_notifyq_comp reset_event = {
+               .reset.ecode = cpu_to_le16(PDS_EVENT_RESET),
+               .reset.state = 0,
+       };
+
        if (test_and_set_bit(PDSC_S_FW_DEAD, &pdsc->state)) {
                dev_err(pdsc->dev, "%s: already happening\n", __func__);
                return;
        }
 
+       /* Notify clients of fw_down */
        devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc);
+       pdsc_notify(PDS_EVENT_RESET, &reset_event);
 
        pdsc_stop(pdsc);
        pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY);
@@ -507,6 +533,10 @@ static void pdsc_fw_down(struct pdsc *pdsc)
 
 static void pdsc_fw_up(struct pdsc *pdsc)
 {
+       union pds_core_notifyq_comp reset_event = {
+               .reset.ecode = cpu_to_le16(PDS_EVENT_RESET),
+               .reset.state = 1,
+       };
        int err;
 
        if (!test_bit(PDSC_S_FW_DEAD, &pdsc->state)) {
@@ -522,9 +552,11 @@ static void pdsc_fw_up(struct pdsc *pdsc)
        if (err)
                goto err_out;
 
+       /* Notify clients of fw_up */
        pdsc->fw_recoveries++;
        devlink_health_reporter_state_update(pdsc->fw_reporter,
                                             DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
+       pdsc_notify(PDS_EVENT_RESET, &reset_event);
 
        return;
 
index 9e01a9ee686854f27905e0149fb777d78eb7160b..e545fafc4819697ce9db6ce26d6a70e12a6d017f 100644 (file)
@@ -297,6 +297,9 @@ int pdsc_start(struct pdsc *pdsc);
 void pdsc_stop(struct pdsc *pdsc);
 void pdsc_health_thread(struct work_struct *work);
 
+int pdsc_register_notify(struct notifier_block *nb);
+void pdsc_unregister_notify(struct notifier_block *nb);
+void pdsc_notify(unsigned long event, void *data);
 int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf);
 int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf);
 
index 4b37675fde3e59f4b0f8b727869636cb472e36a5..060331486d50d85a8a7623dab584d7272fa14d0d 100644 (file)
@@ -60,6 +60,8 @@ enum pds_core_logical_qtype {
        PDS_CORE_QTYPE_MAX     = 16   /* don't change - used in struct size */
 };
 
+int pdsc_register_notify(struct notifier_block *nb);
+void pdsc_unregister_notify(struct notifier_block *nb);
 void *pdsc_get_pf_struct(struct pci_dev *vf_pdev);
 int pds_client_register(struct pci_dev *pf_pdev, char *devname);
 int pds_client_unregister(struct pci_dev *pf_pdev, u16 client_id);