aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@winlab.rutgers.edu>2008-02-19 17:41:50 -0500
committerLuis R. Rodriguez <mcgrof@winlab.rutgers.edu>2008-02-19 17:41:50 -0500
commit8ac2bab6887c748e61836dac5763669770c2e316 (patch)
tree7039c2360607ad078826d239b6ec08bea427207b
parent8bdc53cb4d6477f0c76a81ed054208019c52018b (diff)
downloadcompat-wireless-2.6-old-8ac2bab6887c748e61836dac5763669770c2e316.tar.gz
Enable led support, port pm_qos_params support. PID rate control algorithm
is now enabled as default as 'simple' is scheduled for removal for 2.6.26. b43 driver now gets leds support. This should get some testing. This was tested on 2.6.25. On 2.6.24-4-generic on ubuntu I was having issues with the modules not being installed on the /lib/modules/`uname -r`/updates dir, still looking into this but pushing out changes for now. Work based on Hauke Mehrtens's patch. Signed-off-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
-rw-r--r--Makefile2
-rw-r--r--compat/compat.c242
-rw-r--r--compat/compat.diff93
-rw-r--r--compat/compat.h54
-rw-r--r--config.mk13
-rwxr-xr-xscripts/admin-update.sh4
6 files changed, 355 insertions, 53 deletions
diff --git a/Makefile b/Makefile
index f64f2f0..3b6f0b5 100644
--- a/Makefile
+++ b/Makefile
@@ -52,7 +52,7 @@ $(CREL_CHECK):
@md5sum $(COMPAT_CONFIG) > $(CONFIG_CHECK)
install: uninstall modules
- @$(MAKE) -C $(KLIB_BUILD) M=$(PWD) $(KMODDIR_ARG) $(KMODPATH_ARG) \
+ $(MAKE) -C $(KLIB_BUILD) M=$(PWD) $(KMODDIR_ARG) $(KMODPATH_ARG) \
modules_install
@# All the scripts we can use
@mkdir -p /usr/lib/compat-wireless/
diff --git a/compat/compat.c b/compat/compat.c
index b15b519..5b172a7 100644
--- a/compat/compat.c
+++ b/compat/compat.c
@@ -9,17 +9,241 @@
* The headers don't need to be modified as we're simply adding them.
*/
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/netpoll.h>
-#include <linux/rtnetlink.h>
-#include <linux/audit.h>
-#include <linux/workqueue.h>
-#include <linux/pci.h>
-#include <net/arp.h>
#include <net/compat.h>
+/* All things not in 2.6.22, 2.6.23 and 2.6.24 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
+
+/* Backport work for QoS dependencies (kernel/pm_qos_params.c)
+ * ipw2100 now makes use of
+ * pm_qos_add_requirement(),
+ * pm_qos_update_requirement() and
+ * pm_qos_remove_requirement() from it
+ *
+ * */
+
+/*
+ * locking rule: all changes to target_value or requirements or notifiers lists
+ * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
+ * held, taken with _irqsave. One lock to rule them all
+ */
+struct requirement_list {
+ struct list_head list;
+ union {
+ s32 value;
+ s32 usec;
+ s32 kbps;
+ };
+ char *name;
+};
+
+static s32 max_compare(s32 v1, s32 v2);
+static s32 min_compare(s32 v1, s32 v2);
+
+struct pm_qos_object {
+ struct requirement_list requirements;
+ struct blocking_notifier_head *notifiers;
+ struct miscdevice pm_qos_power_miscdev;
+ char *name;
+ s32 default_value;
+ s32 target_value;
+ s32 (*comparitor)(s32, s32);
+};
+
+static struct pm_qos_object null_pm_qos;
+static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
+static struct pm_qos_object cpu_dma_pm_qos = {
+ .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
+ .notifiers = &cpu_dma_lat_notifier,
+ .name = "cpu_dma_latency",
+ .default_value = 2000 * USEC_PER_SEC,
+ .target_value = 2000 * USEC_PER_SEC,
+ .comparitor = min_compare
+};
+
+static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
+static struct pm_qos_object network_lat_pm_qos = {
+ .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
+ .notifiers = &network_lat_notifier,
+ .name = "network_latency",
+ .default_value = 2000 * USEC_PER_SEC,
+ .target_value = 2000 * USEC_PER_SEC,
+ .comparitor = min_compare
+};
+
+
+static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
+static struct pm_qos_object network_throughput_pm_qos = {
+ .requirements =
+ {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
+ .notifiers = &network_throughput_notifier,
+ .name = "network_throughput",
+ .default_value = 0,
+ .target_value = 0,
+ .comparitor = max_compare
+};
+
+
+static struct pm_qos_object *pm_qos_array[] = {
+ &null_pm_qos,
+ &cpu_dma_pm_qos,
+ &network_lat_pm_qos,
+ &network_throughput_pm_qos
+};
+
+static DEFINE_SPINLOCK(pm_qos_lock);
+
+/* static helper functions */
+static s32 max_compare(s32 v1, s32 v2)
+{
+ return max(v1, v2);
+}
+
+static s32 min_compare(s32 v1, s32 v2)
+{
+ return min(v1, v2);
+}
+
+static void update_target(int target)
+{
+ s32 extreme_value;
+ struct requirement_list *node;
+ unsigned long flags;
+ int call_notifier = 0;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ extreme_value = pm_qos_array[target]->default_value;
+ list_for_each_entry(node,
+ &pm_qos_array[target]->requirements.list, list) {
+ extreme_value = pm_qos_array[target]->comparitor(
+ extreme_value, node->value);
+ }
+ if (pm_qos_array[target]->target_value != extreme_value) {
+ call_notifier = 1;
+ pm_qos_array[target]->target_value = extreme_value;
+ pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
+ pm_qos_array[target]->target_value);
+ }
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+
+ if (call_notifier)
+ blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
+ (unsigned long) extreme_value, NULL);
+}
+
+
+/**
+ * pm_qos_add_requirement - inserts new qos request into the list
+ * @pm_qos_class: identifies which list of qos request to us
+ * @name: identifies the request
+ * @value: defines the qos request
+ *
+ * This function inserts a new entry in the pm_qos_class list of requested qos
+ * performance charactoistics. It recomputes the agregate QoS expectations for
+ * the pm_qos_class of parrameters.
+ */
+int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
+{
+ struct requirement_list *dep;
+ unsigned long flags;
+
+ dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
+ if (dep) {
+ if (value == PM_QOS_DEFAULT_VALUE)
+ dep->value = pm_qos_array[pm_qos_class]->default_value;
+ else
+ dep->value = value;
+ dep->name = kstrdup(name, GFP_KERNEL);
+ if (!dep->name)
+ goto cleanup;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ list_add(&dep->list,
+ &pm_qos_array[pm_qos_class]->requirements.list);
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+ update_target(pm_qos_class);
+
+ return 0;
+ }
+
+cleanup:
+ kfree(dep);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
+
+/**
+ * pm_qos_update_requirement - modifies an existing qos request
+ * @pm_qos_class: identifies which list of qos request to us
+ * @name: identifies the request
+ * @value: defines the qos request
+ *
+ * Updates an existing qos requierement for the pm_qos_class of parameters along
+ * with updating the target pm_qos_class value.
+ *
+ * If the named request isn't in the lest then no change is made.
+ */
+int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
+{
+ unsigned long flags;
+ struct requirement_list *node;
+ int pending_update = 0;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ list_for_each_entry(node,
+ &pm_qos_array[pm_qos_class]->requirements.list, list) {
+ if (strcmp(node->name, name) == 0) {
+ if (new_value == PM_QOS_DEFAULT_VALUE)
+ node->value =
+ pm_qos_array[pm_qos_class]->default_value;
+ else
+ node->value = new_value;
+ pending_update = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+ if (pending_update)
+ update_target(pm_qos_class);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
+
+/**
+ * pm_qos_remove_requirement - modifies an existing qos request
+ * @pm_qos_class: identifies which list of qos request to us
+ * @name: identifies the request
+ *
+ * Will remove named qos request from pm_qos_class list of parrameters and
+ * recompute the current target value for the pm_qos_class.
+ */
+void pm_qos_remove_requirement(int pm_qos_class, char *name)
+{
+ unsigned long flags;
+ struct requirement_list *node;
+ int pending_update = 0;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ list_for_each_entry(node,
+ &pm_qos_array[pm_qos_class]->requirements.list, list) {
+ if (strcmp(node->name, name) == 0) {
+ kfree(node->name);
+ list_del(&node->list);
+ kfree(node);
+ pending_update = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+ if (pending_update)
+ update_target(pm_qos_class);
+}
+EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
+
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) */
+
/* All things not in 2.6.22 and 2.6.23 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
diff --git a/compat/compat.diff b/compat/compat.diff
index c857ea2..a3ba919 100644
--- a/compat/compat.diff
+++ b/compat/compat.diff
@@ -250,16 +250,6 @@
obj-$(CONFIG_CFG80211) += cfg80211.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
---- a/net/mac80211/Makefile 2008-01-26 19:37:05.000000000 -0500
-+++ b/net/mac80211/Makefile 2008-01-26 19:37:05.000000000 -0500
-@@ -26,6 +26,7 @@
- tx.o \
- key.o \
- util.o \
-+ compat.o \
- event.o
-
- mac80211-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
--- a/drivers/net/wireless/adm8211.c 2008-01-26 19:37:05.000000000 -0500
+++ b/drivers/net/wireless/adm8211.c 2008-01-26 19:37:05.000000000 -0500
@@ -143,7 +143,11 @@
@@ -586,28 +576,6 @@
obj-$(CONFIG_LIBERTAS) += libertas/
rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
---- a/net/mac80211/ieee80211.c 2008-02-06 14:28:58.000000000 -0500
-+++ b/net/mac80211/ieee80211.c 2008-02-06 14:28:58.000000000 -0500
-@@ -21,7 +21,9 @@
- #include <linux/wireless.h>
- #include <linux/rtnetlink.h>
- #include <linux/bitmap.h>
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
- #include <net/net_namespace.h>
-+#endif
- #include <net/cfg80211.h>
-
- #include "ieee80211_i.h"
-@@ -1455,7 +1457,9 @@
- mdev->open = ieee80211_master_open;
- mdev->stop = ieee80211_master_stop;
- mdev->type = ARPHRD_IEEE80211;
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
- mdev->header_ops = &ieee80211_header_ops;
-+#endif
- mdev->set_multicast_list = ieee80211_master_set_multicast_list;
-
- sdata->vif.type = IEEE80211_IF_TYPE_AP;
--- a/drivers/misc/Makefile 2008-02-15 16:29:43.000000000 -0500
+++ b/drivers/misc/Makefile 2008-02-15 16:29:24.000000000 -0500
@@ -3,22 +3,4 @@
@@ -633,3 +601,64 @@
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
-obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
-obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
+--- a/drivers/net/wireless/zd1211rw/zd_chip.c 2008-02-15 16:29:43.000000000 -0500
++++ b/drivers/net/wireless/zd1211rw/zd_chip.c 2008-02-15 16:29:43.000000000 -0500
+@@ -1280,7 +1280,7 @@ int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
+ other_led = chip->link_led == LED1 ? LED2 : LED1;
+
+ switch (status) {
+- case LED_OFF:
++ case LED_OFF_ZD:
+ ioreqs[0].value = FW_LINK_OFF;
+ ioreqs[1].value = v[1] & ~(LED1|LED2);
+ break;
+--- a/drivers/net/wireless/zd1211rw/zd_chip.h 2008-02-15 16:29:43.000000000 -0500
++++ b/drivers/net/wireless/zd1211rw/zd_chip.h 2008-02-15 16:29:43.000000000 -0500
+@@ -890,7 +890,7 @@ int zd_chip_lock_phy_regs(struct zd_chip *chip);
+ int zd_chip_unlock_phy_regs(struct zd_chip *chip);
+
+ enum led_status {
+- LED_OFF = 0,
++ LED_OFF_ZD = 0,
+ LED_SCANNING = 1,
+ LED_ASSOCIATED = 2,
+ };
+--- a/drivers/net/wireless/zd1211rw/zd_mac.c 2008-02-15 16:29:43.000000000 -0500
++++ b/drivers/net/wireless/zd1211rw/zd_mac.c 2008-02-15 16:29:43.000000000 -0500
+@@ -965,5 +965,5 @@ static void housekeeping_disable(struct zd_mac *mac)
+ dev_dbg_f(zd_mac_dev(mac), "\n");
+ cancel_rearming_delayed_workqueue(zd_workqueue,
+ &mac->housekeeping.link_led_work);
+- zd_chip_control_leds(&mac->chip, LED_OFF);
++ zd_chip_control_leds(&mac->chip, LED_OFF_ZD);
+ }
+--- a/net/mac80211/ieee80211.c 2008-02-19 10:29:53.000000000 -0500
++++ b/net/mac80211/ieee80211.c 2008-02-19 10:29:55.000000000 -0500
+@@ -21,7 +21,9 @@
+ #include <linux/wireless.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/bitmap.h>
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ #include <net/net_namespace.h>
++#endif
+ #include <net/cfg80211.h>
+
+ #include "ieee80211_i.h"
+@@ -1458,7 +1460,9 @@
+ mdev->open = ieee80211_master_open;
+ mdev->stop = ieee80211_master_stop;
+ mdev->type = ARPHRD_IEEE80211;
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ mdev->header_ops = &ieee80211_header_ops;
++#endif
+ mdev->set_multicast_list = ieee80211_master_set_multicast_list;
+
+ sdata->vif.type = IEEE80211_IF_TYPE_AP;
+--- a/net/wireless/Makefile 2008-02-19 17:13:07.000000000 -0500
++++ b/net/wireless/Makefile 2008-02-19 17:13:19.000000000 -0500
+@@ -1,4 +1,4 @@
+ obj-$(CONFIG_CFG80211) += cfg80211.o
+
+-cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
++cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o compat.o
+ cfg80211-$(CONFIG_NL80211) += nl80211.o
diff --git a/compat/compat.h b/compat/compat.h
index b438a5a..2644c95 100644
--- a/compat/compat.h
+++ b/compat/compat.h
@@ -3,12 +3,36 @@
#include <linux/autoconf.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/netpoll.h>
+#include <linux/rtnetlink.h>
+#include <linux/audit.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/genetlink.h>
-#include <net/neighbour.h>
-#include <linux/version.h>
#include <linux/scatterlist.h>
#include <linux/usb.h>
+#include <linux/hw_random.h>
+#include <linux/leds.h>
+#include <linux/pm_qos_params.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+
+#include <net/arp.h>
+#include <net/neighbour.h>
+
#include <linux/compat_autoconf.h>
/* Compat work for 2.6.22 and 2.6.23 */
@@ -17,7 +41,7 @@
/* From include/linux/mod_devicetable.h */
/* SSB core, see drivers/ssb/ */
-#ifndef CONFIG_SSB
+#ifndef SSB_DEVICE
struct ssb_device_id {
__u16 vendor;
__u16 coreid;
@@ -190,4 +214,28 @@ static inline void set_freezable(void) {}
#endif /* CONFIG_PM_SLEEP */
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) */
+
+/* Compat work for 2.6.24 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
+
+/* 2.6.25 changes hwrng_unregister()'s behaviour by supporting
+ * suspend of its parent device (the misc device, which is itself the
+ * hardware random number generator). It does this by passing a parameter to
+ * unregister_miscdev() which is not supported in older kernels. The suspend
+ * parameter allows us to enable access to the device's hardware
+ * number generator during suspend. As far as wireless is concerned this means
+ * if a driver goes to suspend it you won't have the HNR available in
+ * older kernels. */
+static inline void __hwrng_unregister(struct hwrng *rng, bool suspended)
+{
+ hwrng_unregister(rng);
+}
+
+static inline void led_classdev_unregister_suspended(struct led_classdev *lcd)
+{
+ led_classdev_unregister(lcd);
+}
+
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)) */
#endif /* LINUX_26_COMPAT_H */
diff --git a/config.mk b/config.mk
index 58c3419..5edb1a0 100644
--- a/config.mk
+++ b/config.mk
@@ -4,11 +4,12 @@ export
# Wireless subsystem stuff
CONFIG_MAC80211=m
-CONFIG_MAC80211_RC_DEFAULT=simple
-CONFIG_MAC80211_RC_SIMPLE=y
-# Comment above and uncomment below to use rate pid
-#CONFIG_MAC80211_RC_DEFAULT=pid
-#CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_DEFAULT=pid
+CONFIG_MAC80211_RC_PID=y
+# Comment above and uncomment below if you are having issues with
+# the rate pid control algorithm.
+#CONFIG_MAC80211_RC_DEFAULT=simple
+#CONFIG_MAC80211_RC_SIMPLE=y
CONFIG_CFG80211=m
CONFIG_NL80211=y
@@ -30,7 +31,7 @@ CONFIG_B43_DMA_AND_PIO_MODE=y
CONFIG_B43_PCI_AUTOSELECT=y
CONFIG_B43_PCICORE_AUTOSELECT=y
#CONFIG_B43_RFKILL=n
-#CONFIG_B43_LEDS=n
+CONFIG_B43_LEDS=y
# CONFIG_B43_DEBUG is not set
CONFIG_B43LEGACY=m
diff --git a/scripts/admin-update.sh b/scripts/admin-update.sh
index 5f6e9e1..76423b4 100755
--- a/scripts/admin-update.sh
+++ b/scripts/admin-update.sh
@@ -18,7 +18,7 @@
GIT_URL="git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git"
INCLUDE_LINUX="ieee80211.h nl80211.h wireless.h"
-INCLUDE_LINUX="$INCLUDE_LINUX pci_ids.h bitops.h eeprom_93cx6.h"
+INCLUDE_LINUX="$INCLUDE_LINUX pci_ids.h bitops.h eeprom_93cx6.h pm_qos_params.h"
# For rndis_wext
INCLUDE_LINUX_USB="usbnet.h rndis_host.h"
@@ -139,7 +139,7 @@ done
cp $GIT_TREE/$DIR/Makefile $DIR
# Compat stuff
-cp compat/compat.c net/mac80211/
+cp compat/compat.c net/wireless/
cp compat/compat.h include/net/
patch -p1 -N -t < compat/compat.diff