diff options
Diffstat (limited to 'drivers/staging/csr/netdev.c')
-rw-r--r-- | drivers/staging/csr/netdev.c | 630 |
1 files changed, 6 insertions, 624 deletions
diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c index 1e6e111a8e1..9a52ab408e1 100644 --- a/drivers/staging/csr/netdev.c +++ b/drivers/staging/csr/netdev.c @@ -15,7 +15,6 @@ * --------------------------------------------------------------------------- */ - /* * Porting Notes: * This file implements the data plane of the UniFi linux driver. @@ -48,59 +47,14 @@ #include <linux/etherdevice.h> #include <linux/mutex.h> #include <linux/semaphore.h> - +#include <linux/version.h> #include <linux/vmalloc.h> #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_conversions.h" #include "unifi_priv.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) -#include <net/iw_handler.h> -#endif #include <net/pkt_sched.h> -/* ALLOW_Q_PAUSE: Pre 2.6.28 kernels do not support multiple driver queues (required for QoS). - * In order to support QoS in these kernels, multiple queues are implemented in the driver. But since - * there is only a single queue in the kernel (leading to multiple queues in the driver) there is no possibility - * of stopping a particular queue in the kernel. Stopping the single kernel queue leads to undesirable starvation - * of driver queues. One of the proposals is to not stop the kernel queue but to prevent dequeuing from the - * 'stopped' driver queue. Allow q pause is an experimental implementation of this scheme for pre 2.6.28 kernels. - * When NOT defined, queues are paused locally in the driver and packets are dequeued for transmission only from the - * unpaused queues. When Allow q pause is defined the kernel queue is stopped whenever any driver queue is paused. - */ -#define ALLOW_Q_PAUSE - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) -#ifdef UNIFI_NET_NAME -#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ - do { \ - static char name[8]; \ - sprintf(name, "%s%s", UNIFI_NET_NAME, _name); \ - _dev = alloc_netdev_mq(_size, name, _setup, _num_of_queues); \ - } while (0); -#else -#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ - do { \ - _dev = alloc_etherdev_mq(_size, _num_of_queues); \ - } while (0); -#endif /* UNIFI_NET_NAME */ -#else -#ifdef UNIFI_NET_NAME -#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ - do { \ - static char name[8]; \ - sprintf(name, "%s%s", UNIFI_NET_NAME, _name); \ - _dev = alloc_netdev(_size, name, _setup); \ - } while (0); -#else -#define UF_ALLOC_NETDEV(_dev, _size, _name, _setup, _num_of_queues) \ - do { \ - _dev = alloc_etherdev(_size); \ - } while (0); -#endif /* UNIFI_NET_NAME */ -#endif /* LINUX_VERSION_CODE */ - - /* Wext handler is suported only if CSR_SUPPORT_WEXT is defined */ #ifdef CSR_SUPPORT_WEXT extern struct iw_handler_def unifi_iw_handler_def; @@ -119,20 +73,8 @@ static int uf_net_open(struct net_device *dev); static int uf_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int uf_net_stop(struct net_device *dev); static struct net_device_stats *uf_net_get_stats(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) static u16 uf_net_select_queue(struct net_device *dev, struct sk_buff *skb); -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) static netdev_tx_t uf_net_xmit(struct sk_buff *skb, struct net_device *dev); -#else -static int uf_net_xmit(struct sk_buff *skb, struct net_device *dev); -#ifndef NETDEV_TX_OK -#define NETDEV_TX_OK 0 -#endif -#ifndef NETDEV_TX_BUSY -#define NETDEV_TX_BUSY 1 -#endif -#endif static void uf_set_multicast_list(struct net_device *dev); @@ -182,62 +124,8 @@ struct uf_tx_packet_data { unsigned long host_tag; }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -static int uf_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd); -static int uf_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd); -static struct sk_buff *uf_qdiscop_dequeue(struct Qdisc* qd); -static void uf_qdiscop_reset(struct Qdisc* qd); -static void uf_qdiscop_destroy(struct Qdisc* qd); -static int uf_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) -static int uf_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt); -static int uf_qdiscop_init(struct Qdisc *qd, struct nlattr *opt); -#else -static int uf_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt); -static int uf_qdiscop_init(struct Qdisc *qd, struct rtattr *opt); -#endif -#endif - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -/* queueing discipline operations */ -static struct Qdisc_ops uf_qdisc_ops = -{ - .next = NULL, - .cl_ops = NULL, - .id = "UniFi Qdisc", - .priv_size = sizeof(struct uf_sched_data), - - .enqueue = uf_qdiscop_enqueue, - .dequeue = uf_qdiscop_dequeue, - .requeue = uf_qdiscop_requeue, - .drop = NULL, /* drop not needed since we are always the root qdisc */ - - .init = uf_qdiscop_init, - .reset = uf_qdiscop_reset, - .destroy = uf_qdiscop_destroy, - .change = uf_qdiscop_tune, - - .dump = uf_qdiscop_dump, -}; -#endif /* LINUX_VERSION_CODE */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) -#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) -#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ - qdisc_create_dflt(dev, netdev_get_tx_queue(_dev, 0), _ops, _root) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) -#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ - qdisc_create_dflt(dev, _ops, _root) -#else -#define UF_QDISC_CREATE_DFLT(_dev, _ops, _root) \ - qdisc_create_dflt(dev, _ops) -#endif /* LINUX_VERSION_CODE */ - #endif /* CONFIG_NET_SCHED */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) static const struct net_device_ops uf_netdev_ops = { .ndo_open = uf_net_open, @@ -248,7 +136,6 @@ static const struct net_device_ops uf_netdev_ops = .ndo_set_rx_mode = uf_set_multicast_list, .ndo_select_queue = uf_net_select_queue, }; -#endif static u8 oui_rfc1042[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; static u8 oui_8021h[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; @@ -310,7 +197,7 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, * so use "eth*" (like other wireless extns drivers). */ - UF_ALLOC_NETDEV(dev, sizeof(unifi_priv_t)+sizeof(netInterface_priv_t), "%d", ether_setup, UNIFI_TRAFFIC_Q_MAX); + dev = alloc_etherdev_mq(sizeof(unifi_priv_t) + sizeof(netInterface_priv_t), UNIFI_TRAFFIC_Q_MAX); if (dev == NULL) { return NULL; @@ -332,22 +219,7 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) priv->interfacePriv[0] = interfacePriv; /* Setup / override net_device fields */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) dev->netdev_ops = &uf_netdev_ops; -#else - dev->open = uf_net_open; - dev->stop = uf_net_stop; - dev->hard_start_xmit = uf_net_xmit; - dev->do_ioctl = uf_net_ioctl; - - /* called by /proc/net/dev */ - dev->get_stats = uf_net_get_stats; - - dev->set_multicast_list = uf_set_multicast_list; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) - dev->select_queue = uf_net_select_queue; -#endif -#endif #ifdef CSR_SUPPORT_WEXT dev->wireless_handlers = &unifi_iw_handler_def; @@ -440,21 +312,13 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) interfacePriv->connected = UnifiConnectedUnknown; /* -1 unknown, 0 no, 1 yes */ #ifdef USE_DRIVER_LOCK -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) sema_init(&priv->lock, 1); -#else - init_MUTEX(&priv->lock); -#endif #endif /* USE_DRIVER_LOCK */ spin_lock_init(&priv->send_signal_lock); spin_lock_init(&priv->m4_lock); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) sema_init(&priv->ba_mutex, 1); -#else - init_MUTEX(&priv->ba_mutex); -#endif #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) spin_lock_init(&priv->wapi_lock); @@ -487,16 +351,8 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) #endif #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -#ifdef CONFIG_NET_SCHED - /* Register the qdisc operations */ - register_qdisc(&uf_qdisc_ops); -#endif /* CONFIG_NET_SCHED */ -#endif /* LINUX_VERSION_CODE */ - priv->ref_count = 1; - priv->amp_client = NULL; priv->coredump_mode = 0; priv->ptest_mode = 0; @@ -566,7 +422,7 @@ uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag) * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, * so use "eth*" (like other wireless extns drivers). */ - UF_ALLOC_NETDEV(dev, sizeof(netInterface_priv_t), "%d", ether_setup, 1); + dev = alloc_etherdev_mq(sizeof(netInterface_priv_t), 1); if (dev == NULL) { return FALSE; } @@ -589,19 +445,7 @@ uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag) INIT_LIST_HEAD(&interfacePriv->rx_controlled_list); /* Setup / override net_device fields */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) dev->netdev_ops = &uf_netdev_ops; -#else - dev->open = uf_net_open; - dev->stop = uf_net_stop; - dev->hard_start_xmit = uf_net_xmit; - dev->do_ioctl = uf_net_ioctl; - - /* called by /proc/net/dev */ - dev->get_stats = uf_net_get_stats; - - dev->set_multicast_list = uf_set_multicast_list; -#endif #ifdef CSR_SUPPORT_WEXT dev->wireless_handlers = &unifi_iw_handler_def; @@ -686,13 +530,6 @@ uf_free_netdevice(unifi_priv_t *priv) spin_unlock_irqrestore(&priv->wapi_lock, flags); #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -#ifdef CONFIG_NET_SCHED - /* Unregister the qdisc operations */ - unregister_qdisc(&uf_qdisc_ops); -#endif /* CONFIG_NET_SCHED */ -#endif /* LINUX_VERSION_CODE */ - #ifdef CSR_SUPPORT_WEXT /* Unregister callback for netdevice state changes */ unregister_netdevice_notifier(&uf_netdev_notifier); @@ -700,10 +537,8 @@ uf_free_netdevice(unifi_priv_t *priv) #ifdef CSR_SUPPORT_SME /* Cancel work items and destroy the workqueue */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) cancel_work_sync(&priv->multicast_list_task); #endif -#endif /* Destroy the workqueues. */ flush_workqueue(priv->unifi_workqueue); destroy_workqueue(priv->unifi_workqueue); @@ -778,7 +613,7 @@ uf_net_open(struct net_device *dev) } #endif - UF_NETIF_TX_START_ALL_QUEUES(dev); + netif_tx_start_all_queues(dev); func_exit(); return 0; @@ -808,7 +643,7 @@ uf_net_stop(struct net_device *dev) func_enter(); #endif - UF_NETIF_TX_STOP_ALL_QUEUES(dev); + netif_tx_stop_all_queues(dev); func_exit(); return 0; @@ -957,7 +792,6 @@ get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr return priority; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) /* * --------------------------------------------------------------------------- * uf_net_select_queue @@ -1005,7 +839,6 @@ uf_net_select_queue(struct net_device *dev, struct sk_buff *skb) func_exit(); return (u16)queue; } /* uf_net_select_queue() */ -#endif int skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto) @@ -1915,11 +1748,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr * The controlled port is handled in the qdisc dequeue handler. * --------------------------------------------------------------------------- */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) static netdev_tx_t -#else -static int -#endif uf_net_xmit(struct sk_buff *skb, struct net_device *dev) { netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); @@ -1929,9 +1758,7 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) int result; static tx_signal_handler tx_handler; CSR_PRIORITY priority; -#if !defined (CONFIG_NET_SCHED) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) CsrWifiRouterCtrlPortAction port_action; -#endif /* CONFIG_NET_SCHED */ func_enter(); @@ -1956,11 +1783,6 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) port = UF_UNCONTROLLED_PORT_Q; } -#if defined (CONFIG_NET_SCHED) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) - /* Remove the ethernet header */ - skb_pull(skb, ETH_HLEN); - result = tx_handler(priv, skb, &ehdr, priority); -#else /* Uncontrolled port rules apply */ port_action = verify_port(priv , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode)||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI== interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) @@ -1986,7 +1808,6 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev) func_exit(); return NETDEV_TX_OK; } -#endif /* CONFIG_NET_SCHED */ if (result == NETDEV_TX_OK) { #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) @@ -2059,7 +1880,6 @@ unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue) func_enter(); unifi_trace(priv, UDBG2, "Stopping queue %d\n", queue); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++) { if (netif_running(priv->netdev[i])) @@ -2067,24 +1887,6 @@ unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue) netif_stop_subqueue(priv->netdev[i], (u16)queue); } } -#else -#ifdef ALLOW_Q_PAUSE - unifi_trace(priv, UDBG2, "Stopping netif\n"); - /* stop the traffic from all the interfaces. */ - for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++) - { - if (netif_running(priv->netdev[i])) { - UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]); - } - } -#else - if (net_is_tx_q_paused(priv, queue)) { - unifi_trace(priv, UDBG2, "Queue already stopped\n"); - return; - } - net_tx_q_pause(priv, queue); -#endif -#endif #ifdef CSR_SUPPORT_SME if(queue<=3) { @@ -2108,7 +1910,6 @@ unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue) func_enter(); unifi_trace(priv, UDBG2, "Waking queue %d\n", queue); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++) { if (netif_running(priv->netdev[i])) @@ -2116,25 +1917,6 @@ unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue) netif_wake_subqueue(priv->netdev[i], (u16)queue); } } -#else -#ifdef ALLOW_Q_PAUSE - /* Need to supply queue number depending on Kernel support */ - /* Resume the traffic from all the interfaces */ - for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++) - { - if (netif_running(priv->netdev[i])) { - UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[i]); - } - } -#else - if (!(net_is_tx_q_paused(priv, queue))) { - unifi_trace(priv, UDBG2, "Queue already running\n"); - func_exit(); - return; - } - net_tx_q_unpause(priv, queue); -#endif -#endif #ifdef CSR_SUPPORT_SME if(queue <=3) { @@ -2349,13 +2131,7 @@ uf_resume_data_plane(unifi_priv_t *priv, int queue, { #ifdef CONFIG_NET_SCHED if (netif_running(priv->netdev[interfaceTag])) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) netif_tx_schedule_all(priv->netdev[interfaceTag]); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - netif_schedule_queue(netdev_get_tx_queue(priv->netdev[interfaceTag], 0)); -#else - netif_schedule(priv->netdev[interfaceTag]); -#endif /* LINUX_VERSION_CODE */ } #endif uf_process_rx_pending_queue(priv, queue, peer_address, 1,interfaceTag); @@ -2998,19 +2774,13 @@ uf_set_multicast_list(struct net_device *dev) #else u8 *mc_list = interfacePriv->mc_list; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) struct netdev_hw_addr *mc_addr; int mc_addr_count; -#else - struct dev_mc_list *p; /* Pointer to the addresses structure. */ - int i; -#endif if (priv->init_progress != UNIFI_INIT_COMPLETED) { return; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) mc_addr_count = netdev_mc_count(dev); unifi_trace(priv, UDBG3, @@ -3029,25 +2799,6 @@ uf_set_multicast_list(struct net_device *dev) mc_list += ETH_ALEN; } -#else - unifi_trace(priv, UDBG3, - "uf_set_multicast_list (count=%d)\n", dev->mc_count); - - /* Not enough space? */ - if (dev->mc_count > UNIFI_MAX_MULTICAST_ADDRESSES) { - return; - } - - /* Store the list to be processed by the work item. */ - interfacePriv->mc_list_count = dev->mc_count; - p = dev->mc_list; - for (i = 0; i < dev->mc_count; i++) { - memcpy(mc_list, p->dmi_addr, ETH_ALEN); - p = p->next; - mc_list += ETH_ALEN; - } -#endif - /* Send a message to the workqueue */ queue_work(priv->unifi_workqueue, &priv->multicast_list_task); #endif @@ -3181,375 +2932,6 @@ void uf_net_get_name(struct net_device *dev, char *name, int len) } /* uf_net_get_name */ - - - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -#ifdef CONFIG_NET_SCHED - -/* - * --------------------------------------------------------------------------- - * uf_install_qdisc - * - * Creates a root qdisc, registers our qdisc handlers and - * overrides the device's qdisc_sleeping to prevent the system - * from creating a new one for our network device. - * - * Arguments: - * dev Pointer to the network device. - * - * Returns: - * 0 on success, Linux error code otherwise. - * - * Notes: - * This function holds the qdisk lock so it needs to be called - * after registering the network device in uf_register_netdev(). - * Also, the qdisc_create_dflt() API has changed in 2.6.20 to - * include the parentid. - * --------------------------------------------------------------------------- - */ -int uf_install_qdisc(struct net_device *dev) -{ - struct Qdisc *qdisc; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - struct netdev_queue *queue0; -#endif /* LINUX_VERSION_CODE */ - - - func_enter(); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - /* - * check that there is no qdisc currently attached to device - * this ensures that we will be the root qdisc. (I can't find a better - * way to test this explicitly) - */ - if (dev->qdisc_sleeping != &noop_qdisc) { - func_exit_r(-EFAULT); - return -EINVAL; - } -#endif /* LINUX_VERSION_CODE */ - - qdisc = UF_QDISC_CREATE_DFLT(dev, &uf_qdisc_ops, TC_H_ROOT); - if (!qdisc) { - unifi_error(NULL, "%s: qdisc installation failed\n", dev->name); - func_exit_r(-EFAULT); - return -EFAULT; - } - unifi_trace(NULL, UDBG5, "%s: parent qdisc=0x%p\n", - dev->name, qdisc); - - qdisc->handle = 0x80020000; - qdisc->flags = 0x0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - queue0 = netdev_get_tx_queue(dev, 0); - if (queue0 == NULL) { - unifi_error(NULL, "%s: netdev_get_tx_queue returned no queue\n", - dev->name); - func_exit_r(-EFAULT); - return -EFAULT; - } - queue0->qdisc = qdisc; - queue0->qdisc_sleeping = qdisc; -#else - qdisc_lock_tree(dev); - list_add_tail(&qdisc->list, &dev->qdisc_list); - dev->qdisc_sleeping = qdisc; - qdisc_unlock_tree(dev); -#endif /* LINUX_VERSION_CODE */ - - func_exit_r(0); - return 0; - -} /* uf_install_qdisc() */ - -static int uf_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev_queue->dev); -#else - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev); -#endif /* LINUX_VERSION_CODE */ - unifi_priv_t *priv = interfacePriv->privPtr; - struct uf_sched_data *q = qdisc_priv(qd); - struct uf_tx_packet_data *pkt_data = (struct uf_tx_packet_data *) skb->cb; - struct ethhdr ehdr; - struct Qdisc *qdisc; - int r, proto; - - func_enter(); - - memcpy(&ehdr, skb->data, ETH_HLEN); - proto = ntohs(ehdr.h_proto); - - /* 802.1x - apply controlled/uncontrolled port rules */ - if ((proto != ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - && (proto != ETH_P_WAI) -#endif - ) { - /* queues 0 - 3 */ - pkt_data->priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); - pkt_data->queue = unifi_frame_priority_to_queue(pkt_data->priority); - } else { - pkt_data->queue = UNIFI_TRAFFIC_Q_EAPOL; - } - - qdisc = q->queues[pkt_data->queue]; - r = qdisc->enqueue(skb, qdisc); - if (r == NET_XMIT_SUCCESS) { - qd->q.qlen++; - qd->bstats.bytes += skb->len; - qd->bstats.packets++; - func_exit_r(NET_XMIT_SUCCESS); - return NET_XMIT_SUCCESS; - } - - unifi_error(priv, "uf_qdiscop_enqueue: dropped\n"); - qd->qstats.drops++; - - func_exit_r(r); - return r; - -} /* uf_qdiscop_enqueue() */ - - -static int uf_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(qd->dev_queue->dev); -#else - netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(qd->dev); -#endif /* LINUX_VERSION_CODE */ - unifi_priv_t *priv = interfacePriv->privPtr; - struct uf_sched_data *q = qdisc_priv(qd); - struct uf_tx_packet_data *pkt_data = (struct uf_tx_packet_data *) skb->cb; - struct Qdisc *qdisc; - int r; - - func_enter(); - - unifi_trace(priv, UDBG5, "uf_qdiscop_requeue: (q=%d), tag=%u\n", - pkt_data->queue, pkt_data->host_tag); - - /* we recorded which queue to use earlier! */ - qdisc = q->queues[pkt_data->queue]; - - if ((r = qdisc->ops->requeue(skb, qdisc)) == 0) { - qd->q.qlen++; - func_exit_r(0); - return 0; - } - - unifi_error(priv, "uf_qdiscop_requeue: dropped\n"); - qd->qstats.drops++; - - func_exit_r(r); - return r; -} /* uf_qdiscop_requeue() */ - -static struct sk_buff *uf_qdiscop_dequeue(struct Qdisc* qd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev_queue->dev); -#else - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(qd->dev); -#endif /* LINUX_VERSION_CODE */ - unifi_priv_t *priv = interfacePriv->privPtr; - struct uf_sched_data *q = qdisc_priv(qd); - struct sk_buff *skb; - struct Qdisc *qdisc; - int queue, i; - struct ethhdr ehdr; - struct uf_tx_packet_data *pkt_data; - CsrWifiRouterCtrlPortAction port_action; - - func_enter(); - - /* check all the queues */ - for (i = UNIFI_TRAFFIC_Q_MAX - 1; i >= 0; i--) { - - if (i != UNIFI_TRAFFIC_Q_EAPOL) { - queue = priv->prev_queue; - if (++priv->prev_queue >= UNIFI_TRAFFIC_Q_EAPOL) { - priv->prev_queue = 0; - } - } else { - queue = i; - } - -#ifndef ALLOW_Q_PAUSE - /* If queue is paused, do not dequeue */ - if (net_is_tx_q_paused(priv, queue)) { - unifi_trace(priv, UDBG5, - "uf_qdiscop_dequeue: tx queue paused (q=%d)\n", queue); - continue; - } -#endif - - qdisc = q->queues[queue]; - skb = qdisc->dequeue(qdisc); - if (skb) { - /* A packet has been dequeued, decrease the queued packets count */ - qd->q.qlen--; - - pkt_data = (struct uf_tx_packet_data *) skb->cb; - - /* Check the (un)controlled port status */ - memcpy(&ehdr, skb->data, ETH_HLEN); - - port_action = verify_port(priv - , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) ||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI == interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) - , (UNIFI_TRAFFIC_Q_EAPOL == queue? UF_UNCONTROLLED_PORT_Q: UF_CONTROLLED_PORT_Q) - , interfacePriv->InterfaceTag); - - /* Dequeue packet if port is open */ - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - unifi_trace(priv, UDBG5, - "uf_qdiscop_dequeue: new (q=%d), tag=%u\n", - queue, pkt_data->host_tag); - - func_exit(); - return skb; - } - - /* Discard or block the packet if necessary */ - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { - unifi_trace(priv, UDBG5, - "uf_qdiscop_dequeue: drop (q=%d), tag=%u\n", - queue, pkt_data->host_tag); - kfree_skb(skb); - break; - } - - /* We can not send the packet now, put it back to the queue */ - if (qdisc->ops->requeue(skb, qdisc) != 0) { - unifi_error(priv, - "uf_qdiscop_dequeue: requeue (q=%d) failed, tag=%u, drop it\n", - queue, pkt_data->host_tag); - - /* Requeue failed, drop the packet */ - kfree_skb(skb); - break; - } - /* We requeued the packet, increase the queued packets count */ - qd->q.qlen++; - - unifi_trace(priv, UDBG5, - "uf_qdiscop_dequeue: skip (q=%d), tag=%u\n", - queue, pkt_data->host_tag); - } - } - - func_exit(); - return NULL; -} /* uf_qdiscop_dequeue() */ - - -static void uf_qdiscop_reset(struct Qdisc* qd) -{ - struct uf_sched_data *q = qdisc_priv(qd); - int queue; - func_enter(); - - for (queue = 0; queue < UNIFI_TRAFFIC_Q_MAX; queue++) { - qdisc_reset(q->queues[queue]); - } - qd->q.qlen = 0; - - func_exit(); -} /* uf_qdiscop_reset() */ - - -static void uf_qdiscop_destroy(struct Qdisc* qd) -{ - struct uf_sched_data *q = qdisc_priv(qd); - int queue; - - func_enter(); - - for (queue=0; queue < UNIFI_TRAFFIC_Q_MAX; queue++) { - qdisc_destroy(q->queues[queue]); - q->queues[queue] = &noop_qdisc; - } - - func_exit(); -} /* uf_qdiscop_destroy() */ - - -/* called whenever parameters are updated on existing qdisc */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) -static int uf_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt) -#else -static int uf_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt) -#endif -{ - func_enter(); - func_exit(); - return 0; -} /* uf_qdiscop_tune() */ - - -/* called during initial creation of qdisc on device */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) -static int uf_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) -#else -static int uf_qdiscop_init(struct Qdisc *qd, struct rtattr *opt) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - struct net_device *dev = qd->dev_queue->dev; -#else - struct net_device *dev = qd->dev; -#endif /* LINUX_VERSION_CODE */ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct uf_sched_data *q = qdisc_priv(qd); - int err = 0, i; - - func_enter(); - - /* make sure we do not mess with the ingress qdisc */ - if (qd->flags & TCQ_F_INGRESS) { - func_exit(); - return -EINVAL; - } - - /* if options were passed in, set them */ - if (opt) { - err = uf_qdiscop_tune(qd, opt); - } - - /* create child queues */ - for (i = 0; i < UNIFI_TRAFFIC_Q_MAX; i++) { - q->queues[i] = UF_QDISC_CREATE_DFLT(dev, &pfifo_qdisc_ops, - qd->handle); - if (!q->queues[i]) { - q->queues[i] = &noop_qdisc; - unifi_error(priv, "%s child qdisc %i creation failed\n"); - } - - unifi_trace(priv, UDBG5, "%s: child qdisc=0x%p\n", - dev->name, q->queues[i]); - } - - func_exit_r(err); - return err; -} /* uf_qdiscop_init() */ - - -static int uf_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb) -{ - func_enter(); - func_exit_r(skb->len); - return skb->len; -} /* uf_qdiscop_dump() */ - -#endif /* CONFIG_NET_SCHED */ -#endif /* LINUX_VERSION_CODE */ - #ifdef CSR_SUPPORT_WEXT /* @@ -3595,7 +2977,7 @@ uf_netdev_event(struct notifier_block *notif, unsigned long event, void* ptr) { interfacePriv->wait_netdev_change ? "" : "not"); if (interfacePriv->wait_netdev_change) { - UF_NETIF_TX_WAKE_ALL_QUEUES(priv->netdev[interfacePriv->InterfaceTag]); + netif_tx_wake_all_queues(priv->netdev[interfacePriv->InterfaceTag]); interfacePriv->connected = UnifiConnected; interfacePriv->wait_netdev_change = FALSE; /* Note: passing the broadcast address here will allow anyone to attempt to join our adhoc network */ |