From 164f4e91748b04082732addd27ca06457a219d98 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 10 Apr 2012 19:12:50 -0700 Subject: [PATCH] compat-wireless: split patches/01-netdev.patch up This splits up patches/01-netdev.patch into the following set of patches: patches/0001-netdev_ops.patch patches/0002-net-misc.patch patches/0003-netdev-needed_headroom_tailroom.patch patches/0004-wext-namespace.patch This isolates the network device operations infrastructure into a separate file to show one collateral evolution [0]. The next objective will be to extract SmPL out of the patch patches/0001-netdev_ops.patch. If we can extract SmPL [1] out of it, with the help of compat as a backend store to help us backport the work required, we could automatically backport this collateral evolution to any network driver. Backporting this specific collateral evolution then on compat-wireless would simply require adding the driver's directory to be copied into the framework, a one line change. If we keep doing this for more collateral evolutions the implications are the ability to enhance automatically backporting even more collateral evolutions and therefore drivers. mcgrof@flash ~/devel/compat-wireless (git::master)$ time ckmake ; time ckmake Trying kernel 3.2.2-030202-generic [OK] Trying kernel 3.1.10-030110-generic [OK] Trying kernel 3.0.18-030018-generic [OK] Trying kernel 2.6.39-02063904-generic [OK] Trying kernel 2.6.38-02063808-generic [OK] Trying kernel 2.6.37-02063706-generic [OK] Trying kernel 2.6.36-02063604-generic [OK] Trying kernel 2.6.35-02063512-generic [OK] Trying kernel 2.6.34-02063410-generic [OK] Trying kernel 2.6.33-02063305-generic [OK] Trying kernel 2.6.32-02063255-generic [OK] Trying kernel 2.6.31-02063113-generic [OK] Trying kernel 2.6.30-02063010-generic [OK] Trying kernel 2.6.29-02062906-generic [OK] Trying kernel 2.6.28-02062810-generic [OK] Trying kernel 2.6.27-020627-generic [OK] Trying kernel 2.6.26-020626-generic [OK] Trying kernel 2.6.25-020625-generic [OK] Trying kernel 2.6.24-020624-generic [OK] real 85m10.426s user 258m22.297s sys 22m55.582s real 14m37.117s user 32m18.885s sys 7m4.599s [0] http://coccinelle.lip6.fr/ce.php [1] http://coccinelle.lip6.fr/ Signed-off-by: Luis R. Rodriguez --- ...{01-netdev.patch => 0001-netdev_ops.patch} | 276 ++++++------------ patches/0002-net-misc.patch | 68 +++++ ...0003-netdev-needed_headroom_tailroom.patch | 36 +++ patches/0004-wext-namespace.patch | 58 ++++ 4 files changed, 255 insertions(+), 183 deletions(-) rename patches/{01-netdev.patch => 0001-netdev_ops.patch} (66%) create mode 100644 patches/0002-net-misc.patch create mode 100644 patches/0003-netdev-needed_headroom_tailroom.patch create mode 100644 patches/0004-wext-namespace.patch diff --git a/patches/01-netdev.patch b/patches/0001-netdev_ops.patch similarity index 66% rename from patches/01-netdev.patch rename to patches/0001-netdev_ops.patch index 6d35b36a70b6..56a6886aaf1b 100644 --- a/patches/01-netdev.patch +++ b/patches/0001-netdev_ops.patch @@ -1,23 +1,49 @@ -This patch backports the struct net_device_ops changes added -on 2.6.29. It also backports the namespace changes added -through net/wireless/wext.c. Note that there is another -patch file which also addresses netns changes, we leave -them separate as there is no easy way to split the stuff -without creating a headache on maintenance of the pathes. +This patch backports the struct net_device_ops changes added on 2.6.29. + +If we add the compat.git netdev_attach_ops() implementation +for newer kernels upstream it means we do not have to use this +patch at all for older kernels. + +mcgrof@tux ~/linux-stable (git::master)$ git describe --contains d314774cf2cd5dfeb39a00d37deee65d4c627927 +v2.6.29-rc1~581^2~677 + +commit d314774cf2cd5dfeb39a00d37deee65d4c627927 +Author: Stephen Hemminger +Date: Wed Nov 19 21:32:24 2008 -0800 + + netdev: network device operations infrastructure + + This patch changes the network device internal API to move adminstrative + operations out of the network device structure and into a separate structure. + + This patch involves some hackery to maintain compatablity between the + new and old model, so all 300+ drivers don't have to be changed at once. + For drivers that aren't converted yet, the netdevice_ops virt function list + still resides in the net_device structure. For old protocols, the new + net_device_ops are copied out to the old net_device pointers. + + After the transistion is completed the nag message can be changed to + an WARN_ON, and the compatiablity code can be made configurable. + + Some function pointers aren't moved: + * destructor can't be in net_device_ops because + it may need to be referenced after the module is unloaded. + * neighbor setup is manipulated in a couple of places that need special + consideration + * hard_start_xmit is in the fast path for transmit. + + Signed-off-by: Stephen Hemminger + Signed-off-by: David S. Miller --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c -@@ -355,7 +355,11 @@ generic_rndis_bind(struct usbnet *dev, s +@@ -355,7 +355,7 @@ generic_rndis_bind(struct usbnet *dev, s dev->rx_urb_size &= ~(dev->maxpacket - 1); u.init->max_transfer_size = cpu_to_le32(dev->rx_urb_size); - net->netdev_ops = &rndis_netdev_ops; + netdev_attach_ops(net, &rndis_netdev_ops); -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -+ /* can't we remove this? */ -+ net->change_mtu = NULL; -+#endif retval = rndis_command(dev, u.header, CONTROL_BUFFER_SIZE); if (unlikely(retval < 0)) { @@ -54,57 +80,6 @@ without creating a headache on maintenance of the pathes. tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -703,7 +703,12 @@ static void ieee80211_if_setup(struct ne - { - ether_setup(dev); - dev->priv_flags &= ~IFF_TX_SKB_SHARING; -- dev->netdev_ops = &ieee80211_dataif_ops; -+ netdev_attach_ops(dev, &ieee80211_dataif_ops); -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -+ /* Do we need this ? */ -+ /* we will validate the address ourselves in ->open */ -+ dev->validate_addr = NULL; -+#endif - dev->destructor = free_netdev; - } - -@@ -850,7 +855,7 @@ static void ieee80211_setup_sdata(struct - /* and set some type-dependent values */ - sdata->vif.type = type; - sdata->vif.p2p = false; -- sdata->dev->netdev_ops = &ieee80211_dataif_ops; -+ netdev_attach_ops(sdata->dev, &ieee80211_dataif_ops); - sdata->wdev.iftype = type; - - sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); -@@ -891,7 +896,7 @@ static void ieee80211_setup_sdata(struct - break; - case NL80211_IFTYPE_MONITOR: - sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; -- sdata->dev->netdev_ops = &ieee80211_monitorif_ops; -+ netdev_attach_ops(sdata->dev, &ieee80211_monitorif_ops); - sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | - MONITOR_FLAG_OTHER_BSS; - break; -@@ -1142,6 +1147,8 @@ int ieee80211_if_add(struct ieee80211_lo - return -ENOMEM; - dev_net_set(ndev, wiphy_net(local->hw.wiphy)); - -+/* This is an optimization, just ignore for older kernels */ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) - ndev->needed_headroom = local->tx_headroom + - 4*6 /* four MAC addresses */ - + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ -@@ -1150,6 +1157,7 @@ int ieee80211_if_add(struct ieee80211_lo - - ETH_HLEN /* ethernet hard_header_len */ - + IEEE80211_ENCRYPT_HEADROOM; - ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; -+#endif - - ret = dev_alloc_name(ndev, ndev->name); - if (ret < 0) --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2159,7 +2159,7 @@ static int __devinit b44_init_one(struct @@ -116,74 +91,6 @@ without creating a headache on maintenance of the pathes. netif_napi_add(dev, &bp->napi, b44_poll, 64); dev->watchdog_timeo = B44_TX_TIMEOUT; dev->irq = sdev->irq; ---- a/net/wireless/wext-core.c -+++ b/net/wireless/wext-core.c -@@ -342,6 +342,7 @@ static const int compat_event_type_size[ - - /* IW event code */ - -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) - static int __net_init wext_pernet_init(struct net *net) - { - skb_queue_head_init(&net->wext_nlevents); -@@ -384,6 +385,29 @@ static void wireless_nlevent_process(str - - static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); - -+#else -+/* Older kernels get the old way of doing stuff*/ -+static struct sk_buff_head wireless_nlevent_queue; -+ -+static int __init wireless_nlevent_init(void) -+{ -+ skb_queue_head_init(&wireless_nlevent_queue); -+ return 0; -+} -+ -+subsys_initcall(wireless_nlevent_init); -+ -+static void wireless_nlevent_process(unsigned long data) -+{ -+ struct sk_buff *skb; -+ while ((skb = skb_dequeue(&wireless_nlevent_queue))) -+ rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); -+} -+ -+static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); -+ -+#endif -+ - static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, - struct sk_buff *skb) - { -@@ -597,8 +621,13 @@ void wireless_send_event(struct net_devi - - skb_shinfo(skb)->frag_list = compskb; - #endif -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) - skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); - schedule_work(&wireless_nlevent_work); -+#else -+ skb_queue_tail(&wireless_nlevent_queue, skb); -+ tasklet_schedule(&wireless_nlevent_tasklet); -+#endif - } - EXPORT_SYMBOL(wireless_send_event); - -@@ -925,8 +954,13 @@ static int wireless_process_ioctl(struct - return private(dev, iwr, cmd, info, handler); - } - /* Old driver API : call driver ioctl handler */ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) - if (dev->netdev_ops->ndo_do_ioctl) - return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); -+#else -+ if (dev->do_ioctl) -+ return dev->do_ioctl(dev, ifr, cmd); -+#endif - return -EOPNOTSUPP; - } - --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6114,7 +6114,7 @@ static struct net_device *ipw2100_alloc_ @@ -248,23 +155,6 @@ without creating a headache on maintenance of the pathes. mesh_dev->ethtool_ops = &lbs_ethtool_ops; memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN); ---- a/drivers/net/wireless/libertas/defs.h -+++ b/drivers/net/wireless/libertas/defs.h -@@ -16,6 +16,14 @@ - #define DRV_NAME "libertas" - #endif - -+/* -+ * Really nasty hack to avoid stuffing compat.diff with tons of ifdefs, -+ * we could add this to a compat header file but too lazy to check ml_priv -+ * is not used anywhere else -+ */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) -+#define ml_priv priv -+#endif - - #define LBS_DEB_ENTER 0x00000001 - #define LBS_DEB_LEAVE 0x00000002 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1289,7 +1289,7 @@ static const struct net_device_ops hwsim @@ -287,44 +177,8 @@ without creating a headache on maintenance of the pathes. /* Initialize private structure */ priv->current_key_index = 0; priv->media_connected = false; ---- a/drivers/net/wireless/orinoco/main.c -+++ b/drivers/net/wireless/orinoco/main.c -@@ -2278,14 +2278,18 @@ int orinoco_if_add(struct orinoco_privat - #endif - /* Default to standard ops if not set */ - if (ops) -- dev->netdev_ops = ops; -+ netdev_attach_ops(dev, ops); - else -- dev->netdev_ops = &orinoco_netdev_ops; -+ netdev_attach_ops(dev, &orinoco_netdev_ops); - - /* we use the default eth_mac_addr for setting the MAC addr */ - - /* Reserve space in skb for the SNAP header */ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) - dev->needed_headroom = ENCAPS_OVERHEAD; -+#else -+ dev->hard_header_len += ENCAPS_OVERHEAD; -+#endif - - netif_carrier_off(dev); - --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c -@@ -170,8 +170,12 @@ static inline int bnep_net_proto_filter( - } - #endif - -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31)) - static netdev_tx_t bnep_net_xmit(struct sk_buff *skb, - struct net_device *dev) -+#else -+static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) -+#endif - { - struct bnep_session *s = netdev_priv(dev); - struct sock *sk = s->sock->sk; @@ -232,7 +236,7 @@ void bnep_net_setup(struct net_device *d ether_setup(dev); @@ -378,3 +232,59 @@ without creating a headache on maintenance of the pathes. atl2_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -703,7 +703,7 @@ static void ieee80211_if_setup(struct ne + { + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; +- dev->netdev_ops = &ieee80211_dataif_ops; ++ netdev_attach_ops(dev, &ieee80211_dataif_ops); + dev->destructor = free_netdev; + } + +@@ -850,7 +850,7 @@ static void ieee80211_setup_sdata(struct + /* and set some type-dependent values */ + sdata->vif.type = type; + sdata->vif.p2p = false; +- sdata->dev->netdev_ops = &ieee80211_dataif_ops; ++ netdev_attach_ops(sdata->dev, &ieee80211_dataif_ops); + sdata->wdev.iftype = type; + + sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); +@@ -891,7 +891,7 @@ static void ieee80211_setup_sdata(struct + break; + case NL80211_IFTYPE_MONITOR: + sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; +- sdata->dev->netdev_ops = &ieee80211_monitorif_ops; ++ netdev_attach_ops(sdata->dev, &ieee80211_monitorif_ops); + sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | + MONITOR_FLAG_OTHER_BSS; + break; +--- a/drivers/net/wireless/orinoco/main.c ++++ b/drivers/net/wireless/orinoco/main.c +@@ -2278,9 +2278,9 @@ int orinoco_if_add(struct orinoco_privat + #endif + /* Default to standard ops if not set */ + if (ops) +- dev->netdev_ops = ops; ++ netdev_attach_ops(dev, ops); + else +- dev->netdev_ops = &orinoco_netdev_ops; ++ netdev_attach_ops(dev, &orinoco_netdev_ops); + + /* we use the default eth_mac_addr for setting the MAC addr */ + +--- a/net/wireless/wext-core.c ++++ b/net/wireless/wext-core.c +@@ -925,9 +925,7 @@ static int wireless_process_ioctl(struct + return private(dev, iwr, cmd, info, handler); + } + /* Old driver API : call driver ioctl handler */ +- if (dev->netdev_ops->ndo_do_ioctl) +- return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); +- return -EOPNOTSUPP; ++ return ndo_do_ioctl(dev, ifr, cmd); + } + + /* If command is `set a parameter', or `get the encoding parameters', diff --git a/patches/0002-net-misc.patch b/patches/0002-net-misc.patch new file mode 100644 index 000000000000..03e4d15150ab --- /dev/null +++ b/patches/0002-net-misc.patch @@ -0,0 +1,68 @@ +These are things that removed in later kernels but no good explanatin +was provided as to their removal. We should review if this is needed +and if not remove these hunks. + +Pretty sure we can remove the netdev_tx_t hunk change on +net/bluetooth/bnep/netdev.c, removing that hunk just needs to be +compile tested against older kernels. + +--- a/drivers/net/usb/rndis_host.c ++++ b/drivers/net/usb/rndis_host.c +@@ -329,6 +329,11 @@ generic_rndis_bind(struct usbnet *dev, s + u.init->major_version = cpu_to_le32(1); + u.init->minor_version = cpu_to_le32(0); + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) ++ /* can't we remove this? */ ++ net->change_mtu = NULL; ++#endif ++ + /* max transfer (in spec) is 0x4000 at full speed, but for + * TX we'll stick to one Ethernet packet plus RNDIS framing. + * For RX we handle drivers that zero-pad to end-of-packet. +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -704,6 +704,11 @@ static void ieee80211_if_setup(struct ne + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + netdev_attach_ops(dev, &ieee80211_dataif_ops); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) ++ /* Do we need this ? */ ++ /* we will validate the address ourselves in ->open */ ++ dev->validate_addr = NULL; ++#endif + dev->destructor = free_netdev; + } + +--- a/net/bluetooth/bnep/netdev.c ++++ b/net/bluetooth/bnep/netdev.c +@@ -170,8 +170,12 @@ static inline int bnep_net_proto_filter( + } + #endif + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31)) + static netdev_tx_t bnep_net_xmit(struct sk_buff *skb, + struct net_device *dev) ++#else ++static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) ++#endif + { + struct bnep_session *s = netdev_priv(dev); + struct sock *sk = s->sock->sk; +--- a/drivers/net/wireless/libertas/defs.h ++++ b/drivers/net/wireless/libertas/defs.h +@@ -16,6 +16,14 @@ + #define DRV_NAME "libertas" + #endif + ++/* ++ * Really nasty hack to avoid stuffing compat.diff with tons of ifdefs, ++ * we could add this to a compat header file but too lazy to check ml_priv ++ * is not used anywhere else ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) ++#define ml_priv priv ++#endif + + #define LBS_DEB_ENTER 0x00000001 + #define LBS_DEB_LEAVE 0x00000002 diff --git a/patches/0003-netdev-needed_headroom_tailroom.patch b/patches/0003-netdev-needed_headroom_tailroom.patch new file mode 100644 index 000000000000..1a777c2895d6 --- /dev/null +++ b/patches/0003-netdev-needed_headroom_tailroom.patch @@ -0,0 +1,36 @@ +This is an optimization introduced on newer kernels, just ignore for +older kernels on mac80211. For others the netdev->hard_header_len +could be used. + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1147,6 +1147,7 @@ int ieee80211_if_add(struct ieee80211_lo + return -ENOMEM; + dev_net_set(ndev, wiphy_net(local->hw.wiphy)); + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + ndev->needed_headroom = local->tx_headroom + + 4*6 /* four MAC addresses */ + + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ +@@ -1155,6 +1156,7 @@ int ieee80211_if_add(struct ieee80211_lo + - ETH_HLEN /* ethernet hard_header_len */ + + IEEE80211_ENCRYPT_HEADROOM; + ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; ++#endif + + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) +--- a/drivers/net/wireless/orinoco/main.c ++++ b/drivers/net/wireless/orinoco/main.c +@@ -2285,7 +2285,11 @@ int orinoco_if_add(struct orinoco_privat + /* we use the default eth_mac_addr for setting the MAC addr */ + + /* Reserve space in skb for the SNAP header */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + dev->needed_headroom = ENCAPS_OVERHEAD; ++#else ++ dev->hard_header_len += ENCAPS_OVERHEAD; ++#endif + + netif_carrier_off(dev); + diff --git a/patches/0004-wext-namespace.patch b/patches/0004-wext-namespace.patch new file mode 100644 index 000000000000..606001b62110 --- /dev/null +++ b/patches/0004-wext-namespace.patch @@ -0,0 +1,58 @@ + +This patch backports the namespace changes added +through net/wireless/wext.c. + +--- a/net/wireless/wext-core.c ++++ b/net/wireless/wext-core.c +@@ -342,6 +342,7 @@ static const int compat_event_type_size[ + + /* IW event code */ + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + static int __net_init wext_pernet_init(struct net *net) + { + skb_queue_head_init(&net->wext_nlevents); +@@ -384,6 +385,29 @@ static void wireless_nlevent_process(str + + static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); + ++#else ++/* Older kernels get the old way of doing stuff*/ ++static struct sk_buff_head wireless_nlevent_queue; ++ ++static int __init wireless_nlevent_init(void) ++{ ++ skb_queue_head_init(&wireless_nlevent_queue); ++ return 0; ++} ++ ++subsys_initcall(wireless_nlevent_init); ++ ++static void wireless_nlevent_process(unsigned long data) ++{ ++ struct sk_buff *skb; ++ while ((skb = skb_dequeue(&wireless_nlevent_queue))) ++ rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); ++} ++ ++static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); ++ ++#endif ++ + static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, + struct sk_buff *skb) + { +@@ -597,8 +621,13 @@ void wireless_send_event(struct net_devi + + skb_shinfo(skb)->frag_list = compskb; + #endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); + schedule_work(&wireless_nlevent_work); ++#else ++ skb_queue_tail(&wireless_nlevent_queue, skb); ++ tasklet_schedule(&wireless_nlevent_tasklet); ++#endif + } + EXPORT_SYMBOL(wireless_send_event); + -- 2.30.2