From: Gokul Sivakumar <gokulkumar.sivakumar@infineon.com>
To: <linux-wireless@vger.kernel.org>, <johannes@sipsolutions.net>
Cc: <arend.vanspriel@broadcom.com>,
<wlan-kernel-dev-list@infineon.com>,
<gokulkumar.sivakumar@infineon.com>
Subject: [PATCH wireless-next v3 10/25] wifi: inffmac: add dev_evt.c/h
Date: Wed, 2 Sep 2026 16:50:41 +0000 [thread overview]
Message-ID: <20260902165057.456447-11-gokulkumar.sivakumar@infineon.com> (raw)
In-Reply-To: <20260902165057.456447-1-gokulkumar.sivakumar@infineon.com>
Driver implementation for registering and handling various types of
asynchronous events generated by the CP or the WLAN firmware in the
Device.
Signed-off-by: Gokul Sivakumar <gokulkumar.sivakumar@infineon.com>
---
.../net/wireless/infineon/inffmac/dev_evt.c | 847 ++++++++++++++++++
.../net/wireless/infineon/inffmac/dev_evt.h | 447 +++++++++
2 files changed, 1294 insertions(+)
create mode 100644 drivers/net/wireless/infineon/inffmac/dev_evt.c
create mode 100644 drivers/net/wireless/infineon/inffmac/dev_evt.h
diff --git a/drivers/net/wireless/infineon/inffmac/dev_evt.c b/drivers/net/wireless/infineon/inffmac/dev_evt.c
new file mode 100644
index 000000000000..6d63ad4afab1
--- /dev/null
+++ b/drivers/net/wireless/infineon/inffmac/dev_evt.c
@@ -0,0 +1,847 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Copyright (c) 2025-2026, Infineon Technologies AG, or an affiliate of Infineon Technologies AG.
+ * All rights reserved.
+ */
+#include <linux/netdevice.h>
+
+#include "main.h"
+#include "chan.h"
+#include "utils.h"
+#include "cfg80211.h"
+#include "debug.h"
+#include "dev_evt.h"
+#include "dev_cmd.h"
+#include "interface.h"
+#include "bus_proto.h"
+#include "net.h"
+
+/**
+ * struct inff_fwevt_queue_item - event item on event queue.
+ *
+ * @q: list element for queuing.
+ * @code: event code.
+ * @ifidx: interface index related to this event.
+ * @ifaddr: ethernet address for interface.
+ * @emsg: common parameters of the firmware event message.
+ * @datalen: length of the data array
+ * @data: event specific data part of the firmware event.
+ */
+struct inff_fwevt_queue_item {
+ struct list_head q;
+ enum inff_fwevt_code code;
+ u8 ifidx;
+ u8 ifaddr[ETH_ALEN];
+ struct inff_event_msg_be emsg;
+ u32 datalen;
+ u8 data[] __counted_by(datalen);
+};
+
+/*
+ * struct inff_fwevt_code_name - code, name mapping entry.
+ */
+struct inff_fwevt_code_name {
+ enum inff_fwevt_code code;
+ const char *name;
+};
+
+#ifdef DEBUG
+/* array for mapping code to event name */
+static struct inff_fwevt_code_name
+fwevt_names[] = {
+ {INFF_E_SET_SSID, "SET_SSID"},
+ {INFF_E_JOIN, "JOIN"},
+ {INFF_E_START, "START"},
+ {INFF_E_AUTH, "AUTH"},
+ {INFF_E_AUTH_IND, "AUTH_IND"},
+ {INFF_E_DEAUTH, "DEAUTH"},
+ {INFF_E_DEAUTH_IND, "DEAUTH_IND"},
+ {INFF_E_ASSOC, "ASSOC"},
+ {INFF_E_ASSOC_IND, "ASSOC_IND"},
+ {INFF_E_REASSOC, "REASSOC"},
+ {INFF_E_REASSOC_IND, "REASSOC_IND"},
+ {INFF_E_DISASSOC, "DISASSOC"},
+ {INFF_E_DISASSOC_IND, "DISASSOC_IND"},
+ {INFF_E_QUIET_START, "QUIET_START"},
+ {INFF_E_QUIET_END, "QUIET_END"},
+ {INFF_E_BEACON_RX, "BEACON_RX"},
+ {INFF_E_LINK, "LINK"},
+ {INFF_E_MIC_ERROR, "MIC_ERROR"},
+ {INFF_E_NDIS_LINK, "NDIS_LINK"},
+ {INFF_E_ROAM, "ROAM"},
+ {INFF_E_TXFAIL, "TXFAIL"},
+ {INFF_E_PMKID_CACHE, "PMKID_CACHE"},
+ {INFF_E_RETROGRADE_TSF, "RETROGRADE_TSF"},
+ {INFF_E_PRUNE, "PRUNE"},
+ {INFF_E_AUTOAUTH, "AUTOAUTH"},
+ {INFF_E_EAPOL_MSG, "EAPOL_MSG"},
+ {INFF_E_SCAN_COMPLETE, "SCAN_COMPLETE"},
+ {INFF_E_ADDTS_IND, "ADDTS_IND"},
+ {INFF_E_DELTS_IND, "DELTS_IND"},
+ {INFF_E_BCNSENT_IND, "BCNSENT_IND"},
+ {INFF_E_BCNRX_MSG, "BCNRX_MSG"},
+ {INFF_E_BCNLOST_MSG, "BCNLOST_MSG"},
+ {INFF_E_ROAM_PREP, "ROAM_PREP"},
+ {INFF_E_RESET_COMPLETE, "RESET_COMPLETE"},
+ {INFF_E_JOIN_START, "JOIN_START"},
+ {INFF_E_ROAM_START, "ROAM_START"},
+ {INFF_E_ASSOC_START, "ASSOC_START"},
+ {INFF_E_IBSS_ASSOC, "IBSS_ASSOC"},
+ {INFF_E_RADIO, "RADIO"},
+ {INFF_E_PSM_WATCHDOG, "PSM_WATCHDOG"},
+ {INFF_E_PROBREQ_MSG, "PROBREQ_MSG"},
+ {INFF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"},
+ {INFF_E_PSK_SUP, "PSK_SUP"},
+ {INFF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"},
+ {INFF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"},
+ {INFF_E_ICV_ERROR, "ICV_ERROR"},
+ {INFF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"},
+ {INFF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"},
+ {INFF_E_TRACE, "TRACE"},
+ {INFF_E_IF, "IF"},
+ {INFF_E_RSSI, "RSSI"},
+ {INFF_E_EXTLOG_MSG, "EXTLOG_MSG"},
+ {INFF_E_ACTION_FRAME, "ACTION_FRAME"},
+ {INFF_E_ACTION_FRAME_TX_COMPLETE, "ACTION_FRAME_TX_COMPLETE"},
+ {INFF_E_PRE_ASSOC_IND, "PRE_ASSOC_IND"},
+ {INFF_E_PRE_REASSOC_IND, "PRE_REASSOC_IND"},
+ {INFF_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED"},
+ {INFF_E_AP_STARTED, "AP_STARTED"},
+ {INFF_E_DFS_AP_STOP, "DFS_AP_STOP"},
+ {INFF_E_DFS_AP_RESUME, "DFS_AP_RESUME"},
+ {INFF_E_ESCAN_RESULT, "ESCAN_RESULT"},
+ {INFF_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "ACTION_FRAME_OFF_CHAN_COMPLETE"},
+ {INFF_E_PROBERESP_MSG, "PROBERESP_MSG"},
+ {INFF_E_PROBEREQ_MSG, "PROBEREQ_MSG"},
+ {INFF_E_DCS_REQUEST, "DCS_REQUEST"},
+ {INFF_E_FIFO_CREDIT_MAP, "FIFO_CREDIT_MAP"},
+ {INFF_E_ACTION_FRAME_RX_COMPLETE, "ACTION_FRAME_RX_COMPLETE"},
+ {INFF_E_SA_COMPLETE_IND, "SA_COMPLETE_IND"},
+ {INFF_E_ASSOC_REQ_IE, "ASSOC_REQ_IE"},
+ {INFF_E_ASSOC_RESP_IE, "ASSOC_RESP_IE"},
+ {INFF_E_BCMC_CREDIT_SUPPORT, "BCMC_CREDIT_SUPPORT"},
+ {INFF_E_EXT_AUTH_REQ, "EXT_AUTH_REQ"},
+ {INFF_E_EXT_AUTH_FRAME_RX, "EXT_AUTH_FRAME_RX"},
+ {INFF_E_MGMT_FRAME_TXSTATUS, "MGMT_FRAME_TXSTATUS"},
+ {INFF_E_MGMT_FRAME_OFF_CHAN_COMPLETE, "MGMT_FRAME_OFF_CHAN_COMPLETE"},
+ {INFF_E_EXT_ASSOC_FRAME_RX, "EXT_ASSOC_FRAME_RX"},
+};
+
+/**
+ * inff_fwevt_name() - returns name for given event code.
+ *
+ * @code: code to lookup.
+ */
+const char *
+inff_fwevt_name(enum inff_fwevt_code code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fwevt_names); i++) {
+ if (fwevt_names[i].code == code)
+ return fwevt_names[i].name;
+ }
+ return "unknown";
+}
+#else
+const char *
+inff_fwevt_name(enum inff_fwevt_code code)
+{
+ return "nodebug";
+}
+#endif
+
+/**
+ * inff_fwevt_queue_event() - create and queue event.
+ *
+ * @fwevt: firmware event handling info.
+ * @event: event queue entry.
+ */
+static void
+inff_fwevt_queue_event(struct inff_fwevt_info *fwevt,
+ struct inff_fwevt_queue_item *event)
+{
+ ulong flags;
+
+ spin_lock_irqsave(&fwevt->evt_q_lock, flags);
+ list_add_tail(&event->q, &fwevt->event_q);
+ spin_unlock_irqrestore(&fwevt->evt_q_lock, flags);
+ schedule_work(&fwevt->event_work);
+}
+
+/**
+ * inff_fwevt_dequeue_event() - get event from the queue.
+ *
+ * @fwevt: firmware event handling info.
+ */
+static struct inff_fwevt_queue_item *
+inff_fwevt_dequeue_event(struct inff_fwevt_info *fwevt)
+{
+ struct inff_fwevt_queue_item *event = NULL;
+ ulong flags;
+
+ spin_lock_irqsave(&fwevt->evt_q_lock, flags);
+ if (!list_empty(&fwevt->event_q)) {
+ event = list_first_entry(&fwevt->event_q,
+ struct inff_fwevt_queue_item, q);
+ list_del(&event->q);
+ }
+ spin_unlock_irqrestore(&fwevt->evt_q_lock, flags);
+
+ return event;
+}
+
+/**
+ * inff_fwevt_event_worker() - firmware event worker.
+ *
+ * @work: worker object.
+ */
+static void
+inff_fwevt_event_worker(struct work_struct *work)
+{
+ struct inff_pub *drvr;
+ struct inff_if *ifp;
+ struct inff_fwevt_info *fwevt;
+ struct inff_fwevt_queue_item *event;
+ struct inff_event_msg_be *emsg_be;
+ struct inff_event_msg emsg;
+
+ fwevt = container_of(work, struct inff_fwevt_info, event_work);
+ drvr = container_of(fwevt, struct inff_pub, fwevt);
+
+ while ((event = inff_fwevt_dequeue_event(fwevt))) {
+ inff_dbg(DEVEVT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
+ inff_fwevt_name(event->code), event->code,
+ event->emsg.ifidx, event->emsg.bsscfgidx,
+ event->emsg.addr);
+ if (event->emsg.bsscfgidx >= INFF_MAX_IFS) {
+ iphy_err(drvr, "invalid bsscfg index: %u\n", event->emsg.bsscfgidx);
+ goto event_free;
+ }
+
+ /* convert event message */
+ emsg_be = &event->emsg;
+ emsg.version = be16_to_cpu(emsg_be->version);
+ emsg.flags = be16_to_cpu(emsg_be->flags);
+ emsg.event_code = event->code;
+ emsg.status = be32_to_cpu(emsg_be->status);
+ emsg.reason = be32_to_cpu(emsg_be->reason);
+ emsg.auth_type = be32_to_cpu(emsg_be->auth_type);
+ emsg.datalen = be32_to_cpu(emsg_be->datalen);
+ memcpy(emsg.addr, emsg_be->addr, ETH_ALEN);
+ memcpy(emsg.ifname, emsg_be->ifname, sizeof(emsg.ifname));
+ emsg.ifidx = emsg_be->ifidx;
+ emsg.bsscfgidx = emsg_be->bsscfgidx;
+
+ inff_dbg(DEVEVT, " version %u flags %u status %u reason %u\n",
+ emsg.version, emsg.flags, emsg.status, emsg.reason);
+ inff_dbg_hex_dump(INFF_MSGLVL_ON(DEVEVT), event->data,
+ min_t(u32, emsg.datalen, 64),
+ "event payload, len=%d\n", emsg.datalen);
+
+ ifp = drvr->iflist[emsg.bsscfgidx];
+ if (!ifp)
+ ifp = inff_get_ifp(drvr, 0);
+
+ /* Call the registered event handler */
+ if (fwevt->evt_handler[event->code]) {
+ if (fwevt->evt_handler[event->code](ifp, &emsg, event->data))
+ iphy_err(drvr, "event handler failed (%d)\n",
+ event->code);
+ } else {
+ iphy_err(drvr, "unhandled event %d ignored\n", event->code);
+ }
+event_free:
+ kfree(event);
+ }
+}
+
+/**
+ * inff_fwevt_attach() - initialize firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void
+inff_fwevt_attach(struct inff_pub *drvr)
+{
+ struct inff_fwevt_info *fwevt = &drvr->fwevt;
+
+ INIT_WORK(&fwevt->event_work, inff_fwevt_event_worker);
+ spin_lock_init(&fwevt->evt_q_lock);
+ INIT_LIST_HEAD(&fwevt->event_q);
+}
+
+/**
+ * inff_fwevt_detach() - cleanup firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void
+inff_fwevt_detach(struct inff_pub *drvr)
+{
+ struct inff_fwevt_info *fwevt = &drvr->fwevt;
+
+ /* cancel the worker if initialized */
+ if (fwevt->event_work.func) {
+ cancel_work_sync(&fwevt->event_work);
+ WARN_ON(!list_empty(&fwevt->event_q));
+ memset(fwevt->evt_handler, 0, sizeof(fwevt->evt_handler));
+ }
+}
+
+/**
+ * inff_fwevt_register() - register handler for given event code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ * @handler: handler for the given event code.
+ */
+int
+inff_fwevt_register(struct inff_pub *drvr, enum inff_fwevt_code code,
+ inff_fwevt_handler_t handler)
+{
+ if (drvr->fwevt.evt_handler[code]) {
+ iphy_err(drvr, "event code %d already registered\n", code);
+ return -ENOSPC;
+ }
+ drvr->fwevt.evt_handler[code] = handler;
+ inff_dbg(TRACE, "event handler registered for %s\n",
+ inff_fwevt_name(code));
+ return 0;
+}
+
+/**
+ * inff_fwevt_unregister() - remove handler for given code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ */
+void
+inff_fwevt_unregister(struct inff_pub *drvr,
+ enum inff_fwevt_code code)
+{
+ inff_dbg(TRACE, "event handler cleared for %s\n",
+ inff_fwevt_name(code));
+ drvr->fwevt.evt_handler[code] = NULL;
+}
+
+/**
+ * inff_fwevt_activate_events() - enables firmware events registered.
+ *
+ * @ifp: primary interface object.
+ */
+int
+inff_fwevt_activate_events(struct inff_if *ifp)
+{
+ struct inff_pub *drvr = ifp->drvr;
+ int i, err;
+ struct eventmsgs_ext *eventmask_msg;
+ u32 msglen;
+
+ msglen = EVENTMSGS_EXT_STRUCT_SIZE + INFF_EVENTING_MASK_LEN;
+ eventmask_msg = kzalloc(msglen, GFP_KERNEL);
+ if (!eventmask_msg)
+ return -ENOMEM;
+
+ for (i = 0; i < INFF_E_LAST; i++) {
+ if (ifp->drvr->fwevt.evt_handler[i]) {
+ inff_dbg(DEVEVT, "enable event %s\n",
+ inff_fwevt_name(i));
+ setbit(eventmask_msg->mask, i);
+ }
+ }
+
+ /* want to handle IF event as well */
+ inff_dbg(DEVEVT, "enable event IF\n");
+ setbit(eventmask_msg->mask, INFF_E_IF);
+
+ eventmask_msg->ver = EVENTMSGS_VER;
+ eventmask_msg->command = EVENTMSGS_SET_MASK;
+ eventmask_msg->len = INFF_EVENTING_MASK_LEN;
+
+ err = inff_fwcmd_iovar_data_set(ifp, "event_msgs_ext", eventmask_msg,
+ msglen);
+ if (!err)
+ goto end;
+
+ err = inff_fwcmd_iovar_data_set(ifp, "event_msgs", eventmask_msg->mask,
+ INFF_EVENTING_MASK_LEN);
+ if (err)
+ iphy_err(drvr, "Set event_msgs error (%d)\n", err);
+
+end:
+ kfree(eventmask_msg);
+ return err;
+}
+
+/**
+ * inff_fwevt_process_event() - process skb as firmware event.
+ *
+ * @drvr: driver information object.
+ * @event_packet: event packet to process.
+ * @packet_len: length of the packet
+ * @gfp: memory allocation flags.
+ *
+ * If the packet buffer contains a firmware event message it will
+ * dispatch the event to a registered handler (using worker).
+ */
+void
+inff_fwevt_process_event(struct inff_pub *drvr,
+ struct inff_event *event_packet,
+ u32 packet_len, gfp_t gfp)
+{
+ enum inff_fwevt_code code;
+ struct inff_fwevt_info *fwevt = &drvr->fwevt;
+ struct inff_fwevt_queue_item *event;
+ void *data;
+ u32 datalen;
+
+ /* get event info */
+ code = get_unaligned_be32(&event_packet->msg.event_type);
+ datalen = get_unaligned_be32(&event_packet->msg.datalen);
+ data = &event_packet[1];
+
+ if (code >= INFF_E_LAST)
+ return;
+
+ if (code != INFF_E_IF && !fwevt->evt_handler[code])
+ return;
+
+ if (datalen > INFF_DCMD_MAXLEN ||
+ datalen + sizeof(*event_packet) > packet_len)
+ return;
+
+ event = kzalloc_flex(*event, data, datalen, gfp);
+ if (!event)
+ return;
+
+ event->datalen = datalen;
+ event->code = code;
+ event->ifidx = event_packet->msg.ifidx;
+
+ /* use memcpy to get aligned event message */
+ memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
+ memcpy(event->data, data, datalen);
+ memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
+
+ inff_fwevt_queue_event(fwevt, event);
+}
+
+void
+inff_fwevt_process_skb(struct inff_pub *drvr, struct sk_buff *skb, u16 stype,
+ gfp_t gfp)
+{
+ struct inff_event *event_packet;
+ u16 subtype, usr_stype;
+
+ /* only process events when protocol matches */
+ if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
+ return;
+
+ if ((skb->len + ETH_HLEN) < sizeof(*event_packet))
+ return;
+
+ event_packet = (struct inff_event *)skb_mac_header(skb);
+
+ /* check subtype if needed */
+ if (unlikely(stype)) {
+ subtype = get_unaligned_be16(&event_packet->hdr.subtype);
+ if (subtype != stype)
+ return;
+ }
+
+ if (memcmp(INF_OUI, &event_packet->hdr.oui[0],
+ sizeof(event_packet->hdr.oui)))
+ return;
+
+ /* final match on usr_subtype */
+ usr_stype = get_unaligned_be16(&event_packet->hdr.usr_subtype);
+ if (usr_stype != INFILCP_INF_SUBTYPE_EVENT)
+ return;
+
+ inff_fwevt_process_event(drvr, event_packet, skb->len + ETH_HLEN, gfp);
+}
+
+static s32
+inff_notify_vif_event(struct inff_if *ifp, const struct inff_event_msg *e, void *data)
+{
+ struct inff_pub *drvr = ifp->drvr;
+ struct inff_cfg80211_info *cfg = drvr->config;
+ struct inff_if_event *ifevent = (struct inff_if_event *)data;
+ struct inff_cfg80211_vif_event *event = &cfg->vif_event;
+ struct inff_cfg80211_vif *vif;
+ enum nl80211_iftype iftype = NL80211_IFTYPE_UNSPECIFIED;
+ int err = 0;
+
+ inff_dbg(DEVEVT, "%s (%d) action: %u ifidx: %u bsscfgidx: %u flags: %u role: %u\n",
+ inff_fwevt_name(e->event_code), e->event_code,
+ ifevent->action, ifevent->ifidx, ifevent->bsscfgidx,
+ ifevent->flags, ifevent->role);
+
+ if (ifevent->ifidx >= INFF_MAX_IFS) {
+ iphy_err(drvr, "Invalid interface index: %u\n", ifevent->ifidx);
+ return -EINVAL;
+ }
+
+ spin_lock(&event->vif_event_lock);
+ event->action = ifevent->action;
+ vif = event->vif;
+
+ switch (ifevent->action) {
+ case INFF_E_IF_ADD:
+ inff_dbg(DEVEVT, "adding %s (%pM) interface\n", e->ifname,
+ e->addr);
+
+ switch (ifevent->role) {
+ case INFF_E_IF_ROLE_STA:
+ iftype = NL80211_IFTYPE_STATION;
+ break;
+ case INFF_E_IF_ROLE_AP:
+ iftype = NL80211_IFTYPE_AP;
+ break;
+ default:
+ iphy_err(drvr, "Invalid interface role: %d\n", ifevent->role);
+ spin_unlock(&event->vif_event_lock);
+ return -EINVAL;
+ }
+
+ if (ifevent->bsscfgidx >= INFF_MAX_IFS) {
+ iphy_err(drvr, "invalid bsscfg index: %u\n",
+ ifevent->bsscfgidx);
+ spin_unlock(&event->vif_event_lock);
+ return -EINVAL;
+ }
+
+ ifp = drvr->iflist[ifevent->bsscfgidx];
+ if (ifp) {
+ if (ifevent->bsscfgidx == 0) {
+ inff_dbg(INFO,
+ "ignore IF ADD event for existing primary interface %s\n",
+ ifp->ndev->name);
+ spin_unlock(&event->vif_event_lock);
+ return 0;
+ }
+
+ /*
+ * Remove the corresponding existing interface, to add it again,
+ * incase if its INFF_E_IF_DEL event was missed earlier.
+ */
+ iphy_err(drvr,
+ "netdev:%s already exists, removing to add it again\n",
+ ifp->ndev->name);
+ inff_net_del_if(drvr, ifp, false);
+ }
+
+ ifp = inff_net_add_if(drvr, ifevent->bsscfgidx, ifevent->ifidx,
+ e->ifname, e->addr, iftype);
+ if (IS_ERR_OR_NULL(ifp)) {
+ iphy_err(drvr, "interface (role: %d) addition error (%ld)\n",
+ ifevent->role, PTR_ERR(ifp));
+ spin_unlock(&event->vif_event_lock);
+ return PTR_ERR(ifp);
+ }
+
+ if (!vif) {
+ spin_unlock(&event->vif_event_lock);
+ /* Interface Add event may not be upon user request */
+ vif = inff_alloc_vif(cfg, iftype);
+ if (IS_ERR(vif)) {
+ inff_net_del_if(drvr, ifp, false);
+ return PTR_ERR(vif);
+ }
+ }
+
+ ifp->vif = vif;
+ vif->ifp = ifp;
+
+ if (ifp->ndev) {
+ vif->wdev.netdev = ifp->ndev;
+ ifp->ndev->ieee80211_ptr = &vif->wdev;
+ SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
+ }
+
+ inff_proto_add_if(drvr, ifp);
+
+ spin_unlock(&event->vif_event_lock);
+ if (inff_vif_event_armed(cfg)) {
+ wake_up(&event->vif_wq);
+ break;
+ }
+
+ if (ifp->ndev) {
+ /* Interface Add event may not be upon user request */
+ err = inff_net_attach(ifp, false);
+ if (err) {
+ inff_err("netdevice register failed with err:%d\n",
+ err);
+ inff_net_del_if(drvr, ifp, false);
+ }
+ }
+
+ break;
+ case INFF_E_IF_DEL:
+ inff_dbg(DEVEVT, "deleting %s (%pM) interface\n", e->ifname,
+ e->addr);
+
+ spin_unlock(&event->vif_event_lock);
+ if (inff_vif_event_armed(cfg)) {
+ wake_up(&event->vif_wq);
+ break;
+ }
+
+ /* Interface Delete event may not be upon user request */
+ if (!ifp || ifp->bsscfgidx != ifevent->bsscfgidx)
+ break;
+
+ inff_net_del_if(drvr, ifp, false);
+
+ break;
+ case INFF_E_IF_CHANGE:
+ inff_dbg(DEVEVT, "changing %s (%pM) interface\n", e->ifname,
+ e->addr);
+
+ inff_proto_reset_if(drvr, ifp);
+
+ spin_unlock(&event->vif_event_lock);
+ if (inff_vif_event_armed(cfg))
+ wake_up(&event->vif_wq);
+
+ break;
+ default:
+ err = -EINVAL;
+ spin_unlock(&event->vif_event_lock);
+ break;
+ }
+
+ return err;
+}
+
+void inff_fwevt_register_handlers(struct inff_cfg80211_info *cfg)
+{
+ inff_fwevt_register(cfg->pub, INFF_E_IF,
+ inff_notify_vif_event);
+}
+
+/*
+ * inff_cpevt_dequeue_event() - get event from the queue.
+ *
+ * @evi: event handling info.
+ * @event_q: event queue.
+ */
+static struct inff_cpevt_queue_item *
+inff_cpevt_dequeue_event(struct inff_cpevt_info *evi, struct list_head *event_q)
+{
+ struct inff_cpevt_queue_item *event = NULL;
+ ulong flags;
+
+ spin_lock_irqsave(&evi->lock, flags);
+ if (!list_empty(event_q)) {
+ event = list_first_entry(event_q,
+ struct inff_cpevt_queue_item, list);
+ list_del(&event->list);
+ }
+ spin_unlock_irqrestore(&evi->lock, flags);
+
+ return event;
+}
+
+/*
+ * inff_cpevt_queue_event() - queue event.
+ * @evi: event handling info.
+ * @event: event item.
+ * @event_q: event queue.
+ */
+static void
+inff_cpevt_queue_event(struct inff_cpevt_info *evi,
+ struct inff_cpevt_queue_item *event,
+ struct list_head *event_q)
+{
+ ulong flags;
+
+ spin_lock_irqsave(&evi->lock, flags);
+ list_add_tail(&event->list, event_q);
+ spin_unlock_irqrestore(&evi->lock, flags);
+}
+
+static int
+inff_cpevt_alloc_buf(struct inff_cpevt_info *evi)
+{
+ struct inff_cpevt_queue_item *event_item;
+ u8 i;
+
+ INIT_LIST_HEAD(&evi->idle_q);
+ INIT_LIST_HEAD(&evi->wait_q);
+ INIT_LIST_HEAD(&evi->event_q);
+ INIT_LIST_HEAD(&evi->monitor_q);
+ spin_lock_init(&evi->lock);
+
+ for (i = 0; i < EVENT_MAX_RX_BUF; i++) {
+ event_item = kzalloc_obj(*event_item);
+ if (!event_item)
+ return -ENODATA;
+
+ INIT_LIST_HEAD(&event_item->list);
+ memset(&event_item->event, 0, sizeof(event_item->event));
+
+ spin_lock(&evi->lock);
+ list_add_tail(&event_item->list, &evi->idle_q);
+ spin_unlock(&evi->lock);
+ }
+
+ return 0;
+}
+
+static void
+inff_cpevt_free_buf(struct list_head *q, const char name[])
+{
+ struct inff_cpevt_queue_item *event_item;
+ struct inff_cpevt_queue_item *next = NULL;
+ u32 count = 0;
+
+ list_for_each_entry_safe(event_item, next, q, list) {
+ list_del(&event_item->list);
+ kfree(event_item);
+ count++;
+ }
+ inff_dbg(INFO, "%s Q: free pkt count %d\n", name, count);
+}
+
+static int
+inff_notify_cpevt_scan(struct inff_pub *drvr, struct inff_cpevt *event)
+{
+ struct inff_cpevt_scan *scan_ev = NULL;
+
+ if (event->version != INFF_CP_SCAN_EVENT_VER) {
+ inff_err("version (%d) != %d\n", event->version, INFF_CP_SCAN_EVENT_VER);
+ return -ENODATA;
+ }
+
+ if (event->len != sizeof(*scan_ev)) {
+ inff_err("len %d != scan_event %ld\n", event->len, sizeof(*scan_ev));
+ return -ENODATA;
+ }
+
+ scan_ev = (struct inff_cpevt_scan *)event->data;
+ return inff_cp_scan_event_handler(drvr, scan_ev);
+}
+
+static int
+inff_cpevt_handler(struct inff_pub *drvr, struct inff_cpevt *e)
+{
+ int ret = 0;
+
+ switch (e->type) {
+ case INFF_CP_E_SCAN:
+ ret = inff_notify_cpevt_scan(drvr, e);
+ break;
+ default:
+ inff_err("unsupported event: %d\n", e->type);
+ /* driver bypass this event, keep forward to user */
+ break;
+ }
+
+ if (ret)
+ inff_err("handle event code (%d) failed\n", e->type);
+ return ret;
+}
+
+/*
+ * inff_cpevt_worker() - event worker.
+ *
+ * @work: worker object.
+ */
+static void
+inff_cpevt_worker(struct work_struct *work)
+{
+ struct inff_pub *drvr;
+ struct inff_cpevt_info *evi;
+ struct inff_cpevt_queue_item *event_item = NULL;
+
+ evi = container_of(work, struct inff_cpevt_info, event_work);
+ drvr = container_of(evi, struct inff_pub, evi);
+
+ while ((event_item = inff_cpevt_dequeue_event(evi, &evi->wait_q))) {
+ inff_cpevt_handler(drvr, &event_item->event);
+ inff_cpevt_queue_event(evi, event_item, &evi->idle_q);
+ }
+}
+
+/*
+ * inff_cpevt_attach() - initialize event handling.
+ * @drvr: driver information object.
+ */
+int
+inff_cpevt_attach(struct inff_pub *drvr)
+{
+ struct inff_cpevt_info *evi = &drvr->evi;
+
+ if (inff_cpevt_alloc_buf(evi)) {
+ inff_err("Failed to alloc event buffer\n");
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&evi->event_work, inff_cpevt_worker);
+
+ return 0;
+}
+
+/*
+ * inff_cpevt_detach() - cleanup event handling.
+ * @drvr: driver information object.
+ */
+void
+inff_cpevt_detach(struct inff_pub *drvr)
+{
+ struct inff_cpevt_info *evi = &drvr->evi;
+
+ /* cancel the worker if initialized */
+ if (evi->event_work.func)
+ cancel_work_sync(&evi->event_work);
+
+ spin_lock(&evi->lock);
+
+ inff_cpevt_free_buf(&evi->idle_q, "idle");
+ inff_cpevt_free_buf(&evi->wait_q, "wait");
+ inff_cpevt_free_buf(&evi->event_q, "event");
+ inff_cpevt_free_buf(&evi->monitor_q, "monitor");
+
+ spin_unlock(&evi->lock);
+}
+
+/*
+ * inff_cpevt_process_skb() - process skb as event.
+ * @drvr: driver information object.
+ * @pkt: event packet to process.
+ * @inirq: in irq.
+ * Dispatch the event packet to worker.
+ */
+void
+inff_cpevt_process_skb(struct inff_pub *drvr, struct sk_buff *pkt)
+{
+ struct inff_cpevt_info *evi = &drvr->evi;
+ struct inff_cpevt_queue_item *event_item;
+
+ if (pkt->len > sizeof(struct inff_cpevt)) {
+ inff_err("event len (%d) > %ld\n", pkt->len, sizeof(struct inff_cpevt));
+ return;
+ }
+
+ event_item = inff_cpevt_dequeue_event(evi, &evi->idle_q);
+ if (!event_item) {
+ inff_err("no buffer in idle q\n");
+ return;
+ }
+
+ memset(&event_item->event, 0, sizeof(event_item->event));
+ memcpy(&event_item->event, pkt->data, pkt->len);
+
+ inff_dbg_hex_dump(INFF_MSGLVL_ON(DEVEVT), pkt->data,
+ min_t(u32, pkt->len, 64),
+ "event payload, len=%d\n", pkt->len);
+
+ inff_cpevt_queue_event(evi, event_item, &evi->wait_q);
+
+ schedule_work(&evi->event_work);
+}
diff --git a/drivers/net/wireless/infineon/inffmac/dev_evt.h b/drivers/net/wireless/infineon/inffmac/dev_evt.h
new file mode 100644
index 000000000000..cc9d4384b1b8
--- /dev/null
+++ b/drivers/net/wireless/infineon/inffmac/dev_evt.h
@@ -0,0 +1,447 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Copyright (c) 2025-2026, Infineon Technologies AG, or an affiliate of Infineon Technologies AG.
+ * All rights reserved.
+ */
+
+#ifndef INFF_DEV_EVT_H
+#define INFF_DEV_EVT_H
+
+#include <linux/unaligned.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+
+#define INF_OUI "\x00\x03\x19"
+
+/* formward declarations */
+struct inff_pub;
+struct inff_if;
+struct inff_cfg80211_info;
+
+/* list of firmware events */
+/* firmware event codes sent by the dongle */
+enum inff_fwevt_code {
+ INFF_E_SET_SSID = 0,
+ INFF_E_JOIN = 1,
+ INFF_E_START = 2,
+ INFF_E_AUTH = 3,
+ INFF_E_AUTH_IND = 4,
+ INFF_E_DEAUTH = 5,
+ INFF_E_DEAUTH_IND = 6,
+ INFF_E_ASSOC = 7,
+ INFF_E_ASSOC_IND = 8,
+ INFF_E_REASSOC = 9,
+ INFF_E_REASSOC_IND = 10,
+ INFF_E_DISASSOC = 11,
+ INFF_E_DISASSOC_IND = 12,
+ INFF_E_QUIET_START = 13,
+ INFF_E_QUIET_END = 14,
+ INFF_E_BEACON_RX = 15,
+ INFF_E_LINK = 16,
+ INFF_E_MIC_ERROR = 17,
+ INFF_E_NDIS_LINK = 18,
+ INFF_E_ROAM = 19,
+ INFF_E_TXFAIL = 20,
+ INFF_E_PMKID_CACHE = 21,
+ INFF_E_RETROGRADE_TSF = 22,
+ INFF_E_PRUNE = 23,
+ INFF_E_AUTOAUTH = 24,
+ INFF_E_EAPOL_MSG = 25,
+ INFF_E_SCAN_COMPLETE = 26,
+ INFF_E_ADDTS_IND = 27,
+ INFF_E_DELTS_IND = 28,
+ INFF_E_BCNSENT_IND = 29,
+ INFF_E_BCNRX_MSG = 30,
+ INFF_E_BCNLOST_MSG = 31,
+ INFF_E_ROAM_PREP = 32,
+ INFF_E_RESET_COMPLETE = 35,
+ INFF_E_JOIN_START = 36,
+ INFF_E_ROAM_START = 37,
+ INFF_E_ASSOC_START = 38,
+ INFF_E_IBSS_ASSOC = 39,
+ INFF_E_RADIO = 40,
+ INFF_E_PSM_WATCHDOG = 41,
+ INFF_E_PROBREQ_MSG = 44,
+ INFF_E_SCAN_CONFIRM_IND = 45,
+ INFF_E_PSK_SUP = 46,
+ INFF_E_COUNTRY_CODE_CHANGED = 47,
+ INFF_E_EXCEEDED_MEDIUM_TIME = 48,
+ INFF_E_ICV_ERROR = 49,
+ INFF_E_UNICAST_DECODE_ERROR = 50,
+ INFF_E_MULTICAST_DECODE_ERROR = 51,
+ INFF_E_TRACE = 52,
+ INFF_E_IF = 54,
+ INFF_E_RSSI = 56,
+ INFF_E_EXTLOG_MSG = 58,
+ INFF_E_ACTION_FRAME = 59,
+ INFF_E_ACTION_FRAME_TX_COMPLETE = 60,
+ INFF_E_PRE_ASSOC_IND = 61,
+ INFF_E_PRE_REASSOC_IND = 62,
+ INFF_E_CHANNEL_ADOPTED = 63,
+ INFF_E_AP_STARTED = 64,
+ INFF_E_DFS_AP_STOP = 65,
+ INFF_E_DFS_AP_RESUME = 66,
+ INFF_E_ESCAN_RESULT = 69,
+ INFF_E_ACTION_FRAME_OFF_CHAN_COMPLETE = 70,
+ INFF_E_PROBERESP_MSG = 71,
+ INFF_E_PROBEREQ_MSG = 72,
+ INFF_E_DCS_REQUEST = 73,
+ INFF_E_FIFO_CREDIT_MAP = 74,
+ INFF_E_ACTION_FRAME_RX_COMPLETE = 75,
+ INFF_E_SA_COMPLETE_IND = 80,
+ INFF_E_ASSOC_REQ_IE = 87,
+ INFF_E_ASSOC_RESP_IE = 88,
+ INFF_E_BCMC_CREDIT_SUPPORT = 127,
+ INFF_E_EXT_AUTH_REQ = 187,
+ INFF_E_EXT_AUTH_FRAME_RX = 188,
+ INFF_E_MGMT_FRAME_TXSTATUS = 189,
+ INFF_E_MGMT_FRAME_OFF_CHAN_COMPLETE = 190,
+ INFF_E_EXT_ASSOC_FRAME_RX = 196,
+ /* this determines event mask length which must match
+ * minimum length check in device firmware so it is
+ * hard-coded here.
+ */
+ INFF_E_LAST = 203
+};
+
+/* list of CP events */
+/* CP event codes sent by the dongle */
+enum inff_cpevt_code {
+ INFF_CP_E_NW = 0,
+ INFF_CP_E_SCAN = 1
+};
+
+#define INFF_EVENTING_MASK_LEN DIV_ROUND_UP(INFF_E_LAST, 8)
+
+/* flags field values in struct inff_event_msg */
+#define INFF_EVENT_MSG_LINK 0x01
+#define INFF_EVENT_MSG_FLUSHTXQ 0x02
+#define INFF_EVENT_MSG_GROUP 0x04
+
+/* status field values in struct inff_event_msg */
+#define INFF_E_STATUS_SUCCESS 0
+#define INFF_E_STATUS_FAIL 1
+#define INFF_E_STATUS_TIMEOUT 2
+#define INFF_E_STATUS_NO_NETWORKS 3
+#define INFF_E_STATUS_ABORT 4
+#define INFF_E_STATUS_NO_ACK 5
+#define INFF_E_STATUS_UNSOLICITED 6
+#define INFF_E_STATUS_ATTEMPT 7
+#define INFF_E_STATUS_PARTIAL 8
+#define INFF_E_STATUS_NEWSCAN 9
+#define INFF_E_STATUS_NEWASSOC 10
+#define INFF_E_STATUS_11HQUIET 11
+#define INFF_E_STATUS_SUPPRESS 12
+#define INFF_E_STATUS_NOCHANS 13
+#define INFF_E_STATUS_CS_ABORT 15
+#define INFF_E_STATUS_ERROR 16
+
+/* status field values for PSK_SUP event */
+#define INFF_E_STATUS_FWSUP_WAIT_M1 4
+#define INFF_E_STATUS_FWSUP_PREP_M2 5
+#define INFF_E_STATUS_FWSUP_COMPLETED 6
+#define INFF_E_STATUS_FWSUP_TIMEOUT 7
+#define INFF_E_STATUS_FWSUP_WAIT_M3 8
+#define INFF_E_STATUS_FWSUP_PREP_M4 9
+#define INFF_E_STATUS_FWSUP_WAIT_G1 10
+#define INFF_E_STATUS_FWSUP_PREP_G2 11
+
+/* reason field values in struct inff_event_msg */
+/* roam reason codes */
+#define INFF_ROAM_E_REASON_INITIAL_ASSOC 0 /* initial assoc */
+#define INFF_ROAM_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */
+#define INFF_ROAM_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */
+#define INFF_ROAM_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */
+#define INFF_ROAM_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */
+#define INFF_ROAM_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */
+#define INFF_ROAM_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */
+#define INFF_ROAM_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */
+#define INFF_ROAM_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */
+#define INFF_ROAM_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */
+#define INFF_ROAM_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */
+#define INFF_ROAM_E_REASON_BSSTRANS_REQ 11 /* roamed due to BSS Transition request by AP */
+#define INFF_ROAM_E_REASON_LOW_RSSI_CU 12 /* roamed due to low RSSI and Channel Usage */
+#define INFF_ROAM_E_REASON_RADAR_DETECTED 13 /* roamed due to radar detection by STA */
+#define INFF_ROAM_E_REASON_CSA 14 /* roamed due to CSA from AP */
+#define INFF_ROAM_E_REASON_ESTM_LOW 15 /* roamed due to ESTM low tput */
+#define INFF_ROAM_E_REASON_LAST 16
+
+#define INFF_E_REASON_LINK_BSSCFG_DIS 4
+#define INFF_E_REASON_FAST_ROAM_FAILED 5
+#define INFF_E_REASON_DIRECTED_ROAM 6
+#define INFF_E_REASON_TSPEC_REJECTED 7
+#define INFF_E_REASON_BETTER_AP 8
+
+/* reason field values for PSK_SUP event */
+#define INFF_E_REASON_FWSUP_OTHER 0
+#define INFF_E_REASON_FWSUP_DECRYPT_KEY_DATA 1
+#define INFF_E_REASON_FWSUP_BAD_UCAST_WEP128 2
+#define INFF_E_REASON_FWSUP_BAD_UCAST_WEP40 3
+#define INFF_E_REASON_FWSUP_UNSUP_KEY_LEN 4
+#define INFF_E_REASON_FWSUP_PW_KEY_CIPHER 5
+#define INFF_E_REASON_FWSUP_MSG3_TOO_MANY_IE 6
+#define INFF_E_REASON_FWSUP_MSG3_IE_MISMATCH 7
+#define INFF_E_REASON_FWSUP_NO_INSTALL_FLAG 8
+#define INFF_E_REASON_FWSUP_MSG3_NO_GTK 9
+#define INFF_E_REASON_FWSUP_GRP_KEY_CIPHER 10
+#define INFF_E_REASON_FWSUP_GRP_MSG1_NO_GTK 11
+#define INFF_E_REASON_FWSUP_GTK_DECRYPT_FAIL 12
+#define INFF_E_REASON_FWSUP_SEND_FAIL 13
+#define INFF_E_REASON_FWSUP_DEAUTH 14
+#define INFF_E_REASON_FWSUP_WPA_PSK_TMO 15
+#define INFF_E_REASON_FWSUP_WPA_PSK_M1_TMO 16
+#define INFF_E_REASON_FWSUP_WPA_PSK_M3_TMO 17
+
+/* action field values for inff_ifevent */
+#define INFF_E_IF_ADD 1
+#define INFF_E_IF_DEL 2
+#define INFF_E_IF_CHANGE 3
+
+/* flag field values for inff_ifevent */
+#define INFF_E_IF_FLAG_NOIF 1
+
+/* role field values for inff_ifevent */
+#define INFF_E_IF_ROLE_STA 0
+#define INFF_E_IF_ROLE_AP 1
+
+/**
+ * definitions for event packet validation.
+ */
+#define INFILCP_INF_SUBTYPE_EVENT 1
+#define INFILCP_SUBTYPE_VENDOR_LONG 32769
+
+/**
+ * struct inff_ethhdr - Infineon specific ether header.
+ *
+ * @subtype: subtype for this packet.
+ * @length: length of appended data.
+ * @version: version indication.
+ * @oui: OUI of this packet.
+ * @usr_subtype: subtype for this OUI.
+ */
+struct inff_ethhdr {
+ __be16 subtype;
+ __be16 length;
+ u8 version;
+ u8 oui[3];
+ __be16 usr_subtype;
+} __packed;
+
+struct inff_event_msg_be {
+ __be16 version;
+ __be16 flags;
+ __be32 event_type;
+ __be32 status;
+ __be32 reason;
+ __be32 auth_type;
+ __be32 datalen;
+ u8 addr[ETH_ALEN];
+ char ifname[IFNAMSIZ];
+ u8 ifidx;
+ u8 bsscfgidx;
+} __packed;
+
+/**
+ * struct inff_event - contents of Infineon event packet.
+ *
+ * @eth: standard ether header.
+ * @hdr: Infineon specific ether header.
+ * @msg: common part of the actual event message.
+ */
+struct inff_event {
+ struct ethhdr eth;
+ struct inff_ethhdr hdr;
+ struct inff_event_msg_be msg;
+} __packed;
+
+#define EVENT_MAX_DATA_LEN 1024
+#define EVENT_MAX_RX_BUF 10
+
+struct inff_cpevt {
+ u16 type;
+ u16 len;
+ u8 version;
+ u8 data[EVENT_MAX_DATA_LEN];
+};
+
+/**
+ * struct inff_event_msg - firmware event message.
+ *
+ * @version: version information.
+ * @flags: event flags.
+ * @event_code: firmware event code.
+ * @status: status information.
+ * @reason: reason code.
+ * @auth_type: authentication type.
+ * @datalen: length of event data buffer.
+ * @addr: ether address.
+ * @ifname: interface name.
+ * @ifidx: interface index.
+ * @bsscfgidx: bsscfg index.
+ */
+struct inff_event_msg {
+ u16 version;
+ u16 flags;
+ u32 event_code;
+ u32 status;
+ u32 reason;
+ s32 auth_type;
+ u32 datalen;
+ u8 addr[ETH_ALEN];
+ char ifname[IFNAMSIZ];
+ u8 ifidx;
+ u8 bsscfgidx;
+};
+
+struct inff_if_event {
+ u8 ifidx;
+ u8 action;
+ u8 flags;
+ u8 bsscfgidx;
+ u8 role;
+};
+
+enum event_msgs_ext_command {
+ EVENTMSGS_NONE = 0,
+ EVENTMSGS_SET_BIT = 1,
+ EVENTMSGS_RESET_BIT = 2,
+ EVENTMSGS_SET_MASK = 3
+};
+
+#define EVENTMSGS_VER 1
+#define EVENTMSGS_EXT_STRUCT_SIZE offsetof(struct eventmsgs_ext, mask[0])
+
+/* len- for SET it would be mask size from the application to the firmware */
+/* for GET it would be actual firmware mask size */
+/* maxgetsize - is only used for GET. indicate max mask size that the */
+/* application can read from the firmware */
+struct eventmsgs_ext {
+ u8 ver;
+ u8 command;
+ u8 len;
+ u8 maxgetsize;
+ u8 mask[];
+};
+
+struct inff_fwevt_roam_reason_name {
+ u32 reason;
+ char *reason_name;
+};
+
+typedef int (*inff_fwevt_handler_t)(struct inff_if *ifp,
+ const struct inff_event_msg *evtmsg,
+ void *data);
+
+/**
+ * struct inff_fwevt_info - firmware event handling information.
+ *
+ * @event_work: event worker.
+ * @evt_q_lock: lock for event queue protection.
+ * @event_q: event queue.
+ * @evt_handler: registered event handlers.
+ */
+struct inff_fwevt_info {
+ struct work_struct event_work;
+ spinlock_t evt_q_lock; /* lock for event queue protection */
+ struct list_head event_q;
+
+ int (*evt_handler[INFF_E_LAST])(struct inff_if *ifp,
+ const struct inff_event_msg *evtmsg,
+ void *data);
+};
+
+/*
+ * struct inff_cpevt_queue_item - event item on event queue.
+ *
+ * @list: list element for queuing.
+ * @event: event specific data part of the event.
+ */
+struct inff_cpevt_queue_item {
+ struct list_head list;
+ struct inff_cpevt event;
+};
+
+/*
+ * struct inff_cpevt_info - event handling information.
+ *
+ * @event_work: event worker.
+ * @event_q_lock: lock for event queue protection.
+ * @event_q: event queue.
+ */
+struct inff_cpevt_info {
+ struct work_struct event_work;
+ /* lock for event queue protection */
+ spinlock_t lock;
+ struct list_head idle_q;
+ struct list_head wait_q;
+ struct list_head event_q;
+ struct list_head monitor_q;
+};
+
+#define INFF_CP_NW_EVENT_VER 2
+
+/*
+ * struct inff_cpevt_nw - contents of CP network event.
+ */
+struct inff_cpevt_nw {
+ u8 type;
+ u8 if_idx;
+ union {
+ u8 mac[ETH_ALEN];
+ u32 ipv4; /* IPv4 address in network byte order */
+ u32 reason;
+ u32 pad[2];
+ } u;
+ u32 ipv6[4];
+} __packed;
+
+/* Scan Event */
+#define INFF_CP_SCAN_EVENT_VER 2
+#define INFF_CP_SCAN_IE_LEN_MAX 896
+
+/*
+ * struct inff_cpevt_scan - contents of CP scan event.
+ */
+struct inff_cpevt_scan {
+ u8 ssid_length; /* SSID length */
+ char ssid[IEEE80211_MAX_SSID_LEN + 1]; /* SSID of the access point */
+ u32 security_type; /* WiFi security type */
+ u8 macaddr[ETH_ALEN]; /* MAC Address of the access point */
+ s16 signal_strength; /* signal strength */
+ u8 channel; /* channel number */
+ u8 band; /* WiFi band of access point */
+ bool scan_complete; /* WiFi scan complete/incomplete */
+ u16 beacon_period; /* Interval between two consecutive beacon frames. Unit: Kusec */
+ u16 capability; /* Capability information */
+ u32 ie_len; /* Length of the IE. */
+
+ /* Pointer to the received Beacon/Probe Response IE (Information Element). */
+ u8 ie[INFF_CP_SCAN_IE_LEN_MAX];
+} __packed;
+
+const char *inff_fwevt_name(enum inff_fwevt_code code);
+
+void inff_fwevt_attach(struct inff_pub *drvr);
+void inff_fwevt_detach(struct inff_pub *drvr);
+int inff_fwevt_register(struct inff_pub *drvr, enum inff_fwevt_code code,
+ int (*handler)(struct inff_if *ifp,
+ const struct inff_event_msg *evtmsg,
+ void *data));
+void inff_fwevt_unregister(struct inff_pub *drvr,
+ enum inff_fwevt_code code);
+int inff_fwevt_activate_events(struct inff_if *ifp);
+void inff_fwevt_process_event(struct inff_pub *drvr,
+ struct inff_event *event_packet,
+ u32 packet_len, gfp_t gfp);
+void inff_fwevt_process_skb(struct inff_pub *drvr, struct sk_buff *skb, u16 stype,
+ gfp_t gfp);
+void inff_fwevt_register_handlers(struct inff_cfg80211_info *cfg);
+
+int inff_cpevt_attach(struct inff_pub *drvr);
+void inff_cpevt_detach(struct inff_pub *drvr);
+void inff_cpevt_process_skb(struct inff_pub *drvr, struct sk_buff *pkt);
+
+#endif /* INFF_DEV_EVT_H */
--
2.43.0
next prev parent reply other threads:[~2026-09-02 16:53 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 16:50 [PATCH wireless-next v3 00/25] wifi: inffmac: introducing a driver for Infineon's new generation chipsets Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 01/25] wifi: inffmac: add a new driver directory for infineon WLAN vendor Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 02/25] wifi: inffmac: add firmware.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 03/25] wifi: inffmac: add dfu.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 04/25] wifi: inffmac: add trxhdr.h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 05/25] wifi: inffmac: add chip.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 06/25] wifi: inffmac: add chip_{cyw5591x/acw74xx}.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 07/25] wifi: inffmac: add icdc.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 08/25] wifi: inffmac: add main.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 09/25] wifi: inffmac: add dev_cmd.c/h Gokul Sivakumar
2026-09-02 16:50 ` Gokul Sivakumar [this message]
2026-09-02 16:50 ` [PATCH wireless-next v3 11/25] wifi: inffmac: add net.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 12/25] wifi: inffmac: add cfg80211.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 13/25] wifi: inffmac: add interface.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 14/25] wifi: inffmac: add he.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 15/25] wifi: inffmac: add feature.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 16/25] wifi: inffmac: add bus_proto.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 17/25] wifi: inffmac: add sdio.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 18/25] wifi: inffmac: add fwsignal.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 19/25] wifi: inffmac: add bcdc.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 20/25] wifi: inffmac: add ie.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 21/25] wifi: inffmac: add scan.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 22/25] wifi: inffmac: add chan.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 23/25] wifi: inffmac: add debug.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 24/25] wifi: inffmac: add utils.c/h Gokul Sivakumar
2026-09-02 16:50 ` [PATCH wireless-next v3 25/25] wifi: inffmac: add Kconfig, Makefile Gokul Sivakumar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260902165057.456447-11-gokulkumar.sivakumar@infineon.com \
--to=gokulkumar.sivakumar@infineon.com \
--cc=arend.vanspriel@broadcom.com \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=wlan-kernel-dev-list@infineon.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox