struct work_struct event_work;
        struct mutex bus_lock; /* lock during command/event processing */
        struct dentry *dbg_dir;
+       struct notifier_block netdev_nb;
        /* bus private data */
        char bus_priv[0] __aligned(sizeof(void *));
 };
 
                goto error_del_vif;
        }
 
+       if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) {
+               ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex);
+               if (ret) {
+                       unregister_netdevice(vif->netdev);
+                       vif->netdev = NULL;
+                       goto error_del_vif;
+               }
+       }
+
        vif->wdev.netdev = vif->netdev;
        return &vif->wdev;
 
 
        qtnf_bus_unlock(bus);
        return ret;
 }
+
+int qtnf_cmd_netdev_changeupper(const struct qtnf_vif *vif, int br_domain)
+{
+       struct qtnf_bus *bus = vif->mac->bus;
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_ndev_changeupper *cmd;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_NDEV_EVENT,
+                                           sizeof(*cmd));
+       if (!cmd_skb)
+               return -ENOMEM;
+
+       pr_debug("[VIF%u.%u] set broadcast domain to %d\n",
+                vif->mac->macid, vif->vifid, br_domain);
+
+       cmd = (struct qlink_cmd_ndev_changeupper *)cmd_skb->data;
+       cmd->nehdr.event = cpu_to_le16(QLINK_NDEV_EVENT_CHANGEUPPER);
+       cmd->upper_type = QLINK_NDEV_UPPER_TYPE_BRIDGE;
+       cmd->br_domain = cpu_to_le32(br_domain);
+
+       qtnf_bus_lock(bus);
+       ret = qtnf_cmd_send(bus, cmd_skb);
+       qtnf_bus_unlock(bus);
+
+       if (ret)
+               pr_err("[VIF%u.%u] failed to set broadcast domain\n",
+                      vif->mac->macid, vif->vifid);
+
+       return ret;
+}
 
                          enum nl80211_tx_power_setting type, int mbm);
 int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
                             const struct cfg80211_wowlan *wowl);
+int qtnf_cmd_netdev_changeupper(const struct qtnf_vif *vif, int br_domain);
 
 #endif /* QLINK_COMMANDS_H_ */
 
                goto error_del_vif;
        }
 
+       if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) {
+               ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex);
+               if (ret)
+                       goto error;
+       }
+
        pr_debug("MAC%u initialized\n", macid);
 
        return 0;
        return ret;
 }
 
+bool qtnf_netdev_is_qtn(const struct net_device *ndev)
+{
+       return ndev->netdev_ops == &qtnf_netdev_ops;
+}
+
+static int qtnf_core_netdevice_event(struct notifier_block *nb,
+                                    unsigned long event, void *ptr)
+{
+       struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+       const struct netdev_notifier_changeupper_info *info;
+       struct qtnf_vif *vif;
+       int br_domain;
+       int ret = 0;
+
+       if (!qtnf_netdev_is_qtn(ndev))
+               return NOTIFY_DONE;
+
+       if (!net_eq(dev_net(ndev), &init_net))
+               return NOTIFY_OK;
+
+       vif = qtnf_netdev_get_priv(ndev);
+
+       switch (event) {
+       case NETDEV_CHANGEUPPER:
+               info = ptr;
+
+               if (!netif_is_bridge_master(info->upper_dev))
+                       break;
+
+               pr_debug("[VIF%u.%u] change bridge: %s %s\n",
+                        vif->mac->macid, vif->vifid,
+                        netdev_name(info->upper_dev),
+                        info->linking ? "add" : "del");
+
+               if (info->linking)
+                       br_domain = info->upper_dev->ifindex;
+               else
+                       br_domain = ndev->ifindex;
+
+               ret = qtnf_cmd_netdev_changeupper(vif, br_domain);
+               break;
+       default:
+               break;
+       }
+
+       return notifier_from_errno(ret);
+}
+
 int qtnf_core_attach(struct qtnf_bus *bus)
 {
        unsigned int i;
                }
        }
 
+       if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) {
+               bus->netdev_nb.notifier_call = qtnf_core_netdevice_event;
+               ret = register_netdevice_notifier(&bus->netdev_nb);
+               if (ret) {
+                       pr_err("failed to register netdev notifier: %d\n", ret);
+                       goto error;
+               }
+       }
+
        bus->fw_state = QTNF_FW_STATE_RUNNING;
        return 0;
 
 {
        unsigned int macid;
 
+       unregister_netdevice_notifier(&bus->netdev_nb);
        qtnf_bus_data_rx_stop(bus);
 
        for (macid = 0; macid < QTNF_MAX_MAC; macid++)
 
 void qtnf_netdev_updown(struct net_device *ndev, bool up);
 void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted);
 struct dentry *qtnf_get_debugfs_dir(void);
+bool qtnf_netdev_is_qtn(const struct net_device *ndev);
 
 static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
 {
 
  * @QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR: device supports MAC Address
  *     Randomization in probe requests.
  * @QLINK_HW_CAPAB_OBSS_SCAN: device can perform OBSS scanning.
+ * @QLINK_HW_CAPAB_HW_BRIDGE: device has hardware switch capabilities.
  */
 enum qlink_hw_capab {
        QLINK_HW_CAPAB_REG_UPDATE               = BIT(0),
        QLINK_HW_CAPAB_OBSS_SCAN                = BIT(5),
        QLINK_HW_CAPAB_SCAN_DWELL               = BIT(6),
        QLINK_HW_CAPAB_SAE                      = BIT(8),
+       QLINK_HW_CAPAB_HW_BRIDGE                = BIT(9),
 };
 
 enum qlink_iface_type {
  * @QLINK_CMD_START_CAC: start radar detection procedure on a specified channel.
  * @QLINK_CMD_TXPWR: get or set current channel transmit power for
  *     the specified MAC.
+ * @QLINK_CMD_NDEV_EVENT: signalizes changes made with a corresponding network
+ *     device.
  */
 enum qlink_cmd_type {
        QLINK_CMD_FW_INIT               = 0x0001,
        QLINK_CMD_DEL_STA               = 0x0052,
        QLINK_CMD_SCAN                  = 0x0053,
        QLINK_CMD_CHAN_STATS            = 0x0054,
+       QLINK_CMD_NDEV_EVENT            = 0x0055,
        QLINK_CMD_CONNECT               = 0x0060,
        QLINK_CMD_DISCONNECT            = 0x0061,
        QLINK_CMD_PM_SET                = 0x0062,
        u8 data[0];
 } __packed;
 
+enum qlink_ndev_event_type {
+       QLINK_NDEV_EVENT_CHANGEUPPER,
+};
+
+/**
+ * struct qlink_cmd_ndev_event - data for QLINK_CMD_NDEV_EVENT command
+ *
+ * @event: type of event, one of &enum qlink_ndev_event_type
+ */
+struct qlink_cmd_ndev_event {
+       struct qlink_cmd chdr;
+       __le16 event;
+       u8 rsvd[2];
+} __packed;
+
+enum qlink_ndev_upper_type {
+       QLINK_NDEV_UPPER_TYPE_NONE,
+       QLINK_NDEV_UPPER_TYPE_BRIDGE,
+};
+
+/**
+ * struct qlink_cmd_ndev_changeupper - data for QLINK_NDEV_EVENT_CHANGEUPPER
+ *
+ * @br_domain: layer 2 broadcast domain ID that ndev is a member of
+ * @upper_type: type of upper device, one of &enum qlink_ndev_upper_type
+ */
+struct qlink_cmd_ndev_changeupper {
+       struct qlink_cmd_ndev_event nehdr;
+       __le64 flags;
+       __le32 br_domain;
+       __le32 netspace_id;
+       __le16 vlanid;
+       u8 upper_type;
+       u8 rsvd[1];
+} __packed;
+
 /* QLINK Command Responses messages related definitions
  */