#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
+#include <linux/pci.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+
/* rfkill notification chain */
#define RFKILL_STATE_CHANGED 0x0001 /* state of a normal rfkill
switch has changed */
-static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
+/*
+ * e5899e1b7d73e67de758a32174a859cc2586c0b9 made pci_pme_capable() external,
+ * it was defined internally, some drivers want access to this information.
+ */
/**
- * register_rfkill_notifier - Add notifier to rfkill notifier chain
- * @nb: pointer to the new entry to add to the chain
- *
- * See blocking_notifier_chain_register() for return value and further
- * observations.
- *
- * Adds a notifier to the rfkill notifier chain. The chain will be
- * called with a pointer to the relevant rfkill structure as a parameter,
- * refer to include/linux/rfkill.h for the possible events.
- *
- * Notifiers added to this chain are to always return NOTIFY_DONE. This
- * chain is a blocking notifier chain: notifiers can sleep.
- *
- * Calls to this chain may have been done through a workqueue. One must
- * assume unordered asynchronous behaviour, there is no way to know if
- * actions related to the event that generated the notification have been
- * carried out already.
+ * pci_pme_capable - check the capability of PCI device to generate PME#
+ * @dev: PCI device to handle.
+ * @state: PCI state from which device will issue PME#.
*/
-int register_rfkill_notifier(struct notifier_block *nb)
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
{
- return blocking_notifier_chain_register(&rfkill_notifier_list, nb);
+ if (!dev->pm_cap)
+ return false;
+
+ return !!(dev->pme_support & (1 << state));
}
-EXPORT_SYMBOL_GPL(register_rfkill_notifier);
/**
- * unregister_rfkill_notifier - remove notifier from rfkill notifier chain
- * @nb: pointer to the entry to remove from the chain
+ * mmc_align_data_size - pads a transfer size to a more optimal value
+ * @card: the MMC card associated with the data transfer
+ * @sz: original transfer size
+ *
+ * Pads the original data size with a number of extra bytes in
+ * order to avoid controller bugs and/or performance hits
+ * (e.g. some controllers revert to PIO for certain sizes).
*
- * See blocking_notifier_chain_unregister() for return value and further
- * observations.
+ * Returns the improved size, which might be unmodified.
*
- * Removes a notifier from the rfkill notifier chain.
+ * Note that this function is only relevant when issuing a
+ * single scatter gather entry.
*/
-int unregister_rfkill_notifier(struct notifier_block *nb)
+unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
{
- return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_rfkill_notifier);
-
-
-static void notify_rfkill_state_change(struct rfkill *rfkill)
-{
- blocking_notifier_call_chain(&rfkill_notifier_list,
- RFKILL_STATE_CHANGED,
- rfkill);
+ /*
+ * FIXME: We don't have a system for the controller to tell
+ * the core about its problems yet, so for now we just 32-bit
+ * align the size.
+ */
+ sz = ((sz + 3) / 4) * 4;
+
+ return sz;
}
+EXPORT_SYMBOL(mmc_align_data_size);
/**
- * rfkill_force_state - Force the internal rfkill radio state
- * @rfkill: pointer to the rfkill class to modify.
- * @state: the current radio state the class should be forced to.
+ * sdio_align_size - pads a transfer size to a more optimal value
+ * @func: SDIO function
+ * @sz: original transfer size
+ *
+ * Pads the original data size with a number of extra bytes in
+ * order to avoid controller bugs and/or performance hits
+ * (e.g. some controllers revert to PIO for certain sizes).
*
- * This function updates the internal state of the radio cached
- * by the rfkill class. It should be used when the driver gets
- * a notification by the firmware/hardware of the current *real*
- * state of the radio rfkill switch.
+ * If possible, it will also adjust the size so that it can be
+ * handled in just a single request.
*
- * It may not be called from an atomic context.
+ * Returns the improved size, which might be unmodified.
*/
-int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
+unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
{
- enum rfkill_state oldstate;
-
- if (state != RFKILL_STATE_SOFT_BLOCKED &&
- state != RFKILL_STATE_UNBLOCKED &&
- state != RFKILL_STATE_HARD_BLOCKED)
- return -EINVAL;
-
- mutex_lock(&rfkill->mutex);
-
- oldstate = rfkill->state;
- rfkill->state = state;
-
- if (state != oldstate)
- notify_rfkill_state_change(rfkill);
-
- mutex_unlock(&rfkill->mutex);
-
- return 0;
+ unsigned int orig_sz;
+ unsigned int blk_sz, byte_sz;
+ unsigned chunk_sz;
+
+ orig_sz = sz;
+
+ /*
+ * Do a first check with the controller, in case it
+ * wants to increase the size up to a point where it
+ * might need more than one block.
+ */
+ sz = mmc_align_data_size(func->card, sz);
+
+ /*
+ * If we can still do this with just a byte transfer, then
+ * we're done.
+ */
+ if (sz <= sdio_max_byte_size(func))
+ return sz;
+
+ if (func->card->cccr.multi_block) {
+ /*
+ * Check if the transfer is already block aligned
+ */
+ if ((sz % func->cur_blksize) == 0)
+ return sz;
+
+ /*
+ * Realign it so that it can be done with one request,
+ * and recheck if the controller still likes it.
+ */
+ blk_sz = ((sz + func->cur_blksize - 1) /
+ func->cur_blksize) * func->cur_blksize;
+ blk_sz = mmc_align_data_size(func->card, blk_sz);
+
+ /*
+ * This value is only good if it is still just
+ * one request.
+ */
+ if ((blk_sz % func->cur_blksize) == 0)
+ return blk_sz;
+
+ /*
+ * We failed to do one request, but at least try to
+ * pad the remainder properly.
+ */
+ byte_sz = mmc_align_data_size(func->card,
+ sz % func->cur_blksize);
+ if (byte_sz <= sdio_max_byte_size(func)) {
+ blk_sz = sz / func->cur_blksize;
+ return blk_sz * func->cur_blksize + byte_sz;
+ }
+ } else {
+ /*
+ * We need multiple requests, so first check that the
+ * controller can handle the chunk size;
+ */
+ chunk_sz = mmc_align_data_size(func->card,
+ sdio_max_byte_size(func));
+ if (chunk_sz == sdio_max_byte_size(func)) {
+ /*
+ * Fix up the size of the remainder (if any)
+ */
+ byte_sz = orig_sz % chunk_sz;
+ if (byte_sz) {
+ byte_sz = mmc_align_data_size(func->card,
+ byte_sz);
+ }
+
+ return (orig_sz / chunk_sz) * chunk_sz + byte_sz;
+ }
+ }
+
+ /*
+ * The controller is simply incapable of transferring the size
+ * we want in decent manner, so just return the original size.
+ */
+ return orig_sz;
}
-EXPORT_SYMBOL(rfkill_force_state);
+EXPORT_SYMBOL_GPL(sdio_align_size);
+
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) */
#include <linux/list.h>
#include <linux/rfkill.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+
+#include <asm-generic/bug.h>
+
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
+
+/*
+ * The net_device has a spin_lock on newer kernels, on older kernels we're out of luck
+ */
+#define netif_addr_lock_bh
+#define netif_addr_unlock_bh
+
+/*
+ * To port this properly we'd have to port warn_slowpath_null(),
+ * which I'm lazy to do so just do a regular print for now. If you
+ * want to port this read kernel/panic.c
+ */
+#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0)
+
+/* This is ported directly as-is on newer kernels */
+#ifndef WARN
+#define WARN(condition, format...) ({ \
+ int __ret_warn_on = !!(condition); \
+ if (unlikely(__ret_warn_on)) \
+ __WARN_printf(format); \
+ unlikely(__ret_warn_on); \
+})
+#endif
+
+/* On 2.6.27 a second argument was added, on older kernels we ignore it */
+#define dma_mapping_error(pdev, dma_addr) dma_mapping_error(dma_addr)
+#define pci_dma_mapping_error(pdev, dma_addr) dma_mapping_error(pdev, dma_addr)
/* This is from include/linux/rfkill.h */
#define RFKILL_STATE_SOFT_BLOCKED RFKILL_STATE_OFF
}
}
+extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
+extern unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz);
+
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)) */
#endif /* LINUX_26_27_COMPAT_H */
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
net->ethtool_ops = &usbnet_ethtool_ops;
---- a/net/wireless/Makefile 2009-07-06 10:20:59.511191302 -0700
-+++ b/net/wireless/Makefile 2009-07-06 10:28:11.310193540 -0700
-@@ -1,11 +1,17 @@
+--- a/net/wireless/Makefile 2009-07-06 15:04:31.423241610 -0700
++++ b/net/wireless/Makefile 2009-07-06 14:58:11.298205326 -0700
+@@ -1,4 +1,3 @@
-obj-$(CONFIG_WIRELESS_EXT) += wext.o
obj-$(CONFIG_CFG80211) += cfg80211.o
obj-$(CONFIG_LIB80211) += lib80211.o
obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
- obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
+@@ -6,6 +5,14 @@
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o
+
+# Compat-wireless kernel compatibility code
++cfg80211-y += compat-2.6.27.o
+cfg80211-y += compat-2.6.28.o
+cfg80211-y += compat-2.6.29.o
+cfg80211-y += compat-2.6.30.o
obj-$(CONFIG_LIBERTAS) += libertas/
obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
+--- a/drivers/net/wireless/p54/p54usb.c 2009-07-06 16:05:47.263198670 -0700
++++ b/drivers/net/wireless/p54/p54usb.c 2009-07-06 16:06:32.298597357 -0700
+@@ -1049,7 +1049,9 @@
+ .resume = p54u_resume,
+ .reset_resume = p54u_resume,
+ #endif /* CONFIG_PM */
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+ .soft_unbind = 1,
++#endif
+ };
+
+ static int __init p54u_init(void)
+--- a/drivers/net/wireless/zd1211rw/zd_chip.h 2009-07-06 16:09:14.934197004 -0700
++++ b/drivers/net/wireless/zd1211rw/zd_chip.h 2009-07-06 16:10:01.570226234 -0700
+@@ -897,9 +897,9 @@
+ int zd_chip_unlock_phy_regs(struct zd_chip *chip);
+
+ enum led_status {
+- LED_OFF = 0,
+- LED_SCANNING = 1,
+- LED_ASSOCIATED = 2,
++ ZD_LED_OFF = 0,
++ ZD_LED_SCANNING = 1,
++ ZD_LED_ASSOCIATED = 2,
+ };
+
+ int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
+--- a/drivers/net/wireless/zd1211rw/zd_chip.c 2009-07-06 16:09:24.986198445 -0700
++++ b/drivers/net/wireless/zd1211rw/zd_chip.c 2009-07-06 16:10:19.898624742 -0700
+@@ -1278,11 +1278,11 @@
+ other_led = chip->link_led == LED1 ? LED2 : LED1;
+
+ switch (status) {
+- case LED_OFF:
++ case ZD_LED_OFF:
+ ioreqs[0].value = FW_LINK_OFF;
+ ioreqs[1].value = v[1] & ~(LED1|LED2);
+ break;
+- case LED_SCANNING:
++ case ZD_LED_SCANNING:
+ ioreqs[0].value = FW_LINK_OFF;
+ ioreqs[1].value = v[1] & ~other_led;
+ if (get_seconds() % 3 == 0) {
+@@ -1291,7 +1291,7 @@
+ ioreqs[1].value |= chip->link_led;
+ }
+ break;
+- case LED_ASSOCIATED:
++ case ZD_LED_ASSOCIATED:
+ ioreqs[0].value = FW_LINK_TX;
+ ioreqs[1].value = v[1] & ~other_led;
+ ioreqs[1].value |= chip->link_led;
+--- a/drivers/net/wireless/zd1211rw/zd_mac.c 2009-07-06 16:09:30.382198435 -0700
++++ b/drivers/net/wireless/zd1211rw/zd_mac.c 2009-07-06 16:11:36.778629948 -0700
+@@ -1013,7 +1013,7 @@
+ spin_unlock_irq(&mac->lock);
+
+ r = zd_chip_control_leds(chip,
+- is_associated ? LED_ASSOCIATED : LED_SCANNING);
++ is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
+ if (r)
+ dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
+
+@@ -1038,5 +1038,5 @@
+ 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, ZD_LED_OFF);
+ }