aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2008-06-08 08:25:10 -0700
committerLuis R. Rodriguez <lrodriguez@atheros.com>2008-06-08 08:25:10 -0700
commit462db84332d27fff411136cb4a32728006bb0b0e (patch)
treea72668a815662fcc8582c0847cca937edc7dcc8a
parentdb25d52921f95f6ebb275092c7fdd7e7ede35c6d (diff)
downloadcompat-wireless-2.6-old-462db84332d27fff411136cb4a32728006bb0b0e.tar.gz
Backport CONFIG_NETDEVICES_MULTIQUEUE support for older kernels.
This makes mac80211 use the old internal hacked up MQ support. Note though that unless you are using the new MQ support your kernel won't really be able to schedule individually on each separate hardware queue. This applies to any old kernel releases that don't have this patch yet, which should be <= 2.6.26. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
-rw-r--r--compat/compat.diff204
-rw-r--r--compat/compat.h61
-rw-r--r--compat/mq_compat.h92
-rw-r--r--config.mk16
-rwxr-xr-xscripts/admin-update.sh1
5 files changed, 342 insertions, 32 deletions
diff --git a/compat/compat.diff b/compat/compat.diff
index 6be9626..fee0f2d 100644
--- a/compat/compat.diff
+++ b/compat/compat.diff
@@ -209,9 +209,9 @@
LED_SCANNING = 1,
LED_ASSOCIATED = 2,
};
---- a/net/mac80211/util.c 2008-04-15 19:25:05.000000000 -0700
-+++ b/net/mac80211/util.c 2008-04-15 19:25:05.000000000 -0700
-@@ -20,9 +20,15 @@
+--- a/net/mac80211/util.c 2008-06-04 00:38:14.000000000 -0700
++++ b/net/mac80211/util.c 2008-06-08 07:31:57.000000000 -0700
+@@ -20,11 +20,20 @@
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <linux/bitmap.h>
@@ -226,7 +226,27 @@
+#endif
#include "ieee80211_i.h"
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++#include "mq_compat.h"
++#endif
#include "rate.h"
+ #include "mesh.h"
+ #include "wme.h"
+@@ -331,7 +340,14 @@
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+
++/* 2.6.22 doesn't have CONFIG_NETDEVICES_MULTIQUEUE so lets not make use
++ * of queues_pending map and use our own old hack */
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF,
++ &local->state[queue])) {
++#else
+ if (test_bit(queue, local->queues_pending)) {
++#endif
+ tasklet_schedule(&local->tx_pending_tasklet);
+ } else {
+ if (ieee80211_is_multiqueue(local)) {
--- a/drivers/net/wireless/libertas/dev.h 2008-04-15 19:25:05.000000000 -0700
+++ b/drivers/net/wireless/libertas/dev.h 2008-04-15 19:28:16.000000000 -0700
@@ -11,6 +11,7 @@
@@ -819,9 +839,9 @@
ret = dev_alloc_name(ndev, ndev->name);
if (ret < 0)
---- a/net/mac80211/tx.c 2008-06-04 01:25:08.000000000 -0700
-+++ b/net/mac80211/tx.c 2008-06-04 01:25:09.000000000 -0700
-@@ -18,7 +18,9 @@
+--- a/net/mac80211/tx.c 2008-06-04 00:38:14.000000000 -0700
++++ b/net/mac80211/tx.c 2008-06-08 06:03:45.000000000 -0700
+@@ -18,12 +18,17 @@
#include <linux/etherdevice.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
@@ -831,7 +851,73 @@
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
-@@ -1613,8 +1615,13 @@
+ #include <asm/unaligned.h>
+
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++#include "mq_compat.h" /* Internal MQ backport support for older kernels */
++#endif
+ #include "ieee80211_i.h"
+ #include "led.h"
+ #include "mesh.h"
+@@ -213,6 +218,7 @@
+ return dur;
+ }
+
++
+ static int inline is_ieee80211_device(struct net_device *dev,
+ struct net_device *master)
+ {
+@@ -665,8 +671,12 @@
+ * etc.
+ */
+ if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU ||
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ IEEE80211_SKB_CB(tx->skb)->queue >= tx->local->hw.queues))
++#else
+ skb_get_queue_mapping(tx->skb) >=
+ ieee80211_num_regular_queues(&tx->local->hw)))
++#endif
+ return TX_DROP;
+
+ first = tx->skb;
+@@ -1095,8 +1105,9 @@
+ u16 queue;
+
+ queue = skb_get_queue_mapping(skb);
+-
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23))
+ WARN_ON(test_bit(queue, local->queues_pending));
++#endif
+
+ if (unlikely(skb->len < 10)) {
+ dev_kfree_skb(skb);
+@@ -1174,7 +1185,12 @@
+
+ if (ret == IEEE80211_TX_FRAG_AGAIN)
+ skb = NULL;
++
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ set_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]);
++#else
+ set_bit(queue, local->queues_pending);
++#endif
+ smp_mb();
+ /*
+ * When the driver gets out of buffers during sending of
+@@ -1188,7 +1204,12 @@
+ * possible to have happened.
+ */
+ if (!__netif_subqueue_stopped(local->mdev, queue)) {
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ clear_bit(IEEE80211_LINK_STATE_PENDING,
++ &local->state[queue]);
++#else
+ clear_bit(queue, local->queues_pending);
++#endif
+ goto retry;
+ }
+ store->skb = skb;
+@@ -1613,8 +1634,13 @@
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
skb->dev = local->mdev;
@@ -845,8 +931,59 @@
/* Update skb pointers to various headers since this modified frame
* is going to go through Linux networking code that may potentially
---- a/net/mac80211/ieee80211_i.h 2008-06-04 01:25:08.000000000 -0700
-+++ b/net/mac80211/ieee80211_i.h 2008-06-04 01:25:09.000000000 -0700
+@@ -1646,14 +1672,24 @@
+ struct ieee80211_tx_stored_packet *store;
+
+ for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) {
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ /* XXX: Test this */
++ //if (__ieee80211_queue_stopped(local, i))
++ if (0)
++#else
+ if (!test_bit(i, local->queues_pending))
++#endif
+ continue;
+ store = &local->pending_packet[i];
+ kfree_skb(store->skb);
+ for (j = 0; j < store->num_extra_frag; j++)
+ kfree_skb(store->extra_frag[j]);
+ kfree(store->extra_frag);
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]);
++#else
+ clear_bit(i, local->queues_pending);
++#endif
+ }
+ }
+
+@@ -1674,8 +1710,11 @@
+ /* Check that this queue is ok */
+ if (__netif_subqueue_stopped(local->mdev, i))
+ continue;
+-
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ if (!__ieee80211_queue_pending(local, i)) {
++#else
+ if (!test_bit(i, local->queues_pending)) {
++#endif
+ ieee80211_wake_queue(&local->hw, i);
+ continue;
+ }
+@@ -1692,7 +1731,12 @@
+ if (ret == IEEE80211_TX_FRAG_AGAIN)
+ store->skb = NULL;
+ } else {
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ clear_bit(IEEE80211_LINK_STATE_PENDING,
++ &local->state[i]);
++#else
+ clear_bit(i, local->queues_pending);
++#endif
+ ieee80211_wake_queue(&local->hw, i);
+ }
+ }
+--- a/net/mac80211/ieee80211_i.h 2008-06-04 00:38:14.000000000 -0700
++++ b/net/mac80211/ieee80211_i.h 2008-06-08 05:49:26.000000000 -0700
@@ -406,6 +406,10 @@
struct wireless_dev wdev;
@@ -867,8 +1004,23 @@
enum {
IEEE80211_RX_MSG = 1,
---- a/net/mac80211/main.c 2008-06-04 01:25:08.000000000 -0700
-+++ b/net/mac80211/main.c 2008-06-04 01:25:09.000000000 -0700
+@@ -589,7 +593,14 @@
+ struct sta_info *sta_hash[STA_HASH_SIZE];
+ struct timer_list sta_cleanup;
+
++/* Kernels without CONFIG_NETDEVICES_MULTIQUEUE (<=2.6.22) need this, so
++ * we implement multiple queue support internally with mac80211 hacks. */
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ unsigned long state[IEEE80211_MAX_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
++#else
+ unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
++#endif
++
+ struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES];
+ struct tasklet_struct tx_pending_tasklet;
+
+--- a/net/mac80211/main.c 2008-06-04 00:38:14.000000000 -0700
++++ b/net/mac80211/main.c 2008-06-05 03:12:04.000000000 -0700
@@ -21,7 +21,9 @@
#include <linux/wireless.h>
#include <linux/rtnetlink.h>
@@ -916,3 +1068,33 @@
mdev->set_multicast_list = ieee80211_master_set_multicast_list;
sdata->vif.type = IEEE80211_IF_TYPE_AP;
+--- a/include/net/mac80211.h 2008-06-04 00:38:13.000000000 -0700
++++ b/include/net/mac80211.h 2008-06-08 05:08:41.000000000 -0700
+@@ -293,7 +293,11 @@
+ s8 tx_rate_idx;
+ u8 antenna_sel_tx;
+
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++ u8 queue; /* For compatibilty support for HT for kernels <= 2.6.22 */
++#else
+ /* 1 byte hole */
++#endif
+
+ union {
+ struct {
+@@ -323,6 +327,15 @@
+ return (struct ieee80211_tx_info *)skb->cb;
+ }
+
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
++/* Added was added as of 2.6.24 in include/linux/skbuff.h, this for old kernels,
++ * we put it here instead of compat.h as we don't want to rely on mac80211.h in
++ * compat.h */
++static inline u16 skb_get_queue_mapping(struct sk_buff *skb)
++{
++ return IEEE80211_SKB_CB(skb)->queue;
++}
++#endif
+
+ /**
+ * enum mac80211_rx_flags - receive flags
diff --git a/compat/compat.h b/compat/compat.h
index ab73c30..7acf09b 100644
--- a/compat/compat.h
+++ b/compat/compat.h
@@ -138,15 +138,45 @@ static inline void pci_clear_mwi(struct pci_dev *dev)
/* Added as of 2.6.23 in include/linux/netdevice.h */
#define alloc_netdev_mq(sizeof_priv, name, setup, queue) \
alloc_netdev(sizeof_priv, name, setup)
-#define NETIF_F_MULTI_QUEUE 0
+#define NETIF_F_MULTI_QUEUE 16384
+
+/* Added as of 2.6.23 on include/linux/netdevice.h */
+static inline int netif_is_multiqueue(const struct net_device *dev)
+{
+ return (!!(NETIF_F_MULTI_QUEUE & dev->features));
+}
+
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) */
/* Compat work for 2.6.21, 2.6.22 and 2.6.23 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
-/* Added as of 2.6.24 in include/linux/netdevice.h */
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,23)) /* Local check */
+/* Added as of 2.6.24 in include/linux/skbuff.h.
+ *
+ * Although 2.6.23 does support for CONFIG_NETDEVICES_MULTIQUEUE
+ * this helper was not added until 2.6.24. This implementation
+ * is exactly as it is on newer kernels.
+ *
+ * For older kernels we use the an internal mac80211 hack.
+ * For details see changes to include/net/mac80211.h through
+ * compat.diff and compat/mq_compat.h */
+static inline u16 skb_get_queue_mapping(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ return skb->queue_mapping;
+#else
+ return 0;
+#endif
+}
+#endif /* Local 2.6.23 check */
+/* On older kernels we handle this a bit differently, so we yield to that
+ * code for its implementation in mq_compat.h as we want to make
+ * use of the internal mac80211 __ieee80211_queue_stopped() which itself
+ * uses internal mac80211 data structure hacks. */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)) /* Local check */
/**
* netif_subqueue_stopped - test status of subqueue
* @dev: network device
@@ -165,25 +195,13 @@ static inline int __netif_subqueue_stopped(const struct net_device *dev,
#endif
}
+/* Note: although the backport implementation for netif_subqueue_stopped
+ * on older kernels is identical to upstream __netif_subqueue_stopped()
+ * (except for a const qualifier) we implement netif_subqueue_stopped()
+ * as part of mac80211 as it relies on internal mac80211 structures we
+ * use for MQ support. We this implement it in mq_compat.h */
-/* Added as of 2.6.24 in include/linux/skbuff.h.
- *
- * Although 2.6.23 does support for CONFIG_NETDEVICES_MULTIQUEUE
- * this helper was not added until 2.6.24. This implementation
- * is exactly as it is on newer kernels.
- *
- * Older kernels just use queue 0 as it didn't support
- * CONFIG_NETDEVICES_MULTIQUEUE. This added support on
- * the network stack to use multiple hardware TX queues */
-static inline u16 skb_get_queue_mapping(struct sk_buff *skb)
-{
-#ifdef CONFIG_NETDEVICES_MULTIQUEUE
- return skb->queue_mapping;
-#else
- return 0;
-#endif
-}
-
+#endif /* Local 2.6.23 check */
/*
* Force link bug if constructor is used, can't be done compatibly
@@ -320,7 +338,8 @@ int compat_is_pcie(struct pci_dev *pdev);
/* Compat work for kernels <= 2.6.22 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
-/* dev_mc_list was replaced with dev_addr_list as of 2.6.23 */
+/* dev_mc_list was replaced with dev_addr_list as of 2.6.23,
+ * only new member added is da_synced. */
#define dev_addr_list dev_mc_list
#define da_addr dmi_addr
#define da_addrlen dmi_addrlen
diff --git a/compat/mq_compat.h b/compat/mq_compat.h
new file mode 100644
index 0000000..7b33eb0
--- /dev/null
+++ b/compat/mq_compat.h
@@ -0,0 +1,92 @@
+#ifndef MAC80211_MQ_COMPAT_H
+#define MAC80211_MQ_COMPAT_H
+#include "wme.h"
+/*
+ * Copyright 2008 Luis R. Rodriguez <lrodriguez@atheros.com>
+ *
+ * CONFIG_NETDEVICES_MULTIQUEUE backport support for kernels <= 2.6.22
+ *
+ * Older kernels we use the old skb callback queue as they don't support
+ * CONFIG_NETDEVICES_MULTIQUEUE. CONFIG_NETDEVICES_MULTIQUEUE was
+ * added in the kernel to help support on the network stack multiple
+ * hardware TX queues.
+ *
+ * This is an internal mac80211 hack as its using internal mac80211 data
+ * structures to keep track of queue for the skb.
+ *
+ * Please realize there is a penalty for using this -- you don't get
+ * to schedule each hardware queue separately, so consider upgrading
+ * for better performance on 802.11n. Since this is using what we *used*
+ * to use this also of course means older kernels that weren't using MQ
+ * support for 802.11n are also affected. This means <= 2.6.26.
+ */
+
+#define IEEE80211_DEV_TO_LOCAL(dev) \
+ ((struct ieee80211_local *)(IEEE80211_DEV_TO_SUB_IF(dev))->local)
+
+/* This was stripped out after MQ patch for mac80211, let bring it
+ * back to life */
+enum ieee80211_link_state_t {
+ IEEE80211_LINK_STATE_XOFF = 0,
+ IEEE80211_LINK_STATE_PENDING,
+};
+
+/* Note: skb_get_queue_mapping() was added as of 2.6.24 in
+ * include/linux/skbuff.h. We port this and add it into
+ * include/net/mac80211.h through compat.diff as this could
+ * be used by mac80211 drivers as well. We don't add it to
+ * compat.h as we don't want things which require on
+ * mac80211.h in compat.h */
+
+/* These are helpers which used to be in mac80211 prior to
+ * CONFIG_NETDEVICES_MULTIQUEUE being demanded for CONFIG_MAC80211_QOS
+ * The way we fix this for older kernels is resort to the old work. */
+static inline int __ieee80211_queue_stopped(struct ieee80211_local *local,
+ int queue)
+{
+ return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+
+static inline int __ieee80211_queue_pending(const struct ieee80211_local *local,
+ int queue)
+{
+ return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]);
+}
+
+/* Internal mac80211 hack, note we remove "const" qualifier to net_device
+ * to make compiler shutup as <= 2.6.22 doesn't set net_device as const on
+ * netdev_priv() */
+static inline int __netif_subqueue_stopped(struct net_device *dev,
+ u16 queue_index)
+{
+ return __ieee80211_queue_stopped(IEEE80211_DEV_TO_LOCAL(dev), queue_index);
+}
+
+static inline int netif_subqueue_stopped(struct net_device *dev,
+ struct sk_buff *skb)
+{
+ return __netif_subqueue_stopped(dev, skb_get_queue_mapping(skb));
+}
+
+/* we port this with the penalty performance that we schedule all queues
+ * as well, this isn't exactly MQ support :). We port this to let
+ * our compat.diff be smaller as well.
+ * XXX: We can probably just run __netif_schedule() here */
+static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
+{
+ if (!ieee80211_qdisc_installed(dev)) {
+ if (queue_index == 0)
+ netif_wake_queue(dev);
+ } else
+ __netif_schedule(dev);
+}
+
+/* Backport to use old internal mac80211 queue state. "const" qualifier
+ * remvoved as netdev_priv() doesn't pass us a const in older kernels. */
+static inline void netif_stop_subqueue(struct net_device *dev, u16 queue_index)
+{
+ set_bit(IEEE80211_LINK_STATE_XOFF,
+ &IEEE80211_DEV_TO_LOCAL(dev)->state[queue_index]);
+}
+
+#endif /* MAC80211_MQ_COMPAT_H */
diff --git a/config.mk b/config.mk
index 69edfc0..aeb8241 100644
--- a/config.mk
+++ b/config.mk
@@ -16,6 +16,22 @@ endif
# Wireless subsystem stuff
CONFIG_MAC80211=m
+# Enable QOS for 2.6.22, we'll do some hacks here to enable it.
+# You will need this for HT support (802.11n).
+# If you are >= 2.6.23 we'll only warn when you don't have MQ support
+# enabled, but maybe we should just exit, as I suspect everyone using
+# this package may want it enabled... hmm
+ifeq ($(shell test -e $(KLIB_BUILD)/Makefile && echo yes),yes)
+KERNEL_SUBLEVEL = $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^2\.6\.\([0-9]\+\).*/\1/p')
+ifeq ($(shell test $(KERNEL_SUBLEVEL) -lt 23 && echo yes),yes)
+MAC80211_QOS=m
+else
+ifneq ($(CONFIG_NETDEVICES_MULTIQUEUE),)
+$(warning "WARNING: You are running a kernel >= 2.6.23, you should enable CONFIG_NETDEVICES_MULTIQUEUE for 802.11n support")
+endif
+endif
+endif
+
CONFIG_MAC80211_RC_DEFAULT=pid
CONFIG_MAC80211_RC_PID=y
diff --git a/scripts/admin-update.sh b/scripts/admin-update.sh
index 8277bfd..baa0390 100755
--- a/scripts/admin-update.sh
+++ b/scripts/admin-update.sh
@@ -147,6 +147,7 @@ cp -a $GIT_TREE/$DIR $DIR
# Compat stuff
cp compat/compat.c net/wireless/
cp compat/compat.h include/net/
+cp compat/mq_compat.h net/mac80211/
patch -p1 -N -t < compat/compat.diff
RET=$?